graphql 1.11.4 → 1.12.1

Sign up to get free protection for your applications and to get access to all the features.
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