graphql 1.11.4 → 1.12.1

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 (160) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/install_generator.rb +5 -5
  3. data/lib/generators/graphql/object_generator.rb +2 -0
  4. data/lib/generators/graphql/relay_generator.rb +63 -0
  5. data/lib/generators/graphql/templates/base_connection.erb +8 -0
  6. data/lib/generators/graphql/templates/base_edge.erb +8 -0
  7. data/lib/generators/graphql/templates/node_type.erb +9 -0
  8. data/lib/generators/graphql/templates/object.erb +1 -1
  9. data/lib/generators/graphql/templates/query_type.erb +1 -3
  10. data/lib/generators/graphql/templates/schema.erb +8 -35
  11. data/lib/generators/graphql/templates/union.erb +1 -1
  12. data/lib/graphql.rb +55 -4
  13. data/lib/graphql/analysis/analyze_query.rb +7 -0
  14. data/lib/graphql/analysis/ast.rb +11 -2
  15. data/lib/graphql/analysis/ast/visitor.rb +9 -1
  16. data/lib/graphql/argument.rb +3 -3
  17. data/lib/graphql/backtrace.rb +28 -19
  18. data/lib/graphql/backtrace/legacy_tracer.rb +56 -0
  19. data/lib/graphql/backtrace/table.rb +22 -2
  20. data/lib/graphql/backtrace/tracer.rb +40 -8
  21. data/lib/graphql/backwards_compatibility.rb +1 -0
  22. data/lib/graphql/compatibility/execution_specification.rb +1 -0
  23. data/lib/graphql/compatibility/lazy_execution_specification.rb +2 -0
  24. data/lib/graphql/compatibility/query_parser_specification.rb +2 -0
  25. data/lib/graphql/compatibility/schema_parser_specification.rb +2 -0
  26. data/lib/graphql/dataloader.rb +198 -0
  27. data/lib/graphql/dataloader/null_dataloader.rb +21 -0
  28. data/lib/graphql/dataloader/request.rb +24 -0
  29. data/lib/graphql/dataloader/request_all.rb +22 -0
  30. data/lib/graphql/dataloader/source.rb +93 -0
  31. data/lib/graphql/define/assign_global_id_field.rb +2 -2
  32. data/lib/graphql/define/instance_definable.rb +32 -2
  33. data/lib/graphql/define/type_definer.rb +5 -5
  34. data/lib/graphql/deprecated_dsl.rb +5 -0
  35. data/lib/graphql/enum_type.rb +2 -0
  36. data/lib/graphql/execution/errors.rb +4 -0
  37. data/lib/graphql/execution/execute.rb +7 -0
  38. data/lib/graphql/execution/interpreter.rb +20 -6
  39. data/lib/graphql/execution/interpreter/arguments.rb +57 -5
  40. data/lib/graphql/execution/interpreter/arguments_cache.rb +8 -0
  41. data/lib/graphql/execution/interpreter/handles_raw_value.rb +0 -7
  42. data/lib/graphql/execution/interpreter/runtime.rb +236 -120
  43. data/lib/graphql/execution/multiplex.rb +20 -6
  44. data/lib/graphql/function.rb +4 -0
  45. data/lib/graphql/input_object_type.rb +2 -0
  46. data/lib/graphql/integer_decoding_error.rb +17 -0
  47. data/lib/graphql/interface_type.rb +3 -1
  48. data/lib/graphql/introspection.rb +96 -0
  49. data/lib/graphql/introspection/field_type.rb +7 -3
  50. data/lib/graphql/introspection/input_value_type.rb +6 -0
  51. data/lib/graphql/introspection/introspection_query.rb +6 -92
  52. data/lib/graphql/introspection/type_type.rb +7 -3
  53. data/lib/graphql/invalid_null_error.rb +1 -1
  54. data/lib/graphql/language/block_string.rb +24 -5
  55. data/lib/graphql/language/document_from_schema_definition.rb +50 -23
  56. data/lib/graphql/language/lexer.rb +7 -3
  57. data/lib/graphql/language/lexer.rl +7 -3
  58. data/lib/graphql/language/nodes.rb +1 -1
  59. data/lib/graphql/language/parser.rb +107 -103
  60. data/lib/graphql/language/parser.y +4 -0
  61. data/lib/graphql/language/sanitized_printer.rb +59 -26
  62. data/lib/graphql/name_validator.rb +6 -7
  63. data/lib/graphql/object_type.rb +2 -0
  64. data/lib/graphql/pagination/connection.rb +5 -1
  65. data/lib/graphql/pagination/connections.rb +15 -17
  66. data/lib/graphql/query.rb +8 -3
  67. data/lib/graphql/query/context.rb +18 -3
  68. data/lib/graphql/query/serial_execution.rb +1 -0
  69. data/lib/graphql/query/validation_pipeline.rb +1 -1
  70. data/lib/graphql/relay/array_connection.rb +2 -2
  71. data/lib/graphql/relay/base_connection.rb +7 -0
  72. data/lib/graphql/relay/connection_instrumentation.rb +4 -4
  73. data/lib/graphql/relay/connection_type.rb +1 -1
  74. data/lib/graphql/relay/mutation.rb +1 -0
  75. data/lib/graphql/relay/node.rb +3 -0
  76. data/lib/graphql/relay/range_add.rb +14 -5
  77. data/lib/graphql/relay/type_extensions.rb +2 -0
  78. data/lib/graphql/scalar_type.rb +2 -0
  79. data/lib/graphql/schema.rb +104 -39
  80. data/lib/graphql/schema/argument.rb +74 -5
  81. data/lib/graphql/schema/build_from_definition.rb +203 -86
  82. data/lib/graphql/schema/default_type_error.rb +2 -0
  83. data/lib/graphql/schema/directive.rb +76 -0
  84. data/lib/graphql/schema/directive/deprecated.rb +1 -1
  85. data/lib/graphql/schema/directive/flagged.rb +57 -0
  86. data/lib/graphql/schema/enum.rb +3 -0
  87. data/lib/graphql/schema/enum_value.rb +12 -6
  88. data/lib/graphql/schema/field.rb +59 -24
  89. data/lib/graphql/schema/field/connection_extension.rb +10 -8
  90. data/lib/graphql/schema/field/scope_extension.rb +1 -1
  91. data/lib/graphql/schema/input_object.rb +38 -25
  92. data/lib/graphql/schema/interface.rb +2 -1
  93. data/lib/graphql/schema/late_bound_type.rb +2 -2
  94. data/lib/graphql/schema/loader.rb +1 -0
  95. data/lib/graphql/schema/member.rb +4 -0
  96. data/lib/graphql/schema/member/base_dsl_methods.rb +1 -0
  97. data/lib/graphql/schema/member/build_type.rb +17 -7
  98. data/lib/graphql/schema/member/has_arguments.rb +70 -51
  99. data/lib/graphql/schema/member/has_deprecation_reason.rb +25 -0
  100. data/lib/graphql/schema/member/has_directives.rb +98 -0
  101. data/lib/graphql/schema/member/has_fields.rb +2 -2
  102. data/lib/graphql/schema/member/has_validators.rb +31 -0
  103. data/lib/graphql/schema/member/type_system_helpers.rb +3 -3
  104. data/lib/graphql/schema/object.rb +11 -0
  105. data/lib/graphql/schema/printer.rb +5 -4
  106. data/lib/graphql/schema/relay_classic_mutation.rb +4 -2
  107. data/lib/graphql/schema/resolver.rb +7 -0
  108. data/lib/graphql/schema/resolver/has_payload_type.rb +2 -0
  109. data/lib/graphql/schema/subscription.rb +19 -1
  110. data/lib/graphql/schema/timeout.rb +29 -15
  111. data/lib/graphql/schema/timeout_middleware.rb +2 -0
  112. data/lib/graphql/schema/unique_within_type.rb +1 -2
  113. data/lib/graphql/schema/validation.rb +10 -0
  114. data/lib/graphql/schema/validator.rb +163 -0
  115. data/lib/graphql/schema/validator/exclusion_validator.rb +31 -0
  116. data/lib/graphql/schema/validator/format_validator.rb +49 -0
  117. data/lib/graphql/schema/validator/inclusion_validator.rb +33 -0
  118. data/lib/graphql/schema/validator/length_validator.rb +57 -0
  119. data/lib/graphql/schema/validator/numericality_validator.rb +71 -0
  120. data/lib/graphql/schema/validator/required_validator.rb +68 -0
  121. data/lib/graphql/static_validation.rb +1 -0
  122. data/lib/graphql/static_validation/all_rules.rb +1 -0
  123. data/lib/graphql/static_validation/rules/fields_will_merge.rb +25 -17
  124. data/lib/graphql/static_validation/rules/input_object_names_are_unique.rb +30 -0
  125. data/lib/graphql/static_validation/rules/input_object_names_are_unique_error.rb +30 -0
  126. data/lib/graphql/static_validation/validation_timeout_error.rb +25 -0
  127. data/lib/graphql/static_validation/validator.rb +33 -7
  128. data/lib/graphql/subscriptions.rb +18 -23
  129. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +21 -7
  130. data/lib/graphql/tracing.rb +2 -2
  131. data/lib/graphql/tracing/appoptics_tracing.rb +3 -1
  132. data/lib/graphql/tracing/platform_tracing.rb +4 -2
  133. data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +4 -1
  134. data/lib/graphql/tracing/skylight_tracing.rb +1 -1
  135. data/lib/graphql/types/int.rb +9 -2
  136. data/lib/graphql/types/relay.rb +11 -3
  137. data/lib/graphql/types/relay/base_connection.rb +2 -91
  138. data/lib/graphql/types/relay/base_edge.rb +2 -34
  139. data/lib/graphql/types/relay/connection_behaviors.rb +123 -0
  140. data/lib/graphql/types/relay/default_relay.rb +27 -0
  141. data/lib/graphql/types/relay/edge_behaviors.rb +42 -0
  142. data/lib/graphql/types/relay/has_node_field.rb +41 -0
  143. data/lib/graphql/types/relay/has_nodes_field.rb +41 -0
  144. data/lib/graphql/types/relay/node.rb +2 -4
  145. data/lib/graphql/types/relay/node_behaviors.rb +15 -0
  146. data/lib/graphql/types/relay/node_field.rb +1 -19
  147. data/lib/graphql/types/relay/nodes_field.rb +1 -19
  148. data/lib/graphql/types/relay/page_info.rb +2 -14
  149. data/lib/graphql/types/relay/page_info_behaviors.rb +25 -0
  150. data/lib/graphql/types/string.rb +7 -1
  151. data/lib/graphql/unauthorized_error.rb +1 -1
  152. data/lib/graphql/union_type.rb +2 -0
  153. data/lib/graphql/upgrader/member.rb +1 -0
  154. data/lib/graphql/upgrader/schema.rb +1 -0
  155. data/lib/graphql/version.rb +1 -1
  156. data/readme.md +1 -1
  157. metadata +49 -6
  158. data/lib/graphql/types/relay/base_field.rb +0 -22
  159. data/lib/graphql/types/relay/base_interface.rb +0 -29
  160. data/lib/graphql/types/relay/base_object.rb +0 -26
@@ -3,24 +3,32 @@ require "graphql/schema/build_from_definition/resolve_map"
3
3
 
4
4
  module GraphQL
5
5
  class Schema
6
+ # TODO Populate `.directive(...)` from here
6
7
  module BuildFromDefinition
8
+ if !String.method_defined?(:-@)
9
+ using GraphQL::StringDedupBackport
10
+ end
11
+
7
12
  class << self
8
13
  # @see {Schema.from_definition}
9
- def from_definition(definition_string, default_resolve:, using: {}, relay: false, interpreter: true, parser: DefaultParser)
10
- document = parser.parse(definition_string)
11
- default_resolve ||= {}
12
- Builder.build(document, default_resolve: default_resolve, relay: relay, using: using, interpreter: interpreter)
14
+ def from_definition(definition_string, parser: GraphQL.default_parser, **kwargs)
15
+ from_document(parser.parse(definition_string), **kwargs)
13
16
  end
14
- end
15
17
 
16
- # @api private
17
- DefaultParser = GraphQL::Language::Parser
18
+ def from_definition_path(definition_path, parser: GraphQL.default_parser, **kwargs)
19
+ from_document(parser.parse_file(definition_path), **kwargs)
20
+ end
21
+
22
+ def from_document(document, default_resolve:, using: {}, relay: false)
23
+ Builder.build(document, default_resolve: default_resolve || {}, relay: relay, using: using)
24
+ end
25
+ end
18
26
 
19
27
  # @api private
20
28
  module Builder
21
29
  extend self
22
30
 
23
- def build(document, default_resolve:, using: {}, interpreter: true, relay:)
31
+ def build(document, default_resolve:, using: {}, relay:)
24
32
  raise InvalidDocumentError.new('Must provide a document ast.') if !document || !document.is_a?(GraphQL::Language::Nodes::Document)
25
33
 
26
34
  if default_resolve.is_a?(Hash)
@@ -34,45 +42,43 @@ module GraphQL
34
42
  schema_definition = schema_defns.first
35
43
  types = {}
36
44
  directives = {}
37
- type_resolver = ->(type) { resolve_type(types, type) }
45
+ type_resolver = build_resolve_type(types, directives, ->(type_name) { types[type_name] ||= Schema::LateBoundType.new(type_name)})
46
+ # Make a different type resolver because we need to coerce directive arguments
47
+ # _while_ building the schema.
48
+ # It will dig for a type if it encounters a custom type. This could be a problem if there are cycles.
49
+ directive_type_resolver = nil
50
+ directive_type_resolver = build_resolve_type(GraphQL::Schema::BUILT_IN_TYPES, directives, ->(type_name) {
51
+ types[type_name] ||= begin
52
+ defn = document.definitions.find { |d| d.respond_to?(:name) && d.name == type_name }
53
+ build_definition_from_node(defn, directive_type_resolver, default_resolve)
54
+ end
55
+ })
38
56
 
39
57
  document.definitions.each do |definition|
40
- case definition
41
- when GraphQL::Language::Nodes::SchemaDefinition
42
- nil # already handled
43
- when GraphQL::Language::Nodes::EnumTypeDefinition
44
- types[definition.name] = build_enum_type(definition, type_resolver)
45
- when GraphQL::Language::Nodes::ObjectTypeDefinition
46
- types[definition.name] = build_object_type(definition, type_resolver, default_resolve: default_resolve)
47
- when GraphQL::Language::Nodes::InterfaceTypeDefinition
48
- types[definition.name] = build_interface_type(definition, type_resolver)
49
- when GraphQL::Language::Nodes::UnionTypeDefinition
50
- types[definition.name] = build_union_type(definition, type_resolver)
51
- when GraphQL::Language::Nodes::ScalarTypeDefinition
52
- types[definition.name] = build_scalar_type(definition, type_resolver, default_resolve: default_resolve)
53
- when GraphQL::Language::Nodes::InputObjectTypeDefinition
54
- types[definition.name] = build_input_object_type(definition, type_resolver)
55
- when GraphQL::Language::Nodes::DirectiveDefinition
56
- directives[definition.name] = build_directive(definition, type_resolver)
58
+ if definition.is_a?(GraphQL::Language::Nodes::DirectiveDefinition)
59
+ directives[definition.name] = build_directive(definition, directive_type_resolver)
57
60
  end
58
61
  end
59
62
 
60
- # At this point, if types named by the built in types are _late-bound_ types,
61
- # that means they were referenced in the schema but not defined in the schema.
62
- # That's supported for built-in types. (Eg, you can use `String` without defining it.)
63
- # In that case, insert the concrete type definition now.
64
- #
65
- # However, if the type in `types` is a _concrete_ type definition, that means that
66
- # the document contained an explicit definition of the scalar type.
67
- # Don't override it in this case.
68
- GraphQL::Schema::BUILT_IN_TYPES.each do |scalar_name, built_in_scalar|
69
- existing_type = types[scalar_name]
70
- if existing_type.is_a?(GraphQL::Schema::LateBoundType)
71
- types[scalar_name] = built_in_scalar
63
+ directives = GraphQL::Schema.default_directives.merge(directives)
64
+
65
+ # In case any directives referenced built-in types for their arguments:
66
+ replace_late_bound_types_with_built_in(types)
67
+
68
+ document.definitions.each do |definition|
69
+ case definition
70
+ when GraphQL::Language::Nodes::SchemaDefinition, GraphQL::Language::Nodes::DirectiveDefinition
71
+ nil # already handled
72
+ else
73
+ # It's possible that this was already loaded by the directives
74
+ prev_type = types[definition.name]
75
+ if prev_type.nil? || prev_type.is_a?(Schema::LateBoundType)
76
+ types[definition.name] = build_definition_from_node(definition, type_resolver, default_resolve)
77
+ end
72
78
  end
73
79
  end
74
80
 
75
- directives = GraphQL::Schema.default_directives.merge(directives)
81
+ replace_late_bound_types_with_built_in(types)
76
82
 
77
83
  if schema_definition
78
84
  if schema_definition.query
@@ -111,11 +117,11 @@ module GraphQL
111
117
  end
112
118
 
113
119
  if default_resolve.respond_to?(:resolve_type)
114
- define_singleton_method(:resolve_type) do |*args|
115
- default_resolve.resolve_type(*args)
120
+ def self.resolve_type(*args)
121
+ self.definition_default_resolve.resolve_type(*args)
116
122
  end
117
123
  else
118
- define_singleton_method(:resolve_type) do |*args|
124
+ def self.resolve_type(*args)
119
125
  NullResolveType.call(*args)
120
126
  end
121
127
  end
@@ -126,11 +132,6 @@ module GraphQL
126
132
  ast_node(schema_definition)
127
133
  end
128
134
 
129
- if interpreter
130
- use GraphQL::Execution::Interpreter
131
- use GraphQL::Analysis::AST
132
- end
133
-
134
135
  using.each do |plugin, options|
135
136
  if options
136
137
  use(plugin, **options)
@@ -141,6 +142,20 @@ module GraphQL
141
142
 
142
143
  # Empty `orphan_types` -- this will make unreachable types ... unreachable.
143
144
  own_orphan_types.clear
145
+
146
+ class << self
147
+ attr_accessor :definition_default_resolve
148
+ end
149
+
150
+ self.definition_default_resolve = default_resolve
151
+
152
+ def definition_default_resolve
153
+ self.class.definition_default_resolve
154
+ end
155
+
156
+ def self.inherited(child_class)
157
+ child_class.definition_default_resolve = self.definition_default_resolve
158
+ end
144
159
  end
145
160
  end
146
161
 
@@ -148,10 +163,85 @@ module GraphQL
148
163
  raise(GraphQL::RequiredImplementationMissingError, "Generated Schema cannot use Interface or Union types for execution. Implement resolve_type on your resolver.")
149
164
  }
150
165
 
166
+ def build_definition_from_node(definition, type_resolver, default_resolve)
167
+ case definition
168
+ when GraphQL::Language::Nodes::EnumTypeDefinition
169
+ build_enum_type(definition, type_resolver)
170
+ when GraphQL::Language::Nodes::ObjectTypeDefinition
171
+ build_object_type(definition, type_resolver)
172
+ when GraphQL::Language::Nodes::InterfaceTypeDefinition
173
+ build_interface_type(definition, type_resolver)
174
+ when GraphQL::Language::Nodes::UnionTypeDefinition
175
+ build_union_type(definition, type_resolver)
176
+ when GraphQL::Language::Nodes::ScalarTypeDefinition
177
+ build_scalar_type(definition, type_resolver, default_resolve: default_resolve)
178
+ when GraphQL::Language::Nodes::InputObjectTypeDefinition
179
+ build_input_object_type(definition, type_resolver)
180
+ end
181
+ end
182
+
183
+ # Modify `types`, replacing any late-bound references to built-in types
184
+ # with their actual definitions.
185
+ #
186
+ # (Schema definitions are allowed to reference those built-ins without redefining them.)
187
+ # @return void
188
+ def replace_late_bound_types_with_built_in(types)
189
+ GraphQL::Schema::BUILT_IN_TYPES.each do |scalar_name, built_in_scalar|
190
+ existing_type = types[scalar_name]
191
+ if existing_type.is_a?(GraphQL::Schema::LateBoundType)
192
+ types[scalar_name] = built_in_scalar
193
+ end
194
+ end
195
+ end
196
+
197
+ def build_directives(definition, ast_node, type_resolver)
198
+ dirs = prepare_directives(ast_node, type_resolver)
199
+ dirs.each do |dir_class, options|
200
+ definition.directive(dir_class, **options)
201
+ end
202
+ end
203
+
204
+ def prepare_directives(ast_node, type_resolver)
205
+ dirs = {}
206
+ ast_node.directives.each do |dir_node|
207
+ if dir_node.name == "deprecated"
208
+ # This is handled using `deprecation_reason`
209
+ next
210
+ else
211
+ dir_class = type_resolver.call(dir_node.name)
212
+ if dir_class.nil?
213
+ raise ArgumentError, "No definition for @#{dir_node.name} on #{ast_node.name} at #{ast_node.line}:#{ast_node.col}"
214
+ end
215
+ options = args_to_kwargs(dir_class, dir_node)
216
+ dirs[dir_class] = options
217
+ end
218
+ end
219
+ dirs
220
+ end
221
+
222
+ def args_to_kwargs(arg_owner, node)
223
+ if node.respond_to?(:arguments)
224
+ kwargs = {}
225
+ node.arguments.each do |arg_node|
226
+ arg_defn = arg_owner.get_argument(arg_node.name)
227
+ kwargs[arg_defn.keyword] = args_to_kwargs(arg_defn.type.unwrap, arg_node.value)
228
+ end
229
+ kwargs
230
+ elsif node.is_a?(Array)
231
+ node.map { |n| args_to_kwargs(arg_owner, n) }
232
+ elsif node.is_a?(Language::Nodes::Enum)
233
+ node.name
234
+ else
235
+ # scalar
236
+ node
237
+ end
238
+ end
239
+
151
240
  def build_enum_type(enum_type_definition, type_resolver)
152
241
  builder = self
153
242
  Class.new(GraphQL::Schema::Enum) do
154
243
  graphql_name(enum_type_definition.name)
244
+ builder.build_directives(self, enum_type_definition, type_resolver)
155
245
  description(enum_type_definition.description)
156
246
  ast_node(enum_type_definition)
157
247
  enum_type_definition.values.each do |enum_value_definition|
@@ -159,6 +249,7 @@ module GraphQL
159
249
  value: enum_value_definition.name,
160
250
  deprecation_reason: builder.build_deprecation_reason(enum_value_definition.directives),
161
251
  description: enum_value_definition.description,
252
+ directives: builder.prepare_directives(enum_value_definition, type_resolver),
162
253
  ast_node: enum_value_definition,
163
254
  )
164
255
  end
@@ -176,49 +267,54 @@ module GraphQL
176
267
  end
177
268
 
178
269
  def build_scalar_type(scalar_type_definition, type_resolver, default_resolve:)
270
+ builder = self
179
271
  Class.new(GraphQL::Schema::Scalar) do
180
272
  graphql_name(scalar_type_definition.name)
181
273
  description(scalar_type_definition.description)
182
274
  ast_node(scalar_type_definition)
275
+ builder.build_directives(self, scalar_type_definition, type_resolver)
183
276
 
184
277
  if default_resolve.respond_to?(:coerce_input)
185
- define_singleton_method(:coerce_input) do |val, ctx|
186
- default_resolve.coerce_input(self, val, ctx)
187
- end
188
-
189
- define_singleton_method(:coerce_result) do |val, ctx|
190
- default_resolve.coerce_result(self, val, ctx)
191
- end
278
+ # Put these method definitions in another method to avoid retaining `type_resolve`
279
+ # from this method's bindiing
280
+ builder.build_scalar_type_coerce_method(self, :coerce_input, default_resolve)
281
+ builder.build_scalar_type_coerce_method(self, :coerce_result, default_resolve)
192
282
  end
193
283
  end
194
284
  end
195
285
 
286
+ def build_scalar_type_coerce_method(scalar_class, method_name, default_definition_resolve)
287
+ scalar_class.define_singleton_method(method_name) do |val, ctx|
288
+ default_definition_resolve.public_send(method_name, self, val, ctx)
289
+ end
290
+ end
291
+
196
292
  def build_union_type(union_type_definition, type_resolver)
293
+ builder = self
197
294
  Class.new(GraphQL::Schema::Union) do
198
295
  graphql_name(union_type_definition.name)
199
296
  description(union_type_definition.description)
200
297
  possible_types(*union_type_definition.types.map { |type_name| type_resolver.call(type_name) })
201
298
  ast_node(union_type_definition)
299
+ builder.build_directives(self, union_type_definition, type_resolver)
202
300
  end
203
301
  end
204
302
 
205
- def build_object_type(object_type_definition, type_resolver, default_resolve:)
303
+ def build_object_type(object_type_definition, type_resolver)
206
304
  builder = self
207
- type_def = nil
208
- typed_resolve_fn = ->(field, obj, args, ctx) { default_resolve.call(type_def, field, obj, args, ctx) }
209
305
 
210
306
  Class.new(GraphQL::Schema::Object) do
211
- type_def = self
212
307
  graphql_name(object_type_definition.name)
213
308
  description(object_type_definition.description)
214
309
  ast_node(object_type_definition)
310
+ builder.build_directives(self, object_type_definition, type_resolver)
215
311
 
216
312
  object_type_definition.interfaces.each do |interface_name|
217
313
  interface_defn = type_resolver.call(interface_name)
218
314
  implements(interface_defn)
219
315
  end
220
316
 
221
- builder.build_fields(self, object_type_definition.fields, type_resolver, default_resolve: typed_resolve_fn)
317
+ builder.build_fields(self, object_type_definition.fields, type_resolver, default_resolve: true)
222
318
  end
223
319
  end
224
320
 
@@ -228,6 +324,7 @@ module GraphQL
228
324
  graphql_name(input_object_type_definition.name)
229
325
  description(input_object_type_definition.description)
230
326
  ast_node(input_object_type_definition)
327
+ builder.build_directives(self, input_object_type_definition, type_resolver)
231
328
  builder.build_arguments(self, input_object_type_definition.fields, type_resolver)
232
329
  end
233
330
  end
@@ -247,13 +344,16 @@ module GraphQL
247
344
  end
248
345
  end
249
346
 
347
+ NO_DEFAULT_VALUE = {}.freeze
348
+
250
349
  def build_arguments(type_class, arguments, type_resolver)
251
350
  builder = self
252
351
 
253
352
  arguments.each do |argument_defn|
254
- default_value_kwargs = {}
255
- if !argument_defn.default_value.nil?
256
- default_value_kwargs[:default_value] = builder.build_default_value(argument_defn.default_value)
353
+ default_value_kwargs = if !argument_defn.default_value.nil?
354
+ { default_value: builder.build_default_value(argument_defn.default_value) }
355
+ else
356
+ NO_DEFAULT_VALUE
257
357
  end
258
358
 
259
359
  type_class.argument(
@@ -261,9 +361,11 @@ module GraphQL
261
361
  type: type_resolver.call(argument_defn.type),
262
362
  required: false,
263
363
  description: argument_defn.description,
364
+ deprecation_reason: builder.build_deprecation_reason(argument_defn.directives),
264
365
  ast_node: argument_defn,
265
366
  camelize: false,
266
367
  method_access: false,
368
+ directives: prepare_directives(argument_defn, type_resolver),
267
369
  **default_value_kwargs
268
370
  )
269
371
  end
@@ -287,6 +389,7 @@ module GraphQL
287
389
  graphql_name(interface_type_definition.name)
288
390
  description(interface_type_definition.description)
289
391
  ast_node(interface_type_definition)
392
+ builder.build_directives(self, interface_type_definition, type_resolver)
290
393
 
291
394
  builder.build_fields(self, interface_type_definition.fields, type_resolver, default_resolve: nil)
292
395
  end
@@ -295,10 +398,10 @@ module GraphQL
295
398
  def build_fields(owner, field_definitions, type_resolver, default_resolve:)
296
399
  builder = self
297
400
 
298
- field_definitions.map do |field_definition|
401
+ field_definitions.each do |field_definition|
299
402
  type_name = resolve_type_name(field_definition.type)
300
- resolve_method_name = "resolve_field_#{field_definition.name}"
301
- owner.field(
403
+ resolve_method_name = -"resolve_field_#{field_definition.name}"
404
+ schema_field_defn = owner.field(
302
405
  field_definition.name,
303
406
  description: field_definition.description,
304
407
  type: type_resolver.call(field_definition.type),
@@ -309,33 +412,47 @@ module GraphQL
309
412
  ast_node: field_definition,
310
413
  method_conflict_warning: false,
311
414
  camelize: false,
415
+ directives: prepare_directives(field_definition, type_resolver),
312
416
  resolver_method: resolve_method_name,
313
- ) do
314
- builder.build_arguments(self, field_definition.arguments, type_resolver)
315
-
316
- # Don't do this for interfaces
317
- if default_resolve
318
- owner.send(:define_method, resolve_method_name) do |**args|
319
- field_instance = self.class.get_field(field_definition.name)
320
- default_resolve.call(field_instance, object, args, context)
417
+ )
418
+
419
+ builder.build_arguments(schema_field_defn, field_definition.arguments, type_resolver)
420
+
421
+ # Don't do this for interfaces
422
+ if default_resolve
423
+ owner.class_eval <<-RUBY, __FILE__, __LINE__
424
+ # frozen_string_literal: true
425
+ def #{resolve_method_name}(**args)
426
+ field_instance = self.class.get_field("#{field_definition.name}")
427
+ context.schema.definition_default_resolve.call(self.class, field_instance, object, args, context)
321
428
  end
322
- end
429
+ RUBY
323
430
  end
324
431
  end
325
432
  end
326
433
 
327
- def resolve_type(types, ast_node)
328
- case ast_node
329
- when GraphQL::Language::Nodes::TypeName
330
- type_name = ast_node.name
331
- types[type_name] ||= GraphQL::Schema::LateBoundType.new(type_name)
332
- when GraphQL::Language::Nodes::NonNullType
333
- resolve_type(types, ast_node.of_type).to_non_null_type
334
- when GraphQL::Language::Nodes::ListType
335
- resolve_type(types, ast_node.of_type).to_list_type
336
- else
337
- raise "Unexpected ast_node: #{ast_node.inspect}"
338
- end
434
+ def build_resolve_type(lookup_hash, directives, missing_type_handler)
435
+ resolve_type_proc = nil
436
+ resolve_type_proc = ->(ast_node) {
437
+ case ast_node
438
+ when GraphQL::Language::Nodes::TypeName
439
+ type_name = ast_node.name
440
+ if lookup_hash.key?(type_name)
441
+ lookup_hash[type_name]
442
+ else
443
+ missing_type_handler.call(type_name)
444
+ end
445
+ when GraphQL::Language::Nodes::NonNullType
446
+ resolve_type_proc.call(ast_node.of_type).to_non_null_type
447
+ when GraphQL::Language::Nodes::ListType
448
+ resolve_type_proc.call(ast_node.of_type).to_list_type
449
+ when String
450
+ directives[ast_node]
451
+ else
452
+ raise "Unexpected ast_node: #{ast_node.inspect}"
453
+ end
454
+ }
455
+ resolve_type_proc
339
456
  end
340
457
 
341
458
  def resolve_type_name(type)
@@ -8,6 +8,8 @@ module GraphQL
8
8
  ctx.errors << type_error
9
9
  when GraphQL::UnresolvedTypeError, GraphQL::StringEncodingError, GraphQL::IntegerEncodingError
10
10
  raise type_error
11
+ when GraphQL::IntegerDecodingError
12
+ nil
11
13
  end
12
14
  end
13
15
  end