graphql 1.11.3 → 1.12.0

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 (180) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/core.rb +8 -0
  3. data/lib/generators/graphql/install_generator.rb +5 -5
  4. data/lib/generators/graphql/object_generator.rb +2 -0
  5. data/lib/generators/graphql/relay_generator.rb +63 -0
  6. data/lib/generators/graphql/templates/base_argument.erb +2 -0
  7. data/lib/generators/graphql/templates/base_connection.erb +8 -0
  8. data/lib/generators/graphql/templates/base_edge.erb +8 -0
  9. data/lib/generators/graphql/templates/base_enum.erb +2 -0
  10. data/lib/generators/graphql/templates/base_field.erb +2 -0
  11. data/lib/generators/graphql/templates/base_input_object.erb +2 -0
  12. data/lib/generators/graphql/templates/base_interface.erb +2 -0
  13. data/lib/generators/graphql/templates/base_mutation.erb +2 -0
  14. data/lib/generators/graphql/templates/base_object.erb +2 -0
  15. data/lib/generators/graphql/templates/base_scalar.erb +2 -0
  16. data/lib/generators/graphql/templates/base_union.erb +2 -0
  17. data/lib/generators/graphql/templates/enum.erb +2 -0
  18. data/lib/generators/graphql/templates/graphql_controller.erb +2 -0
  19. data/lib/generators/graphql/templates/interface.erb +2 -0
  20. data/lib/generators/graphql/templates/loader.erb +2 -0
  21. data/lib/generators/graphql/templates/mutation.erb +2 -0
  22. data/lib/generators/graphql/templates/mutation_type.erb +2 -0
  23. data/lib/generators/graphql/templates/node_type.erb +9 -0
  24. data/lib/generators/graphql/templates/object.erb +3 -1
  25. data/lib/generators/graphql/templates/query_type.erb +3 -3
  26. data/lib/generators/graphql/templates/scalar.erb +2 -0
  27. data/lib/generators/graphql/templates/schema.erb +10 -35
  28. data/lib/generators/graphql/templates/union.erb +3 -1
  29. data/lib/graphql.rb +55 -4
  30. data/lib/graphql/analysis/analyze_query.rb +7 -0
  31. data/lib/graphql/analysis/ast.rb +11 -2
  32. data/lib/graphql/analysis/ast/visitor.rb +9 -1
  33. data/lib/graphql/argument.rb +3 -3
  34. data/lib/graphql/backtrace.rb +28 -19
  35. data/lib/graphql/backtrace/legacy_tracer.rb +56 -0
  36. data/lib/graphql/backtrace/table.rb +22 -2
  37. data/lib/graphql/backtrace/tracer.rb +40 -8
  38. data/lib/graphql/backwards_compatibility.rb +1 -0
  39. data/lib/graphql/compatibility/execution_specification.rb +1 -0
  40. data/lib/graphql/compatibility/lazy_execution_specification.rb +2 -0
  41. data/lib/graphql/compatibility/query_parser_specification.rb +2 -0
  42. data/lib/graphql/compatibility/schema_parser_specification.rb +2 -0
  43. data/lib/graphql/dataloader.rb +197 -0
  44. data/lib/graphql/dataloader/null_dataloader.rb +21 -0
  45. data/lib/graphql/dataloader/request.rb +24 -0
  46. data/lib/graphql/dataloader/request_all.rb +22 -0
  47. data/lib/graphql/dataloader/source.rb +93 -0
  48. data/lib/graphql/define/assign_global_id_field.rb +2 -2
  49. data/lib/graphql/define/instance_definable.rb +32 -2
  50. data/lib/graphql/define/type_definer.rb +5 -5
  51. data/lib/graphql/deprecated_dsl.rb +5 -0
  52. data/lib/graphql/enum_type.rb +2 -0
  53. data/lib/graphql/execution/errors.rb +4 -0
  54. data/lib/graphql/execution/execute.rb +7 -0
  55. data/lib/graphql/execution/interpreter.rb +20 -6
  56. data/lib/graphql/execution/interpreter/arguments.rb +57 -5
  57. data/lib/graphql/execution/interpreter/arguments_cache.rb +8 -0
  58. data/lib/graphql/execution/interpreter/handles_raw_value.rb +0 -7
  59. data/lib/graphql/execution/interpreter/runtime.rb +251 -138
  60. data/lib/graphql/execution/multiplex.rb +20 -6
  61. data/lib/graphql/function.rb +4 -0
  62. data/lib/graphql/input_object_type.rb +2 -0
  63. data/lib/graphql/integer_decoding_error.rb +17 -0
  64. data/lib/graphql/interface_type.rb +3 -1
  65. data/lib/graphql/introspection.rb +96 -0
  66. data/lib/graphql/introspection/field_type.rb +7 -3
  67. data/lib/graphql/introspection/input_value_type.rb +6 -0
  68. data/lib/graphql/introspection/introspection_query.rb +6 -92
  69. data/lib/graphql/introspection/type_type.rb +7 -3
  70. data/lib/graphql/invalid_null_error.rb +1 -1
  71. data/lib/graphql/language/block_string.rb +24 -5
  72. data/lib/graphql/language/document_from_schema_definition.rb +50 -23
  73. data/lib/graphql/language/lexer.rb +7 -3
  74. data/lib/graphql/language/lexer.rl +7 -3
  75. data/lib/graphql/language/nodes.rb +1 -1
  76. data/lib/graphql/language/parser.rb +107 -103
  77. data/lib/graphql/language/parser.y +4 -0
  78. data/lib/graphql/language/sanitized_printer.rb +59 -26
  79. data/lib/graphql/name_validator.rb +6 -7
  80. data/lib/graphql/object_type.rb +2 -0
  81. data/lib/graphql/pagination/connection.rb +5 -1
  82. data/lib/graphql/pagination/connections.rb +15 -17
  83. data/lib/graphql/query.rb +8 -3
  84. data/lib/graphql/query/context.rb +38 -4
  85. data/lib/graphql/query/fingerprint.rb +2 -0
  86. data/lib/graphql/query/serial_execution.rb +1 -0
  87. data/lib/graphql/query/validation_pipeline.rb +4 -1
  88. data/lib/graphql/relay/array_connection.rb +2 -2
  89. data/lib/graphql/relay/base_connection.rb +7 -0
  90. data/lib/graphql/relay/connection_instrumentation.rb +4 -4
  91. data/lib/graphql/relay/connection_type.rb +1 -1
  92. data/lib/graphql/relay/mutation.rb +1 -0
  93. data/lib/graphql/relay/node.rb +3 -0
  94. data/lib/graphql/relay/range_add.rb +14 -5
  95. data/lib/graphql/relay/type_extensions.rb +2 -0
  96. data/lib/graphql/scalar_type.rb +2 -0
  97. data/lib/graphql/schema.rb +107 -38
  98. data/lib/graphql/schema/argument.rb +74 -5
  99. data/lib/graphql/schema/build_from_definition.rb +203 -86
  100. data/lib/graphql/schema/default_type_error.rb +2 -0
  101. data/lib/graphql/schema/directive.rb +76 -0
  102. data/lib/graphql/schema/directive/deprecated.rb +1 -1
  103. data/lib/graphql/schema/directive/flagged.rb +57 -0
  104. data/lib/graphql/schema/enum.rb +3 -0
  105. data/lib/graphql/schema/enum_value.rb +12 -6
  106. data/lib/graphql/schema/field.rb +59 -24
  107. data/lib/graphql/schema/field/connection_extension.rb +11 -9
  108. data/lib/graphql/schema/field/scope_extension.rb +1 -1
  109. data/lib/graphql/schema/input_object.rb +38 -25
  110. data/lib/graphql/schema/interface.rb +2 -1
  111. data/lib/graphql/schema/late_bound_type.rb +2 -2
  112. data/lib/graphql/schema/loader.rb +1 -0
  113. data/lib/graphql/schema/member.rb +4 -0
  114. data/lib/graphql/schema/member/base_dsl_methods.rb +1 -0
  115. data/lib/graphql/schema/member/build_type.rb +17 -7
  116. data/lib/graphql/schema/member/has_arguments.rb +70 -51
  117. data/lib/graphql/schema/member/has_deprecation_reason.rb +25 -0
  118. data/lib/graphql/schema/member/has_directives.rb +98 -0
  119. data/lib/graphql/schema/member/has_fields.rb +2 -2
  120. data/lib/graphql/schema/member/has_validators.rb +31 -0
  121. data/lib/graphql/schema/member/type_system_helpers.rb +3 -3
  122. data/lib/graphql/schema/object.rb +11 -0
  123. data/lib/graphql/schema/printer.rb +5 -4
  124. data/lib/graphql/schema/relay_classic_mutation.rb +4 -2
  125. data/lib/graphql/schema/resolver.rb +7 -0
  126. data/lib/graphql/schema/resolver/has_payload_type.rb +2 -0
  127. data/lib/graphql/schema/subscription.rb +20 -12
  128. data/lib/graphql/schema/timeout.rb +29 -15
  129. data/lib/graphql/schema/timeout_middleware.rb +2 -0
  130. data/lib/graphql/schema/unique_within_type.rb +1 -2
  131. data/lib/graphql/schema/validation.rb +10 -0
  132. data/lib/graphql/schema/validator.rb +163 -0
  133. data/lib/graphql/schema/validator/exclusion_validator.rb +31 -0
  134. data/lib/graphql/schema/validator/format_validator.rb +49 -0
  135. data/lib/graphql/schema/validator/inclusion_validator.rb +33 -0
  136. data/lib/graphql/schema/validator/length_validator.rb +57 -0
  137. data/lib/graphql/schema/validator/numericality_validator.rb +71 -0
  138. data/lib/graphql/schema/validator/required_validator.rb +68 -0
  139. data/lib/graphql/schema/warden.rb +2 -3
  140. data/lib/graphql/static_validation.rb +1 -0
  141. data/lib/graphql/static_validation/all_rules.rb +1 -0
  142. data/lib/graphql/static_validation/rules/fields_will_merge.rb +25 -17
  143. data/lib/graphql/static_validation/rules/input_object_names_are_unique.rb +30 -0
  144. data/lib/graphql/static_validation/rules/input_object_names_are_unique_error.rb +30 -0
  145. data/lib/graphql/static_validation/validation_timeout_error.rb +25 -0
  146. data/lib/graphql/static_validation/validator.rb +31 -7
  147. data/lib/graphql/subscriptions.rb +23 -16
  148. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +21 -7
  149. data/lib/graphql/tracing.rb +2 -2
  150. data/lib/graphql/tracing/appoptics_tracing.rb +12 -2
  151. data/lib/graphql/tracing/platform_tracing.rb +4 -2
  152. data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +4 -1
  153. data/lib/graphql/tracing/skylight_tracing.rb +1 -1
  154. data/lib/graphql/types/int.rb +9 -2
  155. data/lib/graphql/types/iso_8601_date_time.rb +2 -1
  156. data/lib/graphql/types/relay.rb +11 -3
  157. data/lib/graphql/types/relay/base_connection.rb +2 -90
  158. data/lib/graphql/types/relay/base_edge.rb +2 -34
  159. data/lib/graphql/types/relay/connection_behaviors.rb +123 -0
  160. data/lib/graphql/types/relay/default_relay.rb +27 -0
  161. data/lib/graphql/types/relay/edge_behaviors.rb +42 -0
  162. data/lib/graphql/types/relay/has_node_field.rb +41 -0
  163. data/lib/graphql/types/relay/has_nodes_field.rb +41 -0
  164. data/lib/graphql/types/relay/node.rb +2 -4
  165. data/lib/graphql/types/relay/node_behaviors.rb +15 -0
  166. data/lib/graphql/types/relay/node_field.rb +1 -19
  167. data/lib/graphql/types/relay/nodes_field.rb +1 -19
  168. data/lib/graphql/types/relay/page_info.rb +2 -14
  169. data/lib/graphql/types/relay/page_info_behaviors.rb +25 -0
  170. data/lib/graphql/types/string.rb +7 -1
  171. data/lib/graphql/unauthorized_error.rb +1 -1
  172. data/lib/graphql/union_type.rb +2 -0
  173. data/lib/graphql/upgrader/member.rb +1 -0
  174. data/lib/graphql/upgrader/schema.rb +1 -0
  175. data/lib/graphql/version.rb +1 -1
  176. data/readme.md +1 -1
  177. metadata +38 -9
  178. data/lib/graphql/types/relay/base_field.rb +0 -22
  179. data/lib/graphql/types/relay/base_interface.rb +0 -29
  180. data/lib/graphql/types/relay/base_object.rb +0 -26
@@ -21,40 +21,8 @@ module GraphQL
21
21
  # end
22
22
  #
23
23
  # @see {Relay::BaseConnection} for connection types
24
- class BaseEdge < Types::Relay::BaseObject
25
- description "An edge in a connection."
26
-
27
- class << self
28
- # Get or set the Object type that this edge wraps.
29
- #
30
- # @param node_type [Class] A `Schema::Object` subclass
31
- # @param null [Boolean]
32
- def node_type(node_type = nil, null: true)
33
- if node_type
34
- @node_type = node_type
35
- # Add a default `node` field
36
- field :node, node_type, null: null, description: "The item at the end of the edge."
37
- end
38
- @node_type
39
- end
40
-
41
- def authorized?(obj, ctx)
42
- true
43
- end
44
-
45
- def accessible?(ctx)
46
- node_type.accessible?(ctx)
47
- end
48
-
49
- def visible?(ctx)
50
- node_type.visible?(ctx)
51
- end
52
- end
53
-
54
-
55
- field :cursor, String,
56
- null: false,
57
- description: "A cursor for use in pagination."
24
+ class BaseEdge < GraphQL::Schema::Object
25
+ include Types::Relay::EdgeBehaviors
58
26
  end
59
27
  end
60
28
  end
@@ -0,0 +1,123 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ module Types
5
+ module Relay
6
+ module ConnectionBehaviors
7
+ extend Forwardable
8
+ def_delegators :@object, :cursor_from_node, :parent
9
+
10
+ def self.included(child_class)
11
+ child_class.extend(ClassMethods)
12
+ child_class.extend(Relay::DefaultRelay)
13
+ child_class.default_relay(true)
14
+ child_class.node_nullable(true)
15
+ add_page_info_field(child_class)
16
+ end
17
+
18
+ module ClassMethods
19
+ # @return [Class]
20
+ attr_reader :node_type
21
+
22
+ # @return [Class]
23
+ attr_reader :edge_class
24
+
25
+ # Configure this connection to return `edges` and `nodes` based on `edge_type_class`.
26
+ #
27
+ # This method will use the inputs to create:
28
+ # - `edges` field
29
+ # - `nodes` field
30
+ # - description
31
+ #
32
+ # It's called when you subclass this base connection, trying to use the
33
+ # class name to set defaults. You can call it again in the class definition
34
+ # to override the default (or provide a value, if the default lookup failed).
35
+ def edge_type(edge_type_class, edge_class: GraphQL::Relay::Edge, node_type: edge_type_class.node_type, nodes_field: true, node_nullable: self.node_nullable)
36
+ # Set this connection's graphql name
37
+ node_type_name = node_type.graphql_name
38
+
39
+ @node_type = node_type
40
+ @edge_type = edge_type_class
41
+ @edge_class = edge_class
42
+
43
+ field :edges, [edge_type_class, null: true],
44
+ null: true,
45
+ description: "A list of edges.",
46
+ legacy_edge_class: edge_class, # This is used by the old runtime only, for EdgesInstrumentation
47
+ connection: false
48
+
49
+ define_nodes_field(node_nullable) if nodes_field
50
+
51
+ description("The connection type for #{node_type_name}.")
52
+ end
53
+
54
+ # Filter this list according to the way its node type would scope them
55
+ def scope_items(items, context)
56
+ node_type.scope_items(items, context)
57
+ end
58
+
59
+ # Add the shortcut `nodes` field to this connection and its subclasses
60
+ def nodes_field(node_nullable: self.node_nullable)
61
+ define_nodes_field(node_nullable)
62
+ end
63
+
64
+ def authorized?(obj, ctx)
65
+ true # Let nodes be filtered out
66
+ end
67
+
68
+ def accessible?(ctx)
69
+ node_type.accessible?(ctx)
70
+ end
71
+
72
+ def visible?(ctx)
73
+ node_type.visible?(ctx)
74
+ end
75
+
76
+ # Set the default `node_nullable` for this class and its child classes. (Defaults to `true`.)
77
+ # Use `node_nullable(false)` in your base class to make non-null `node` and `nodes` fields.
78
+ def node_nullable(new_value = nil)
79
+ if new_value.nil?
80
+ @node_nullable || superclass.node_nullable
81
+ else
82
+ @node_nullable ||= new_value
83
+ end
84
+ end
85
+
86
+ private
87
+
88
+ def define_nodes_field(nullable)
89
+ field :nodes, [@node_type, null: nullable],
90
+ null: nullable,
91
+ description: "A list of nodes.",
92
+ connection: false
93
+ end
94
+ end
95
+
96
+ class << self
97
+ def add_page_info_field(obj_type)
98
+ obj_type.field :page_info, GraphQL::Types::Relay::PageInfo, null: false, description: "Information to aid in pagination."
99
+ end
100
+ end
101
+
102
+ # By default this calls through to the ConnectionWrapper's edge nodes method,
103
+ # but sometimes you need to override it to support the `nodes` field
104
+ def nodes
105
+ @object.edge_nodes
106
+ end
107
+
108
+ def edges
109
+ if @object.is_a?(GraphQL::Pagination::Connection)
110
+ @object.edges
111
+ elsif context.interpreter?
112
+ context.schema.after_lazy(object.edge_nodes) do |nodes|
113
+ nodes.map { |n| self.class.edge_class.new(n, object) }
114
+ end
115
+ else
116
+ # This is done by edges_instrumentation
117
+ @object.edge_nodes
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ module Types
5
+ module Relay
6
+ module DefaultRelay
7
+ def self.extended(child_class)
8
+ child_class.default_relay(true)
9
+ end
10
+
11
+ def default_relay(new_value)
12
+ @default_relay = new_value
13
+ end
14
+
15
+ def default_relay?
16
+ !!@default_relay
17
+ end
18
+
19
+ def to_graphql
20
+ type_defn = super
21
+ type_defn.default_relay = default_relay?
22
+ type_defn
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ module Types
5
+ module Relay
6
+ module EdgeBehaviors
7
+ def self.included(child_class)
8
+ child_class.description("An edge in a connection.")
9
+ child_class.field(:cursor, String, null: false, description: "A cursor for use in pagination.")
10
+ child_class.extend(ClassMethods)
11
+ end
12
+
13
+ module ClassMethods
14
+ # Get or set the Object type that this edge wraps.
15
+ #
16
+ # @param node_type [Class] A `Schema::Object` subclass
17
+ # @param null [Boolean]
18
+ def node_type(node_type = nil, null: true)
19
+ if node_type
20
+ @node_type = node_type
21
+ # Add a default `node` field
22
+ field :node, node_type, null: null, description: "The item at the end of the edge.", connection: false
23
+ end
24
+ @node_type
25
+ end
26
+
27
+ def authorized?(obj, ctx)
28
+ true
29
+ end
30
+
31
+ def accessible?(ctx)
32
+ node_type.accessible?(ctx)
33
+ end
34
+
35
+ def visible?(ctx)
36
+ node_type.visible?(ctx)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ module Types
5
+ module Relay
6
+ module HasNodeField
7
+ def self.included(child_class)
8
+ child_class.field(**field_options, &field_block)
9
+ end
10
+
11
+ class << self
12
+ def field_options
13
+ {
14
+ name: "node",
15
+ owner: nil,
16
+ type: GraphQL::Types::Relay::Node,
17
+ null: true,
18
+ description: "Fetches an object given its ID.",
19
+ relay_node_field: true,
20
+ }
21
+ end
22
+
23
+ def field_block
24
+ Proc.new {
25
+ argument :id, "ID!", required: true,
26
+ description: "ID of the object."
27
+
28
+ def resolve(obj, args, ctx)
29
+ ctx.schema.object_from_id(args[:id], ctx)
30
+ end
31
+
32
+ def resolve_field(obj, args, ctx)
33
+ resolve(obj, args, ctx)
34
+ end
35
+ }
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ module Types
5
+ module Relay
6
+ module HasNodesField
7
+ def self.included(child_class)
8
+ child_class.field(**field_options, &field_block)
9
+ end
10
+
11
+ class << self
12
+ def field_options
13
+ {
14
+ name: "nodes",
15
+ owner: nil,
16
+ type: [GraphQL::Types::Relay::Node, null: true],
17
+ null: false,
18
+ description: "Fetches a list of objects given a list of IDs.",
19
+ relay_nodes_field: true,
20
+ }
21
+ end
22
+
23
+ def field_block
24
+ Proc.new {
25
+ argument :ids, "[ID!]!", required: true,
26
+ description: "IDs of the objects."
27
+
28
+ def resolve(obj, args, ctx)
29
+ args[:ids].map { |id| ctx.schema.object_from_id(id, ctx) }
30
+ end
31
+
32
+ def resolve_field(obj, args, ctx)
33
+ resolve(obj, args, ctx)
34
+ end
35
+ }
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -7,10 +7,8 @@ module GraphQL
7
7
  # or you can take it as inspiration for your own implementation
8
8
  # of the `Node` interface.
9
9
  module Node
10
- include Types::Relay::BaseInterface
11
- default_relay(true)
12
- description "An object with an ID."
13
- field(:id, ID, null: false, description: "ID of the object.")
10
+ include GraphQL::Schema::Interface
11
+ include Types::Relay::NodeBehaviors
14
12
  end
15
13
  end
16
14
  end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ module Types
5
+ module Relay
6
+ module NodeBehaviors
7
+ def self.included(child_module)
8
+ child_module.extend(DefaultRelay)
9
+ child_module.description("An object with an ID.")
10
+ child_module.field(:id, ID, null: false, description: "ID of the object.")
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -19,25 +19,7 @@ module GraphQL
19
19
  # context.schema.object_from_id(id, context)
20
20
  # end
21
21
  #
22
- NodeField = GraphQL::Schema::Field.new(
23
- name: "node",
24
- owner: nil,
25
- type: GraphQL::Types::Relay::Node,
26
- null: true,
27
- description: "Fetches an object given its ID.",
28
- relay_node_field: true,
29
- ) do
30
- argument :id, "ID!", required: true,
31
- description: "ID of the object."
32
-
33
- def resolve(obj, args, ctx)
34
- ctx.schema.object_from_id(args[:id], ctx)
35
- end
36
-
37
- def resolve_field(obj, args, ctx)
38
- resolve(obj, args, ctx)
39
- end
40
- end
22
+ NodeField = GraphQL::Schema::Field.new(**HasNodeField.field_options, &HasNodeField.field_block)
41
23
  end
42
24
  end
43
25
  end
@@ -21,25 +21,7 @@ module GraphQL
21
21
  # end
22
22
  # end
23
23
  #
24
- NodesField = GraphQL::Schema::Field.new(
25
- name: "nodes",
26
- owner: nil,
27
- type: [GraphQL::Types::Relay::Node, null: true],
28
- null: false,
29
- description: "Fetches a list of objects given a list of IDs.",
30
- relay_nodes_field: true,
31
- ) do
32
- argument :ids, "[ID!]!", required: true,
33
- description: "IDs of the objects."
34
-
35
- def resolve(obj, args, ctx)
36
- args[:ids].map { |id| ctx.schema.object_from_id(id, ctx) }
37
- end
38
-
39
- def resolve_field(obj, args, ctx)
40
- resolve(obj, args, ctx)
41
- end
42
- end
24
+ NodesField = GraphQL::Schema::Field.new(**HasNodesField.field_options, &HasNodesField.field_block)
43
25
  end
44
26
  end
45
27
  end
@@ -3,20 +3,8 @@ module GraphQL
3
3
  module Types
4
4
  module Relay
5
5
  # The return type of a connection's `pageInfo` field
6
- class PageInfo < Types::Relay::BaseObject
7
- default_relay true
8
- description "Information about pagination in a connection."
9
- field :has_next_page, Boolean, null: false,
10
- description: "When paginating forwards, are there more items?"
11
-
12
- field :has_previous_page, Boolean, null: false,
13
- description: "When paginating backwards, are there more items?"
14
-
15
- field :start_cursor, String, null: true,
16
- description: "When paginating backwards, the cursor to continue."
17
-
18
- field :end_cursor, String, null: true,
19
- description: "When paginating forwards, the cursor to continue."
6
+ class PageInfo < GraphQL::Schema::Object
7
+ include PageInfoBehaviors
20
8
  end
21
9
  end
22
10
  end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module Types
4
+ module Relay
5
+ module PageInfoBehaviors
6
+ def self.included(child_class)
7
+ child_class.extend GraphQL::Types::Relay::DefaultRelay
8
+
9
+ child_class.description "Information about pagination in a connection."
10
+ child_class.field :has_next_page, Boolean, null: false,
11
+ description: "When paginating forwards, are there more items?"
12
+
13
+ child_class.field :has_previous_page, Boolean, null: false,
14
+ description: "When paginating backwards, are there more items?"
15
+
16
+ child_class.field :start_cursor, String, null: true,
17
+ description: "When paginating backwards, the cursor to continue."
18
+
19
+ child_class.field :end_cursor, String, null: true,
20
+ description: "When paginating forwards, the cursor to continue."
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end