graphql 1.13.16 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (189) hide show
  1. checksums.yaml +4 -4
  2. data/lib/graphql/analysis/ast/query_complexity.rb +1 -1
  3. data/lib/graphql/analysis/ast/query_depth.rb +0 -1
  4. data/lib/graphql/analysis/ast/visitor.rb +1 -1
  5. data/lib/graphql/analysis/ast.rb +0 -10
  6. data/lib/graphql/analysis.rb +0 -7
  7. data/lib/graphql/backtrace/table.rb +0 -18
  8. data/lib/graphql/backtrace/tracer.rb +1 -2
  9. data/lib/graphql/backtrace.rb +2 -8
  10. data/lib/graphql/dig.rb +1 -1
  11. data/lib/graphql/execution/errors.rb +1 -9
  12. data/lib/graphql/execution/interpreter/runtime.rb +2 -9
  13. data/lib/graphql/execution/interpreter.rb +0 -22
  14. data/lib/graphql/execution/lazy.rb +1 -1
  15. data/lib/graphql/execution/lookahead.rb +6 -13
  16. data/lib/graphql/execution/multiplex.rb +50 -107
  17. data/lib/graphql/execution.rb +11 -3
  18. data/lib/graphql/introspection/dynamic_fields.rb +3 -8
  19. data/lib/graphql/introspection/entry_points.rb +2 -15
  20. data/lib/graphql/language/document_from_schema_definition.rb +0 -17
  21. data/lib/graphql/pagination/connections.rb +2 -28
  22. data/lib/graphql/query/context.rb +1 -185
  23. data/lib/graphql/query/input_validation_result.rb +0 -9
  24. data/lib/graphql/query/literal_input.rb +8 -13
  25. data/lib/graphql/query/validation_pipeline.rb +6 -34
  26. data/lib/graphql/query/variable_validation_error.rb +2 -2
  27. data/lib/graphql/query/variables.rb +8 -31
  28. data/lib/graphql/query.rb +5 -34
  29. data/lib/graphql/railtie.rb +0 -104
  30. data/lib/graphql/relay/range_add.rb +0 -4
  31. data/lib/graphql/relay.rb +0 -15
  32. data/lib/graphql/schema/addition.rb +1 -8
  33. data/lib/graphql/schema/argument.rb +1 -25
  34. data/lib/graphql/schema/build_from_definition.rb +0 -1
  35. data/lib/graphql/schema/directive.rb +0 -21
  36. data/lib/graphql/schema/enum.rb +3 -19
  37. data/lib/graphql/schema/enum_value.rb +0 -22
  38. data/lib/graphql/schema/field.rb +2 -185
  39. data/lib/graphql/schema/input_object.rb +11 -57
  40. data/lib/graphql/schema/interface.rb +0 -25
  41. data/lib/graphql/schema/introspection_system.rb +3 -8
  42. data/lib/graphql/schema/late_bound_type.rb +2 -2
  43. data/lib/graphql/schema/list.rb +3 -24
  44. data/lib/graphql/schema/loader.rb +0 -1
  45. data/lib/graphql/schema/member/base_dsl_methods.rb +0 -5
  46. data/lib/graphql/schema/member/build_type.rb +4 -6
  47. data/lib/graphql/schema/member/has_arguments.rb +14 -18
  48. data/lib/graphql/schema/member/has_fields.rb +2 -2
  49. data/lib/graphql/schema/member/has_interfaces.rb +0 -2
  50. data/lib/graphql/schema/member/validates_input.rb +2 -2
  51. data/lib/graphql/schema/member.rb +0 -6
  52. data/lib/graphql/schema/mutation.rb +0 -9
  53. data/lib/graphql/schema/non_null.rb +3 -9
  54. data/lib/graphql/schema/object.rb +0 -40
  55. data/lib/graphql/schema/relay_classic_mutation.rb +17 -28
  56. data/lib/graphql/schema/scalar.rb +1 -16
  57. data/lib/graphql/schema/union.rb +0 -16
  58. data/lib/graphql/schema/warden.rb +1 -1
  59. data/lib/graphql/schema/wrapper.rb +0 -5
  60. data/lib/graphql/schema.rb +106 -945
  61. data/lib/graphql/static_validation/base_visitor.rb +4 -21
  62. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +12 -12
  63. data/lib/graphql/static_validation/validator.rb +2 -24
  64. data/lib/graphql/static_validation.rb +0 -2
  65. data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +38 -1
  66. data/lib/graphql/subscriptions/event.rb +1 -1
  67. data/lib/graphql/subscriptions/instrumentation.rb +0 -51
  68. data/lib/graphql/subscriptions.rb +4 -13
  69. data/lib/graphql/tracing/data_dog_tracing.rb +2 -19
  70. data/lib/graphql/tracing/platform_tracing.rb +4 -31
  71. data/lib/graphql/tracing.rb +0 -1
  72. data/lib/graphql/types/relay/connection_behaviors.rb +2 -6
  73. data/lib/graphql/types/relay/default_relay.rb +0 -10
  74. data/lib/graphql/types/relay/node_behaviors.rb +5 -1
  75. data/lib/graphql/types/relay.rb +0 -2
  76. data/lib/graphql/version.rb +1 -1
  77. data/lib/graphql.rb +1 -65
  78. metadata +6 -131
  79. data/lib/graphql/analysis/analyze_query.rb +0 -98
  80. data/lib/graphql/analysis/field_usage.rb +0 -45
  81. data/lib/graphql/analysis/max_query_complexity.rb +0 -26
  82. data/lib/graphql/analysis/max_query_depth.rb +0 -26
  83. data/lib/graphql/analysis/query_complexity.rb +0 -88
  84. data/lib/graphql/analysis/query_depth.rb +0 -43
  85. data/lib/graphql/analysis/reducer_state.rb +0 -48
  86. data/lib/graphql/argument.rb +0 -131
  87. data/lib/graphql/authorization.rb +0 -82
  88. data/lib/graphql/backtrace/legacy_tracer.rb +0 -56
  89. data/lib/graphql/backwards_compatibility.rb +0 -61
  90. data/lib/graphql/base_type.rb +0 -232
  91. data/lib/graphql/boolean_type.rb +0 -2
  92. data/lib/graphql/compatibility/execution_specification/counter_schema.rb +0 -53
  93. data/lib/graphql/compatibility/execution_specification/specification_schema.rb +0 -200
  94. data/lib/graphql/compatibility/execution_specification.rb +0 -436
  95. data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +0 -111
  96. data/lib/graphql/compatibility/lazy_execution_specification.rb +0 -215
  97. data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +0 -87
  98. data/lib/graphql/compatibility/query_parser_specification/query_assertions.rb +0 -79
  99. data/lib/graphql/compatibility/query_parser_specification.rb +0 -266
  100. data/lib/graphql/compatibility/schema_parser_specification.rb +0 -682
  101. data/lib/graphql/compatibility.rb +0 -5
  102. data/lib/graphql/define/assign_argument.rb +0 -12
  103. data/lib/graphql/define/assign_connection.rb +0 -13
  104. data/lib/graphql/define/assign_enum_value.rb +0 -18
  105. data/lib/graphql/define/assign_global_id_field.rb +0 -11
  106. data/lib/graphql/define/assign_mutation_function.rb +0 -34
  107. data/lib/graphql/define/assign_object_field.rb +0 -42
  108. data/lib/graphql/define/defined_object_proxy.rb +0 -53
  109. data/lib/graphql/define/instance_definable.rb +0 -255
  110. data/lib/graphql/define/no_definition_error.rb +0 -7
  111. data/lib/graphql/define/non_null_with_bang.rb +0 -16
  112. data/lib/graphql/define/type_definer.rb +0 -31
  113. data/lib/graphql/define.rb +0 -31
  114. data/lib/graphql/deprecated_dsl.rb +0 -55
  115. data/lib/graphql/directive/deprecated_directive.rb +0 -2
  116. data/lib/graphql/directive/include_directive.rb +0 -2
  117. data/lib/graphql/directive/skip_directive.rb +0 -2
  118. data/lib/graphql/directive.rb +0 -107
  119. data/lib/graphql/enum_type.rb +0 -133
  120. data/lib/graphql/execution/execute.rb +0 -333
  121. data/lib/graphql/execution/flatten.rb +0 -40
  122. data/lib/graphql/execution/typecast.rb +0 -50
  123. data/lib/graphql/field/resolve.rb +0 -59
  124. data/lib/graphql/field.rb +0 -226
  125. data/lib/graphql/float_type.rb +0 -2
  126. data/lib/graphql/function.rb +0 -128
  127. data/lib/graphql/id_type.rb +0 -2
  128. data/lib/graphql/input_object_type.rb +0 -138
  129. data/lib/graphql/int_type.rb +0 -2
  130. data/lib/graphql/interface_type.rb +0 -72
  131. data/lib/graphql/internal_representation/document.rb +0 -27
  132. data/lib/graphql/internal_representation/node.rb +0 -206
  133. data/lib/graphql/internal_representation/print.rb +0 -51
  134. data/lib/graphql/internal_representation/rewrite.rb +0 -184
  135. data/lib/graphql/internal_representation/scope.rb +0 -88
  136. data/lib/graphql/internal_representation/visit.rb +0 -36
  137. data/lib/graphql/internal_representation.rb +0 -7
  138. data/lib/graphql/list_type.rb +0 -80
  139. data/lib/graphql/non_null_type.rb +0 -71
  140. data/lib/graphql/object_type.rb +0 -130
  141. data/lib/graphql/query/arguments.rb +0 -189
  142. data/lib/graphql/query/arguments_cache.rb +0 -24
  143. data/lib/graphql/query/executor.rb +0 -52
  144. data/lib/graphql/query/serial_execution/field_resolution.rb +0 -92
  145. data/lib/graphql/query/serial_execution/operation_resolution.rb +0 -19
  146. data/lib/graphql/query/serial_execution/selection_resolution.rb +0 -23
  147. data/lib/graphql/query/serial_execution/value_resolution.rb +0 -87
  148. data/lib/graphql/query/serial_execution.rb +0 -40
  149. data/lib/graphql/relay/array_connection.rb +0 -83
  150. data/lib/graphql/relay/base_connection.rb +0 -189
  151. data/lib/graphql/relay/connection_instrumentation.rb +0 -54
  152. data/lib/graphql/relay/connection_resolve.rb +0 -43
  153. data/lib/graphql/relay/connection_type.rb +0 -54
  154. data/lib/graphql/relay/edge.rb +0 -27
  155. data/lib/graphql/relay/edge_type.rb +0 -19
  156. data/lib/graphql/relay/edges_instrumentation.rb +0 -39
  157. data/lib/graphql/relay/global_id_resolve.rb +0 -17
  158. data/lib/graphql/relay/mongo_relation_connection.rb +0 -50
  159. data/lib/graphql/relay/mutation/instrumentation.rb +0 -23
  160. data/lib/graphql/relay/mutation/resolve.rb +0 -56
  161. data/lib/graphql/relay/mutation/result.rb +0 -38
  162. data/lib/graphql/relay/mutation.rb +0 -106
  163. data/lib/graphql/relay/node.rb +0 -39
  164. data/lib/graphql/relay/page_info.rb +0 -7
  165. data/lib/graphql/relay/relation_connection.rb +0 -188
  166. data/lib/graphql/relay/type_extensions.rb +0 -32
  167. data/lib/graphql/scalar_type.rb +0 -91
  168. data/lib/graphql/schema/catchall_middleware.rb +0 -35
  169. data/lib/graphql/schema/default_parse_error.rb +0 -10
  170. data/lib/graphql/schema/default_type_error.rb +0 -17
  171. data/lib/graphql/schema/member/accepts_definition.rb +0 -164
  172. data/lib/graphql/schema/member/cached_graphql_definition.rb +0 -58
  173. data/lib/graphql/schema/member/instrumentation.rb +0 -131
  174. data/lib/graphql/schema/middleware_chain.rb +0 -82
  175. data/lib/graphql/schema/possible_types.rb +0 -44
  176. data/lib/graphql/schema/rescue_middleware.rb +0 -60
  177. data/lib/graphql/schema/timeout_middleware.rb +0 -88
  178. data/lib/graphql/schema/traversal.rb +0 -228
  179. data/lib/graphql/schema/validation.rb +0 -313
  180. data/lib/graphql/static_validation/default_visitor.rb +0 -15
  181. data/lib/graphql/static_validation/no_validate_visitor.rb +0 -10
  182. data/lib/graphql/string_type.rb +0 -2
  183. data/lib/graphql/subscriptions/subscription_root.rb +0 -76
  184. data/lib/graphql/tracing/skylight_tracing.rb +0 -70
  185. data/lib/graphql/types/relay/node_field.rb +0 -24
  186. data/lib/graphql/types/relay/nodes_field.rb +0 -43
  187. data/lib/graphql/union_type.rb +0 -115
  188. data/lib/graphql/upgrader/member.rb +0 -937
  189. data/lib/graphql/upgrader/schema.rb +0 -38
@@ -1,24 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
  require "graphql/schema/addition"
3
3
  require "graphql/schema/base_64_encoder"
4
- require "graphql/schema/catchall_middleware"
5
- require "graphql/schema/default_parse_error"
6
- require "graphql/schema/default_type_error"
7
4
  require "graphql/schema/find_inherited_value"
8
5
  require "graphql/schema/finder"
9
6
  require "graphql/schema/invalid_type_error"
10
7
  require "graphql/schema/introspection_system"
11
8
  require "graphql/schema/late_bound_type"
12
- require "graphql/schema/middleware_chain"
13
9
  require "graphql/schema/null_mask"
14
- require "graphql/schema/possible_types"
15
- require "graphql/schema/rescue_middleware"
16
10
  require "graphql/schema/timeout"
17
- require "graphql/schema/timeout_middleware"
18
- require "graphql/schema/traversal"
19
11
  require "graphql/schema/type_expression"
20
12
  require "graphql/schema/unique_within_type"
21
- require "graphql/schema/validation"
22
13
  require "graphql/schema/warden"
23
14
  require "graphql/schema/build_from_definition"
24
15
 
@@ -79,11 +70,7 @@ module GraphQL
79
70
  # end
80
71
  #
81
72
  class Schema
82
- extend Forwardable
83
- extend GraphQL::Schema::Member::AcceptsDefinition
84
73
  extend GraphQL::Schema::Member::HasAstNode
85
- include GraphQL::Define::InstanceDefinable
86
- extend GraphQL::Define::InstanceDefinable::DeprecatedDefine
87
74
  extend GraphQL::Schema::FindInheritedValue
88
75
 
89
76
  class DuplicateTypeNamesError < GraphQL::Error
@@ -102,757 +89,41 @@ module GraphQL
102
89
  end
103
90
  end
104
91
 
105
- module LazyHandlingMethods
106
- # Call the given block at the right time, either:
107
- # - Right away, if `value` is not registered with `lazy_resolve`
108
- # - After resolving `value`, if it's registered with `lazy_resolve` (eg, `Promise`)
109
- # @api private
110
- def after_lazy(value, &block)
111
- if lazy?(value)
112
- GraphQL::Execution::Lazy.new do
113
- result = sync_lazy(value)
114
- # The returned result might also be lazy, so check it, too
115
- after_lazy(result, &block)
116
- end
117
- else
118
- yield(value) if block_given?
119
- end
120
- end
121
-
122
- # Override this method to handle lazy objects in a custom way.
123
- # @param value [Object] an instance of a class registered with {.lazy_resolve}
124
- # @return [Object] A GraphQL-ready (non-lazy) object
125
- # @api private
126
- def sync_lazy(value)
127
- lazy_method = lazy_method_name(value)
128
- if lazy_method
129
- synced_value = value.public_send(lazy_method)
130
- sync_lazy(synced_value)
131
- else
132
- value
133
- end
134
- end
135
-
136
- # @return [Symbol, nil] The method name to lazily resolve `obj`, or nil if `obj`'s class wasn't registered with {#lazy_resolve}.
137
- def lazy_method_name(obj)
138
- lazy_methods.get(obj)
139
- end
140
-
141
- # @return [Boolean] True if this object should be lazily resolved
142
- def lazy?(obj)
143
- !!lazy_method_name(obj)
144
- end
145
-
146
- # Return a lazy if any of `maybe_lazies` are lazy,
147
- # otherwise, call the block eagerly and return the result.
148
- # @param maybe_lazies [Array]
149
- # @api private
150
- def after_any_lazies(maybe_lazies)
151
- if maybe_lazies.any? { |l| lazy?(l) }
152
- GraphQL::Execution::Lazy.all(maybe_lazies).then do |result|
153
- yield result
154
- end
155
- else
156
- yield maybe_lazies
157
- end
158
- end
159
- end
160
-
161
- include LazyHandlingMethods
162
- extend LazyHandlingMethods
163
-
164
- deprecated_accepts_definitions \
165
- :query_execution_strategy, :mutation_execution_strategy, :subscription_execution_strategy,
166
- :validate_timeout, :validate_max_errors, :max_depth, :max_complexity, :default_max_page_size,
167
- :orphan_types, :resolve_type, :type_error, :parse_error,
168
- :error_bubbling,
169
- :raise_definition_error,
170
- :object_from_id, :id_from_object,
171
- :default_mask,
172
- :cursor_encoder,
173
- # If these are given as classes, normalize them. Accept `nil` when building from string.
174
- query: ->(schema, t) { schema.query = t.respond_to?(:graphql_definition) ? t.graphql_definition : t },
175
- mutation: ->(schema, t) { schema.mutation = t.respond_to?(:graphql_definition) ? t.graphql_definition : t },
176
- subscription: ->(schema, t) { schema.subscription = t.respond_to?(:graphql_definition) ? t.graphql_definition : t },
177
- disable_introspection_entry_points: ->(schema) { schema.disable_introspection_entry_points = true },
178
- disable_schema_introspection_entry_point: ->(schema) { schema.disable_schema_introspection_entry_point = true },
179
- disable_type_introspection_entry_point: ->(schema) { schema.disable_type_introspection_entry_point = true },
180
- directives: ->(schema, directives) { schema.directives = directives.reduce({}) { |m, d| m[d.graphql_name] = d; m } },
181
- directive: ->(schema, directive) { schema.directives[directive.graphql_name] = directive },
182
- instrument: ->(schema, type, instrumenter, after_built_ins: false) {
183
- if type == :field && after_built_ins
184
- type = :field_after_built_ins
185
- end
186
- schema.instrumenters[type] << instrumenter
187
- },
188
- query_analyzer: ->(schema, analyzer) {
189
- if analyzer == GraphQL::Authorization::Analyzer
190
- GraphQL::Deprecation.warn("The Authorization query analyzer is deprecated. Authorizing at query runtime is generally a better idea.")
191
- end
192
- schema.query_analyzers << analyzer
193
- },
194
- multiplex_analyzer: ->(schema, analyzer) { schema.multiplex_analyzers << analyzer },
195
- middleware: ->(schema, middleware) { schema.middleware << middleware },
196
- lazy_resolve: ->(schema, lazy_class, lazy_value_method) { schema.lazy_methods.set(lazy_class, lazy_value_method) },
197
- rescue_from: ->(schema, err_class, &block) { schema.rescue_from(err_class, &block) },
198
- tracer: ->(schema, tracer) { schema.tracers.push(tracer) }
199
-
200
- ensure_defined :introspection_system
201
-
202
- attr_accessor \
203
- :query, :mutation, :subscription,
204
- :query_execution_strategy, :mutation_execution_strategy, :subscription_execution_strategy,
205
- :validate_timeout, :validate_max_errors, :max_depth, :max_complexity, :default_max_page_size,
206
- :orphan_types, :directives,
207
- :query_analyzers, :multiplex_analyzers, :instrumenters, :lazy_methods,
208
- :cursor_encoder,
209
- :ast_node,
210
- :raise_definition_error,
211
- :introspection_namespace,
212
- :analysis_engine
213
-
214
- # [Boolean] True if this object bubbles validation errors up from a field into its parent InputObject, if there is one.
215
- attr_accessor :error_bubbling
216
-
217
- # Single, long-lived instance of the provided subscriptions class, if there is one.
218
- # @return [GraphQL::Subscriptions]
219
- attr_accessor :subscriptions
220
-
221
- # @return [MiddlewareChain] MiddlewareChain which is applied to fields during execution
222
- attr_accessor :middleware
223
-
224
- # @return [<#call(member, ctx)>] A callable for filtering members of the schema
225
- # @see {Query.new} for query-specific filters with `except:`
226
- attr_accessor :default_mask
227
-
228
- # @see {GraphQL::Query::Context} The parent class of these classes
229
- # @return [Class] Instantiated for each query
230
- attr_accessor :context_class
231
-
232
- # [Boolean] True if this object disables the introspection entry point fields
233
- attr_accessor :disable_introspection_entry_points
234
-
235
- def disable_introspection_entry_points?
236
- !!@disable_introspection_entry_points
237
- end
238
-
239
- # [Boolean] True if this object disables the __schema introspection entry point field
240
- attr_accessor :disable_schema_introspection_entry_point
241
-
242
- def disable_schema_introspection_entry_point?
243
- !!@disable_schema_introspection_entry_point
244
- end
245
-
246
- # [Boolean] True if this object disables the __type introspection entry point field
247
- attr_accessor :disable_type_introspection_entry_point
248
-
249
- def disable_type_introspection_entry_point?
250
- !!@disable_type_introspection_entry_point
251
- end
92
+ # Error that is raised when [#Schema#from_definition] is passed an invalid schema definition string.
93
+ class InvalidDocumentError < Error; end;
252
94
 
253
95
  class << self
254
- attr_writer :default_execution_strategy
255
- end
256
-
257
- def default_filter
258
- GraphQL::Filter.new(except: default_mask)
259
- end
260
-
261
- # @return [Array<#trace(key, data)>] Tracers applied to every query
262
- # @see {Query#tracers} for query-specific tracers
263
- attr_reader :tracers
264
-
265
- DYNAMIC_FIELDS = ["__type", "__typename", "__schema"].freeze
266
-
267
- attr_reader :static_validator, :object_from_id_proc, :id_from_object_proc, :resolve_type_proc
268
-
269
- def initialize
270
- @tracers = []
271
- @definition_error = nil
272
- @orphan_types = []
273
- @directives = {}
274
- self.class.default_directives.each do |name, dir|
275
- @directives[name] = dir.graphql_definition
276
- end
277
- @static_validator = GraphQL::StaticValidation::Validator.new(schema: self)
278
- @middleware = MiddlewareChain.new(final_step: GraphQL::Execution::Execute::FieldResolveStep)
279
- @query_analyzers = []
280
- @multiplex_analyzers = []
281
- @resolve_type_proc = nil
282
- @object_from_id_proc = nil
283
- @id_from_object_proc = nil
284
- @type_error_proc = DefaultTypeError
285
- @parse_error_proc = DefaultParseError
286
- @instrumenters = Hash.new { |h, k| h[k] = [] }
287
- @lazy_methods = GraphQL::Execution::Lazy::LazyMethodMap.new
288
- @lazy_methods.set(GraphQL::Execution::Lazy, :value)
289
- @cursor_encoder = Base64Encoder
290
- # For schema instances, default to legacy runtime modules
291
- @analysis_engine = GraphQL::Analysis
292
- @query_execution_strategy = GraphQL::Execution::Execute
293
- @mutation_execution_strategy = GraphQL::Execution::Execute
294
- @subscription_execution_strategy = GraphQL::Execution::Execute
295
- @default_mask = GraphQL::Schema::NullMask
296
- @rebuilding_artifacts = false
297
- @context_class = GraphQL::Query::Context
298
- @introspection_namespace = nil
299
- @introspection_system = nil
300
- @interpreter = false
301
- @error_bubbling = false
302
- @disable_introspection_entry_points = false
303
- @disable_schema_introspection_entry_point = false
304
- @disable_type_introspection_entry_point = false
305
- end
306
-
307
- # @return [Boolean] True if using the new {GraphQL::Execution::Interpreter}
308
- def interpreter?
309
- query_execution_strategy == GraphQL::Execution::Interpreter &&
310
- mutation_execution_strategy == GraphQL::Execution::Interpreter &&
311
- subscription_execution_strategy == GraphQL::Execution::Interpreter
312
- end
313
-
314
- def inspect
315
- "#<#{self.class.name} ...>"
316
- end
317
-
318
- def initialize_copy(other)
319
- super
320
- @orphan_types = other.orphan_types.dup
321
- @directives = other.directives.dup
322
- @static_validator = GraphQL::StaticValidation::Validator.new(schema: self)
323
- @middleware = other.middleware.dup
324
- @query_analyzers = other.query_analyzers.dup
325
- @multiplex_analyzers = other.multiplex_analyzers.dup
326
- @tracers = other.tracers.dup
327
- @possible_types = GraphQL::Schema::PossibleTypes.new(self)
328
-
329
- @lazy_methods = other.lazy_methods.dup
330
-
331
- @instrumenters = Hash.new { |h, k| h[k] = [] }
332
- other.instrumenters.each do |key, insts|
333
- @instrumenters[key].concat(insts)
334
- end
335
-
336
- if other.rescues?
337
- @rescue_middleware = other.rescue_middleware
338
- end
339
-
340
- # This will be rebuilt when it's requested
341
- # or during a later `define` call
342
- @types = nil
343
- @introspection_system = nil
344
- end
345
-
346
- def rescue_from(*args, &block)
347
- rescue_middleware.rescue_from(*args, &block)
348
- end
349
-
350
- def remove_handler(*args, &block)
351
- rescue_middleware.remove_handler(*args, &block)
352
- end
353
-
354
- def using_ast_analysis?
355
- @analysis_engine == GraphQL::Analysis::AST
356
- end
357
-
358
- # For forwards-compatibility with Schema classes
359
- alias :graphql_definition :itself
360
-
361
- def deprecated_define(**kwargs, &block)
362
- super
363
- ensure_defined
364
- # Assert that all necessary configs are present:
365
- validation_error = Validation.validate(self)
366
- validation_error && raise(GraphQL::RequiredImplementationMissingError, validation_error)
367
- rebuild_artifacts
368
-
369
- @definition_error = nil
370
- nil
371
- rescue StandardError => err
372
- if @raise_definition_error || err.is_a?(CyclicalDefinitionError) || err.is_a?(GraphQL::RequiredImplementationMissingError)
373
- raise
374
- else
375
- # Raise this error _later_ to avoid messing with Rails constant loading
376
- @definition_error = err
377
- end
378
- nil
379
- end
380
-
381
- # Attach `instrumenter` to this schema for instrumenting events of `instrumentation_type`.
382
- # @param instrumentation_type [Symbol]
383
- # @param instrumenter
384
- # @return [void]
385
- def instrument(instrumentation_type, instrumenter)
386
- @instrumenters[instrumentation_type] << instrumenter
387
- if instrumentation_type == :field
388
- rebuild_artifacts
389
- end
390
- end
391
-
392
- # @return [Array<GraphQL::BaseType>] The root types of this schema
393
- def root_types
394
- @root_types ||= begin
395
- rebuild_artifacts
396
- @root_types
397
- end
398
- end
399
-
400
- # @see [GraphQL::Schema::Warden] Restricted access to members of a schema
401
- # @return [GraphQL::Schema::TypeMap] `{ name => type }` pairs of types in this schema
402
- def types
403
- @types ||= begin
404
- rebuild_artifacts
405
- @types
406
- end
407
- end
408
-
409
- def get_type(type_name)
410
- @types[type_name]
411
- end
412
-
413
- # @api private
414
- def introspection_system
415
- @introspection_system ||= begin
416
- rebuild_artifacts
417
- @introspection_system
418
- end
419
- end
420
-
421
- # Returns a list of Arguments and Fields referencing a certain type
422
- # @param type_name [String]
423
- # @return [Hash]
424
- def references_to(type_name = nil)
425
- rebuild_artifacts unless defined?(@type_reference_map)
426
- if type_name
427
- @type_reference_map.fetch(type_name, [])
428
- else
429
- @type_reference_map
430
- end
431
- end
432
-
433
- # Returns a list of Union types in which a type is a member
434
- # @param type [GraphQL::ObjectType]
435
- # @return [Array<GraphQL::UnionType>] list of union types of which the type is a member
436
- def union_memberships(type)
437
- rebuild_artifacts unless defined?(@union_memberships)
438
- @union_memberships.fetch(type.name, [])
439
- end
440
-
441
- # Execute a query on itself. Raises an error if the schema definition is invalid.
442
- # @see {Query#initialize} for arguments.
443
- # @return [Hash] query result, ready to be serialized as JSON
444
- def execute(query_str = nil, **kwargs)
445
- if query_str
446
- kwargs[:query] = query_str
447
- end
448
- # Some of the query context _should_ be passed to the multiplex, too
449
- multiplex_context = if (ctx = kwargs[:context])
450
- {
451
- backtrace: ctx[:backtrace],
452
- tracers: ctx[:tracers],
453
- }
454
- else
455
- {}
456
- end
457
- # Since we're running one query, don't run a multiplex-level complexity analyzer
458
- all_results = multiplex([kwargs], max_complexity: nil, context: multiplex_context)
459
- all_results[0]
460
- end
461
-
462
- # Execute several queries on itself. Raises an error if the schema definition is invalid.
463
- # @example Run several queries at once
464
- # context = { ... }
465
- # queries = [
466
- # { query: params[:query_1], variables: params[:variables_1], context: context },
467
- # { query: params[:query_2], variables: params[:variables_2], context: context },
468
- # ]
469
- # results = MySchema.multiplex(queries)
470
- # render json: {
471
- # result_1: results[0],
472
- # result_2: results[1],
473
- # }
474
- #
475
- # @see {Query#initialize} for query keyword arguments
476
- # @see {Execution::Multiplex#run_queries} for multiplex keyword arguments
477
- # @param queries [Array<Hash>] Keyword arguments for each query
478
- # @param context [Hash] Multiplex-level context
479
- # @return [Array<Hash>] One result for each query in the input
480
- def multiplex(queries, **kwargs)
481
- with_definition_error_check {
482
- GraphQL::Execution::Multiplex.run_all(self, queries, **kwargs)
483
- }
484
- end
485
-
486
- # Search for a schema member using a string path
487
- # @example Finding a Field
488
- # Schema.find("Ensemble.musicians")
489
- #
490
- # @see {GraphQL::Schema::Finder} for more examples
491
- # @param path [String] A dot-separated path to the member
492
- # @raise [Schema::Finder::MemberNotFoundError] if path could not be found
493
- # @return [GraphQL::BaseType, GraphQL::Field, GraphQL::Argument, GraphQL::Directive] A GraphQL Schema Member
494
- def find(path)
495
- rebuild_artifacts unless defined?(@finder)
496
- @find_cache[path] ||= @finder.find(path)
497
- end
498
-
499
- # Resolve field named `field_name` for type `parent_type`.
500
- # Handles dynamic fields `__typename`, `__type` and `__schema`, too
501
- # @param parent_type [String, GraphQL::BaseType]
502
- # @param field_name [String]
503
- # @return [GraphQL::Field, nil] The field named `field_name` on `parent_type`
504
- # @see [GraphQL::Schema::Warden] Restricted access to members of a schema
505
- def get_field(parent_type, field_name)
506
- with_definition_error_check do
507
- parent_type_name = case parent_type
508
- when GraphQL::BaseType, Class, Module
509
- parent_type.graphql_name
510
- when String
511
- parent_type
96
+ # Create schema with the result of an introspection query.
97
+ # @param introspection_result [Hash] A response from {GraphQL::Introspection::INTROSPECTION_QUERY}
98
+ # @return [Class<GraphQL::Schema>] the schema described by `input`
99
+ def from_introspection(introspection_result)
100
+ GraphQL::Schema::Loader.load(introspection_result)
101
+ end
102
+
103
+ # Create schema from an IDL schema or file containing an IDL definition.
104
+ # @param definition_or_path [String] A schema definition string, or a path to a file containing the definition
105
+ # @param default_resolve [<#call(type, field, obj, args, ctx)>] A callable for handling field resolution
106
+ # @param parser [Object] An object for handling definition string parsing (must respond to `parse`)
107
+ # @param using [Hash] Plugins to attach to the created schema with `use(key, value)`
108
+ # @return [Class] the schema described by `document`
109
+ def from_definition(definition_or_path, default_resolve: nil, parser: GraphQL.default_parser, using: {})
110
+ # If the file ends in `.graphql`, treat it like a filepath
111
+ if definition_or_path.end_with?(".graphql")
112
+ GraphQL::Schema::BuildFromDefinition.from_definition_path(
113
+ definition_or_path,
114
+ default_resolve: default_resolve,
115
+ parser: parser,
116
+ using: using,
117
+ )
512
118
  else
513
- raise "Unexpected parent_type: #{parent_type}"
514
- end
515
-
516
- defined_field = @instrumented_field_map[parent_type_name][field_name]
517
- if defined_field
518
- defined_field
519
- elsif parent_type == query && (entry_point_field = introspection_system.entry_point(name: field_name))
520
- entry_point_field
521
- elsif (dynamic_field = introspection_system.dynamic_field(name: field_name))
522
- dynamic_field
523
- else
524
- nil
119
+ GraphQL::Schema::BuildFromDefinition.from_definition(
120
+ definition_or_path,
121
+ default_resolve: default_resolve,
122
+ parser: parser,
123
+ using: using,
124
+ )
525
125
  end
526
126
  end
527
- end
528
-
529
- # Fields for this type, after instrumentation is applied
530
- # @return [Hash<String, GraphQL::Field>]
531
- def get_fields(type)
532
- @instrumented_field_map[type.graphql_name]
533
- end
534
-
535
- def type_from_ast(ast_node, context:)
536
- GraphQL::Schema::TypeExpression.build_type(self, ast_node)
537
- end
538
-
539
- # @see [GraphQL::Schema::Warden] Restricted access to members of a schema
540
- # @param type_defn [GraphQL::InterfaceType, GraphQL::UnionType] the type whose members you want to retrieve
541
- # @param context [GraphQL::Query::Context] The context for the current query
542
- # @return [Array<GraphQL::ObjectType>] types which belong to `type_defn` in this schema
543
- def possible_types(type_defn, context = GraphQL::Query::NullContext)
544
- if context == GraphQL::Query::NullContext
545
- @possible_types ||= GraphQL::Schema::PossibleTypes.new(self)
546
- @possible_types.possible_types(type_defn, context)
547
- else
548
- # Use the incoming context to cache this instance --
549
- # if it were cached on the schema, we'd have a memory leak
550
- # https://github.com/rmosolgo/graphql-ruby/issues/2878
551
- ns = context.namespace(:possible_types)
552
- per_query_possible_types = ns[:possible_types] ||= GraphQL::Schema::PossibleTypes.new(self)
553
- per_query_possible_types.possible_types(type_defn, context)
554
- end
555
- end
556
-
557
- # @see [GraphQL::Schema::Warden] Restricted access to root types
558
- # @return [GraphQL::ObjectType, nil]
559
- def root_type_for_operation(operation)
560
- case operation
561
- when "query"
562
- query
563
- when "mutation"
564
- mutation
565
- when "subscription"
566
- subscription
567
- else
568
- raise ArgumentError, "unknown operation type: #{operation}"
569
- end
570
- end
571
-
572
- def execution_strategy_for_operation(operation)
573
- case operation
574
- when "query"
575
- query_execution_strategy
576
- when "mutation"
577
- mutation_execution_strategy
578
- when "subscription"
579
- subscription_execution_strategy
580
- else
581
- raise ArgumentError, "unknown operation type: #{operation}"
582
- end
583
- end
584
-
585
- # Determine the GraphQL type for a given object.
586
- # This is required for unions and interfaces (including Relay's `Node` interface)
587
- # @see [GraphQL::Schema::Warden] Restricted access to members of a schema
588
- # @param type [GraphQL::UnionType, GraphQL:InterfaceType] the abstract type which is being resolved
589
- # @param object [Any] An application object which GraphQL is currently resolving on
590
- # @param ctx [GraphQL::Query::Context] The context for the current query
591
- # @return [GraphQL::ObjectType] The type for exposing `object` in GraphQL
592
- def resolve_type(type, object, ctx = :__undefined__)
593
- check_resolved_type(type, object, ctx) do |ok_type, ok_object, ok_ctx|
594
- if @resolve_type_proc.nil?
595
- raise(GraphQL::RequiredImplementationMissingError, "Can't determine GraphQL type for: #{ok_object.inspect}, define `resolve_type (type, obj, ctx) -> { ... }` inside `Schema.define`.")
596
- end
597
- @resolve_type_proc.call(ok_type, ok_object, ok_ctx)
598
- end
599
- end
600
-
601
- # This is a compatibility hack so that instance-level and class-level
602
- # methods can get correctness checks without calling one another
603
- # @api private
604
- def check_resolved_type(type, object, ctx = :__undefined__)
605
- if ctx == :__undefined__
606
- # Old method signature
607
- ctx = object
608
- object = type
609
- type = nil
610
- end
611
-
612
- if object.is_a?(GraphQL::Schema::Object)
613
- object = object.object
614
- end
615
-
616
- if type.respond_to?(:graphql_definition)
617
- type = type.graphql_definition
618
- end
619
-
620
- # Prefer a type-local function; fall back to the schema-level function
621
- type_proc = type && type.resolve_type_proc
622
- type_result = if type_proc
623
- type_proc.call(object, ctx)
624
- else
625
- yield(type, object, ctx)
626
- end
627
-
628
- if type_result.nil?
629
- nil
630
- else
631
- after_lazy(type_result) do |resolved_type_result|
632
- if resolved_type_result.respond_to?(:graphql_definition)
633
- resolved_type_result = resolved_type_result.graphql_definition
634
- end
635
- if !resolved_type_result.is_a?(GraphQL::BaseType)
636
- type_str = "#{resolved_type_result} (#{resolved_type_result.class.name})"
637
- raise "resolve_type(#{object}) returned #{type_str}, but it should return a GraphQL type"
638
- else
639
- resolved_type_result
640
- end
641
- end
642
- end
643
- end
644
-
645
- def resolve_type=(new_resolve_type_proc)
646
- callable = GraphQL::BackwardsCompatibility.wrap_arity(new_resolve_type_proc, from: 2, to: 3, last: true, name: "Schema#resolve_type(type, obj, ctx)")
647
- @resolve_type_proc = callable
648
- end
649
-
650
- # Fetch an application object by its unique id
651
- # @param id [String] A unique identifier, provided previously by this GraphQL schema
652
- # @param ctx [GraphQL::Query::Context] The context for the current query
653
- # @return [Any] The application object identified by `id`
654
- def object_from_id(id, ctx)
655
- if @object_from_id_proc.nil?
656
- raise(GraphQL::RequiredImplementationMissingError, "Can't fetch an object for id \"#{id}\" because the schema's `object_from_id (id, ctx) -> { ... }` function is not defined")
657
- else
658
- @object_from_id_proc.call(id, ctx)
659
- end
660
- end
661
-
662
- # @param new_proc [#call] A new callable for fetching objects by ID
663
- def object_from_id=(new_proc)
664
- @object_from_id_proc = new_proc
665
- end
666
-
667
- # When we encounter a type error during query execution, we call this hook.
668
- #
669
- # You can use this hook to write a log entry,
670
- # add a {GraphQL::ExecutionError} to the response (with `ctx.add_error`)
671
- # or raise an exception and halt query execution.
672
- #
673
- # @example A `nil` is encountered by a non-null field
674
- # type_error ->(err, query_ctx) {
675
- # err.is_a?(GraphQL::InvalidNullError) # => true
676
- # }
677
- #
678
- # @example An object doesn't resolve to one of a {UnionType}'s members
679
- # type_error ->(err, query_ctx) {
680
- # err.is_a?(GraphQL::UnresolvedTypeError) # => true
681
- # }
682
- #
683
- # @see {DefaultTypeError} is the default behavior.
684
- # @param err [GraphQL::TypeError] The error encountered during execution
685
- # @param ctx [GraphQL::Query::Context] The context for the field where the error occurred
686
- # @return void
687
- def type_error(err, ctx)
688
- @type_error_proc.call(err, ctx)
689
- end
690
-
691
- # @param new_proc [#call] A new callable for handling type errors during execution
692
- def type_error=(new_proc)
693
- @type_error_proc = new_proc
694
- end
695
-
696
- # Can't delegate to `class`
697
- alias :_schema_class :class
698
- def_delegators :_schema_class, :unauthorized_object, :unauthorized_field, :inaccessible_fields
699
- def_delegators :_schema_class, :directive
700
- def_delegators :_schema_class, :error_handler
701
- def_delegators :_schema_class, :validate
702
-
703
-
704
- # Given this schema member, find the class-based definition object
705
- # whose `method_name` should be treated as an application hook
706
- # @see {.visible?}
707
- # @see {.accessible?}
708
- def call_on_type_class(member, method_name, context, default:)
709
- member = if member.respond_to?(:type_class)
710
- member.type_class
711
- else
712
- member
713
- end
714
-
715
- if member.respond_to?(:relay_node_type) && (t = member.relay_node_type)
716
- member = t
717
- end
718
-
719
- if member.respond_to?(method_name)
720
- member.public_send(method_name, context)
721
- else
722
- default
723
- end
724
- end
725
-
726
- def visible?(member, context)
727
- call_on_type_class(member, :visible?, context, default: true)
728
- end
729
-
730
- def accessible?(member, context)
731
- call_on_type_class(member, :accessible?, context, default: true)
732
- end
733
-
734
- # A function to call when {#execute} receives an invalid query string
735
- #
736
- # @see {DefaultParseError} is the default behavior.
737
- # @param err [GraphQL::ParseError] The error encountered during parsing
738
- # @param ctx [GraphQL::Query::Context] The context for the query where the error occurred
739
- # @return void
740
- def parse_error(err, ctx)
741
- @parse_error_proc.call(err, ctx)
742
- end
743
-
744
- # @param new_proc [#call] A new callable for handling parse errors during execution
745
- def parse_error=(new_proc)
746
- @parse_error_proc = new_proc
747
- end
748
-
749
- # Get a unique identifier from this object
750
- # @param object [Any] An application object
751
- # @param type [GraphQL::BaseType] The current type definition
752
- # @param ctx [GraphQL::Query::Context] the context for the current query
753
- # @return [String] a unique identifier for `object` which clients can use to refetch it
754
- def id_from_object(object, type, ctx)
755
- if @id_from_object_proc.nil?
756
- raise(GraphQL::RequiredImplementationMissingError, "Can't generate an ID for #{object.inspect} of type #{type}, schema's `id_from_object` must be defined")
757
- else
758
- @id_from_object_proc.call(object, type, ctx)
759
- end
760
- end
761
-
762
- # @param new_proc [#call] A new callable for generating unique IDs
763
- def id_from_object=(new_proc)
764
- @id_from_object_proc = new_proc
765
- end
766
-
767
- # Create schema with the result of an introspection query.
768
- # @param introspection_result [Hash] A response from {GraphQL::Introspection::INTROSPECTION_QUERY}
769
- # @return [GraphQL::Schema] the schema described by `input`
770
- def self.from_introspection(introspection_result)
771
- GraphQL::Schema::Loader.load(introspection_result)
772
- end
773
-
774
- # Create schema from an IDL schema or file containing an IDL definition.
775
- # @param definition_or_path [String] A schema definition string, or a path to a file containing the definition
776
- # @param default_resolve [<#call(type, field, obj, args, ctx)>] A callable for handling field resolution
777
- # @param parser [Object] An object for handling definition string parsing (must respond to `parse`)
778
- # @param using [Hash] Plugins to attach to the created schema with `use(key, value)`
779
- # @return [Class] the schema described by `document`
780
- def self.from_definition(definition_or_path, default_resolve: nil, parser: GraphQL.default_parser, using: {})
781
- # If the file ends in `.graphql`, treat it like a filepath
782
- if definition_or_path.end_with?(".graphql")
783
- GraphQL::Schema::BuildFromDefinition.from_definition_path(
784
- definition_or_path,
785
- default_resolve: default_resolve,
786
- parser: parser,
787
- using: using,
788
- )
789
- else
790
- GraphQL::Schema::BuildFromDefinition.from_definition(
791
- definition_or_path,
792
- default_resolve: default_resolve,
793
- parser: parser,
794
- using: using,
795
- )
796
- end
797
- end
798
-
799
- # Error that is raised when [#Schema#from_definition] is passed an invalid schema definition string.
800
- class InvalidDocumentError < Error; end;
801
-
802
- # Return the GraphQL IDL for the schema
803
- # @param context [Hash]
804
- # @param only [<#call(member, ctx)>]
805
- # @param except [<#call(member, ctx)>]
806
- # @return [String]
807
- def to_definition(only: nil, except: nil, context: {})
808
- GraphQL::Schema::Printer.print_schema(self, only: only, except: except, context: context)
809
- end
810
-
811
- # Return the GraphQL::Language::Document IDL AST for the schema
812
- # @param context [Hash]
813
- # @param only [<#call(member, ctx)>]
814
- # @param except [<#call(member, ctx)>]
815
- # @return [GraphQL::Language::Document]
816
- def to_document(only: nil, except: nil, context: {})
817
- GraphQL::Language::DocumentFromSchemaDefinition.new(self, only: only, except: except, context: context).document
818
- end
819
-
820
- # Return the Hash response of {Introspection::INTROSPECTION_QUERY}.
821
- # @param context [Hash]
822
- # @param only [<#call(member, ctx)>]
823
- # @param except [<#call(member, ctx)>]
824
- # @return [Hash] GraphQL result
825
- def as_json(only: nil, except: nil, context: {})
826
- execute(Introspection.query(include_deprecated_args: true), only: only, except: except, context: context).to_h
827
- end
828
-
829
- # Returns the JSON response of {Introspection::INTROSPECTION_QUERY}.
830
- # @see {#as_json}
831
- # @return [String]
832
- def to_json(*args)
833
- JSON.pretty_generate(as_json(*args))
834
- end
835
-
836
- def new_connections?
837
- !!connections
838
- end
839
-
840
- attr_accessor :connections
841
-
842
- class << self
843
- extend Forwardable
844
- # For compatibility, these methods all:
845
- # - Cause the Schema instance to be created, if it hasn't been created yet
846
- # - Delegate to that instance
847
- # Eventually, the methods will be moved into this class, removing the need for the singleton.
848
- def_delegators :deprecated_graphql_definition,
849
- # Execution
850
- :execution_strategy_for_operation,
851
- # Configuration
852
- :metadata, :redefine,
853
- :id_from_object_proc, :object_from_id_proc,
854
- :id_from_object=, :object_from_id=,
855
- :remove_handler
856
127
 
857
128
  def deprecated_graphql_definition
858
129
  graphql_definition(silence_deprecation_warning: true)
@@ -911,17 +182,6 @@ module GraphQL
911
182
  @find_cache[path] ||= @finder.find(path)
912
183
  end
913
184
 
914
- def graphql_definition(silence_deprecation_warning: false)
915
- @graphql_definition ||= begin
916
- unless silence_deprecation_warning
917
- message = "Legacy `.graphql_definition` objects are deprecated and will be removed in GraphQL-Ruby 2.0. Use a class-based definition instead."
918
- caller_message = "\n\nCalled on #{self.inspect} from:\n #{caller(1, 25).map { |l| " #{l}" }.join("\n")}"
919
- GraphQL::Deprecation.warn(message + caller_message)
920
- end
921
- to_graphql(silence_deprecation_warning: silence_deprecation_warning)
922
- end
923
- end
924
-
925
185
  def default_filter
926
186
  GraphQL::Filter.new(except: default_mask)
927
187
  end
@@ -951,73 +211,6 @@ module GraphQL
951
211
  find_inherited_value(:plugins, EMPTY_ARRAY) + own_plugins
952
212
  end
953
213
 
954
- prepend Schema::Member::CachedGraphQLDefinition::DeprecatedToGraphQL
955
- def to_graphql
956
- schema_defn = self.new
957
- schema_defn.raise_definition_error = true
958
- schema_defn.query = query && query.graphql_definition(silence_deprecation_warning: true)
959
- schema_defn.mutation = mutation && mutation.graphql_definition(silence_deprecation_warning: true)
960
- schema_defn.subscription = subscription && subscription.graphql_definition(silence_deprecation_warning: true)
961
- schema_defn.validate_timeout = validate_timeout
962
- schema_defn.validate_max_errors = validate_max_errors
963
- schema_defn.max_complexity = max_complexity
964
- schema_defn.error_bubbling = error_bubbling
965
- schema_defn.max_depth = max_depth
966
- schema_defn.default_max_page_size = default_max_page_size
967
- schema_defn.orphan_types = orphan_types.map { |t| t.graphql_definition(silence_deprecation_warning: true) }
968
- schema_defn.disable_introspection_entry_points = disable_introspection_entry_points?
969
- schema_defn.disable_schema_introspection_entry_point = disable_schema_introspection_entry_point?
970
- schema_defn.disable_type_introspection_entry_point = disable_type_introspection_entry_point?
971
-
972
- prepped_dirs = {}
973
- directives.each { |k, v| prepped_dirs[k] = v.graphql_definition}
974
- schema_defn.directives = prepped_dirs
975
- schema_defn.introspection_namespace = introspection
976
- schema_defn.resolve_type = method(:resolve_type)
977
- schema_defn.object_from_id = method(:object_from_id)
978
- schema_defn.id_from_object = method(:id_from_object)
979
- schema_defn.type_error = method(:type_error)
980
- schema_defn.context_class = context_class
981
- schema_defn.cursor_encoder = cursor_encoder
982
- schema_defn.tracers.concat(tracers)
983
- schema_defn.query_analyzers.concat(query_analyzers)
984
- schema_defn.analysis_engine = analysis_engine
985
-
986
- schema_defn.middleware.concat(all_middleware)
987
- schema_defn.multiplex_analyzers.concat(multiplex_analyzers)
988
- schema_defn.query_execution_strategy = query_execution_strategy
989
- schema_defn.mutation_execution_strategy = mutation_execution_strategy
990
- schema_defn.subscription_execution_strategy = subscription_execution_strategy
991
- schema_defn.default_mask = default_mask
992
- instrumenters.each do |step, insts|
993
- insts.each do |inst|
994
- schema_defn.instrumenters[step] << inst
995
- end
996
- end
997
-
998
- lazy_methods.each do |lazy_class, value_method|
999
- schema_defn.lazy_methods.set(lazy_class, value_method)
1000
- end
1001
-
1002
- error_handler.each_rescue do |err_class, handler|
1003
- schema_defn.rescue_from(err_class, &handler)
1004
- end
1005
-
1006
- schema_defn.subscriptions ||= self.subscriptions
1007
-
1008
- if !schema_defn.interpreter?
1009
- schema_defn.instrumenters[:query] << GraphQL::Schema::Member::Instrumentation
1010
- end
1011
-
1012
- if new_connections?
1013
- schema_defn.connections = self.connections
1014
- end
1015
-
1016
- schema_defn.send(:rebuild_artifacts)
1017
-
1018
- schema_defn
1019
- end
1020
-
1021
214
  # Build a map of `{ name => type }` and return it
1022
215
  # @return [Hash<String => Class>] A dictionary of type classes by their GraphQL name
1023
216
  # @see get_type Which is more efficient for finding _one type_ by name, because it doesn't merge hashes.
@@ -1172,9 +365,7 @@ module GraphQL
1172
365
  stored_possible_types = own_possible_types[type.graphql_name]
1173
366
  visible_possible_types = if stored_possible_types && type.kind.interface?
1174
367
  stored_possible_types.select do |possible_type|
1175
- # Use `.graphql_name` comparison to match legacy vs class-based types.
1176
- # When we don't need to support legacy `.define` types, use `.include?(type)` instead.
1177
- possible_type.interfaces(context).any? { |interface| interface.graphql_name == type.graphql_name }
368
+ possible_type.interfaces(context).include?(type)
1178
369
  end
1179
370
  else
1180
371
  stored_possible_types
@@ -1393,13 +584,11 @@ module GraphQL
1393
584
  end
1394
585
 
1395
586
  def using_ast_analysis?
1396
- analysis_engine == GraphQL::Analysis::AST
587
+ true
1397
588
  end
1398
589
 
1399
590
  def interpreter?
1400
- query_execution_strategy == GraphQL::Execution::Interpreter &&
1401
- mutation_execution_strategy == GraphQL::Execution::Interpreter &&
1402
- subscription_execution_strategy == GraphQL::Execution::Interpreter
591
+ true
1403
592
  end
1404
593
 
1405
594
  attr_writer :interpreter
@@ -1518,7 +707,7 @@ module GraphQL
1518
707
  end
1519
708
 
1520
709
  after_lazy(first_resolved_type) do |resolved_type|
1521
- if resolved_type.nil? || (resolved_type.is_a?(Module) && resolved_type.respond_to?(:kind)) || resolved_type.is_a?(GraphQL::BaseType)
710
+ if resolved_type.nil? || (resolved_type.is_a?(Module) && resolved_type.respond_to?(:kind))
1522
711
  if resolved_value
1523
712
  [resolved_type, resolved_value]
1524
713
  else
@@ -1557,11 +746,11 @@ module GraphQL
1557
746
  end
1558
747
 
1559
748
  def visible?(member, ctx)
1560
- member.type_class.visible?(ctx)
749
+ member.visible?(ctx)
1561
750
  end
1562
751
 
1563
752
  def accessible?(member, ctx)
1564
- member.type_class.accessible?(ctx)
753
+ member.accessible?(ctx)
1565
754
  end
1566
755
 
1567
756
  # This hook is called when a client tries to access one or more
@@ -1611,8 +800,15 @@ module GraphQL
1611
800
  unauthorized_object(unauthorized_error)
1612
801
  end
1613
802
 
1614
- def type_error(type_err, ctx)
1615
- DefaultTypeError.call(type_err, ctx)
803
+ def type_error(type_error, ctx)
804
+ case type_error
805
+ when GraphQL::InvalidNullError
806
+ ctx.errors << type_error
807
+ when GraphQL::UnresolvedTypeError, GraphQL::StringEncodingError, GraphQL::IntegerEncodingError
808
+ raise type_error
809
+ when GraphQL::IntegerDecodingError
810
+ nil
811
+ end
1616
812
  end
1617
813
 
1618
814
  # A function to call when {#execute} receives an invalid query string
@@ -1635,17 +831,7 @@ module GraphQL
1635
831
  end
1636
832
 
1637
833
  def instrument(instrument_step, instrumenter, options = {})
1638
- if instrument_step == :field
1639
- GraphQL::Deprecation.warn "Field instrumentation (#{instrumenter.inspect}) will be removed in GraphQL-Ruby 2.0, please upgrade to field extensions: https://graphql-ruby.org/type_definitions/field_extensions.html"
1640
- end
1641
-
1642
- step = if instrument_step == :field && options[:after_built_ins]
1643
- :field_after_built_ins
1644
- else
1645
- instrument_step
1646
- end
1647
-
1648
- own_instrumenters[step] << instrumenter
834
+ own_instrumenters[instrument_step] << instrumenter
1649
835
  end
1650
836
 
1651
837
  # Add several directives at once
@@ -1682,9 +868,6 @@ module GraphQL
1682
868
  end
1683
869
 
1684
870
  def query_analyzer(new_analyzer)
1685
- if new_analyzer == GraphQL::Authorization::Analyzer
1686
- GraphQL::Deprecation.warn("The Authorization query analyzer is deprecated. Authorizing at query runtime is generally a better idea.")
1687
- end
1688
871
  own_query_analyzers << new_analyzer
1689
872
  end
1690
873
 
@@ -1692,16 +875,6 @@ module GraphQL
1692
875
  find_inherited_value(:query_analyzers, EMPTY_ARRAY) + own_query_analyzers
1693
876
  end
1694
877
 
1695
- def middleware(new_middleware = nil)
1696
- if new_middleware
1697
- GraphQL::Deprecation.warn "Middleware will be removed in GraphQL-Ruby 2.0, please upgrade to Field Extensions: https://graphql-ruby.org/type_definitions/field_extensions.html"
1698
- own_middleware << new_middleware
1699
- else
1700
- # TODO make sure this is cached when running a query
1701
- MiddlewareChain.new(steps: all_middleware, final_step: GraphQL::Execution::Execute::FieldResolveStep)
1702
- end
1703
- end
1704
-
1705
878
  def multiplex_analyzer(new_analyzer)
1706
879
  own_multiplex_analyzers << new_analyzer
1707
880
  end
@@ -1730,7 +903,6 @@ module GraphQL
1730
903
  {
1731
904
  backtrace: ctx[:backtrace],
1732
905
  tracers: ctx[:tracers],
1733
- dataloader: ctx[:dataloader],
1734
906
  }
1735
907
  else
1736
908
  {}
@@ -1755,17 +927,12 @@ module GraphQL
1755
927
  # }
1756
928
  #
1757
929
  # @see {Query#initialize} for query keyword arguments
1758
- # @see {Execution::Multiplex#run_queries} for multiplex keyword arguments
930
+ # @see {Execution::Multiplex#run_all} for multiplex keyword arguments
1759
931
  # @param queries [Array<Hash>] Keyword arguments for each query
1760
932
  # @param context [Hash] Multiplex-level context
1761
933
  # @return [Array<Hash>] One result for each query in the input
1762
934
  def multiplex(queries, **kwargs)
1763
- schema = if interpreter?
1764
- self
1765
- else
1766
- graphql_definition
1767
- end
1768
- GraphQL::Execution::Multiplex.run_all(schema, queries, **kwargs)
935
+ GraphQL::Execution::Multiplex.run_all(self, queries, **kwargs)
1769
936
  end
1770
937
 
1771
938
  def instrumenters
@@ -1777,14 +944,10 @@ module GraphQL
1777
944
 
1778
945
  # @api private
1779
946
  def add_subscription_extension_if_necessary
1780
- if interpreter? && !defined?(@subscription_extension_added) && subscription && self.subscriptions
947
+ if !defined?(@subscription_extension_added) && subscription && self.subscriptions
1781
948
  @subscription_extension_added = true
1782
- if subscription.singleton_class.ancestors.include?(Subscriptions::SubscriptionRoot)
1783
- GraphQL::Deprecation.warn("`extend Subscriptions::SubscriptionRoot` is no longer required; you may remove it from #{self}'s `subscription` root type (#{subscription}).")
1784
- else
1785
- subscription.all_field_definitions.each do |field|
1786
- field.extension(Subscriptions::DefaultSubscriptionResolveExtension)
1787
- end
949
+ subscription.all_field_definitions.each do |field|
950
+ field.extension(Subscriptions::DefaultSubscriptionResolveExtension)
1788
951
  end
1789
952
  end
1790
953
  end
@@ -1793,6 +956,60 @@ module GraphQL
1793
956
  query.context.errors.push(GraphQL::ExecutionError.new("This query is too large to execute."))
1794
957
  end
1795
958
 
959
+ # Call the given block at the right time, either:
960
+ # - Right away, if `value` is not registered with `lazy_resolve`
961
+ # - After resolving `value`, if it's registered with `lazy_resolve` (eg, `Promise`)
962
+ # @api private
963
+ def after_lazy(value, &block)
964
+ if lazy?(value)
965
+ GraphQL::Execution::Lazy.new do
966
+ result = sync_lazy(value)
967
+ # The returned result might also be lazy, so check it, too
968
+ after_lazy(result, &block)
969
+ end
970
+ else
971
+ yield(value) if block_given?
972
+ end
973
+ end
974
+
975
+ # Override this method to handle lazy objects in a custom way.
976
+ # @param value [Object] an instance of a class registered with {.lazy_resolve}
977
+ # @return [Object] A GraphQL-ready (non-lazy) object
978
+ # @api private
979
+ def sync_lazy(value)
980
+ lazy_method = lazy_method_name(value)
981
+ if lazy_method
982
+ synced_value = value.public_send(lazy_method)
983
+ sync_lazy(synced_value)
984
+ else
985
+ value
986
+ end
987
+ end
988
+
989
+ # @return [Symbol, nil] The method name to lazily resolve `obj`, or nil if `obj`'s class wasn't registered with {#lazy_resolve}.
990
+ def lazy_method_name(obj)
991
+ lazy_methods.get(obj)
992
+ end
993
+
994
+ # @return [Boolean] True if this object should be lazily resolved
995
+ def lazy?(obj)
996
+ !!lazy_method_name(obj)
997
+ end
998
+
999
+ # Return a lazy if any of `maybe_lazies` are lazy,
1000
+ # otherwise, call the block eagerly and return the result.
1001
+ # @param maybe_lazies [Array]
1002
+ # @api private
1003
+ def after_any_lazies(maybe_lazies)
1004
+ if maybe_lazies.any? { |l| lazy?(l) }
1005
+ GraphQL::Execution::Lazy.all(maybe_lazies).then do |result|
1006
+ yield result
1007
+ end
1008
+ else
1009
+ yield maybe_lazies
1010
+ end
1011
+ end
1012
+
1796
1013
  private
1797
1014
 
1798
1015
  # @param t [Module, Array<Module>]
@@ -1902,68 +1119,12 @@ module GraphQL
1902
1119
  @defined_query_analyzers ||= []
1903
1120
  end
1904
1121
 
1905
- def all_middleware
1906
- find_inherited_value(:all_middleware, EMPTY_ARRAY) + own_middleware
1907
- end
1908
-
1909
- def own_middleware
1910
- @own_middleware ||= []
1911
- end
1912
-
1913
1122
  def own_multiplex_analyzers
1914
1123
  @own_multiplex_analyzers ||= []
1915
1124
  end
1916
1125
  end
1917
1126
 
1918
- def dataloader_class
1919
- self.class.dataloader_class
1920
- end
1921
-
1922
1127
  # Install these here so that subclasses will also install it.
1923
- use(GraphQL::Pagination::Connections)
1924
-
1925
- protected
1926
-
1927
- def rescues?
1928
- !!@rescue_middleware
1929
- end
1930
-
1931
- # Lazily create a middleware and add it to the schema
1932
- # (Don't add it if it's not used)
1933
- def rescue_middleware
1934
- @rescue_middleware ||= GraphQL::Schema::RescueMiddleware.new.tap { |m| middleware.insert(0, m) }
1935
- end
1936
-
1937
- private
1938
-
1939
- def rebuild_artifacts
1940
- if @rebuilding_artifacts
1941
- raise CyclicalDefinitionError, "Part of the schema build process re-triggered the schema build process, causing an infinite loop. Avoid using Schema#types, Schema#possible_types, and Schema#get_field during schema build."
1942
- else
1943
- @rebuilding_artifacts = true
1944
- @introspection_system = Schema::IntrospectionSystem.new(self)
1945
- traversal = Traversal.new(self)
1946
- @types = traversal.type_map
1947
- @root_types = [query, mutation, subscription]
1948
- @instrumented_field_map = traversal.instrumented_field_map
1949
- @type_reference_map = traversal.type_reference_map
1950
- @union_memberships = traversal.union_memberships
1951
- @find_cache = {}
1952
- @finder = Finder.new(self)
1953
- end
1954
- ensure
1955
- @rebuilding_artifacts = false
1956
- end
1957
-
1958
- class CyclicalDefinitionError < GraphQL::Error
1959
- end
1960
-
1961
- def with_definition_error_check
1962
- if @definition_error
1963
- raise @definition_error
1964
- else
1965
- yield
1966
- end
1967
- end
1128
+ self.connections = GraphQL::Pagination::Connections.new(schema: self)
1968
1129
  end
1969
1130
  end