graphql 1.13.6 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of graphql might be problematic. Click here for more details.

Files changed (216) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/core.rb +0 -7
  3. data/lib/generators/graphql/enum_generator.rb +4 -10
  4. data/lib/generators/graphql/field_extractor.rb +31 -0
  5. data/lib/generators/graphql/input_generator.rb +50 -0
  6. data/lib/generators/graphql/install/mutation_root_generator.rb +34 -0
  7. data/lib/generators/graphql/{templates → install/templates}/base_mutation.erb +0 -0
  8. data/lib/generators/graphql/{templates → install/templates}/mutation_type.erb +0 -0
  9. data/lib/generators/graphql/install_generator.rb +1 -1
  10. data/lib/generators/graphql/interface_generator.rb +7 -7
  11. data/lib/generators/graphql/mutation_create_generator.rb +22 -0
  12. data/lib/generators/graphql/mutation_delete_generator.rb +22 -0
  13. data/lib/generators/graphql/mutation_generator.rb +5 -30
  14. data/lib/generators/graphql/mutation_update_generator.rb +22 -0
  15. data/lib/generators/graphql/object_generator.rb +8 -37
  16. data/lib/generators/graphql/orm_mutations_base.rb +40 -0
  17. data/lib/generators/graphql/scalar_generator.rb +4 -2
  18. data/lib/generators/graphql/templates/enum.erb +5 -1
  19. data/lib/generators/graphql/templates/input.erb +9 -0
  20. data/lib/generators/graphql/templates/interface.erb +4 -2
  21. data/lib/generators/graphql/templates/mutation.erb +1 -1
  22. data/lib/generators/graphql/templates/mutation_create.erb +20 -0
  23. data/lib/generators/graphql/templates/mutation_delete.erb +20 -0
  24. data/lib/generators/graphql/templates/mutation_update.erb +21 -0
  25. data/lib/generators/graphql/templates/object.erb +4 -2
  26. data/lib/generators/graphql/templates/scalar.erb +3 -1
  27. data/lib/generators/graphql/templates/union.erb +4 -2
  28. data/lib/generators/graphql/type_generator.rb +46 -9
  29. data/lib/generators/graphql/union_generator.rb +5 -5
  30. data/lib/graphql/analysis/ast/query_complexity.rb +1 -1
  31. data/lib/graphql/analysis/ast/query_depth.rb +0 -1
  32. data/lib/graphql/analysis/ast/visitor.rb +3 -2
  33. data/lib/graphql/analysis/ast.rb +0 -10
  34. data/lib/graphql/analysis.rb +0 -7
  35. data/lib/graphql/backtrace/table.rb +0 -18
  36. data/lib/graphql/backtrace/tracer.rb +1 -2
  37. data/lib/graphql/backtrace.rb +2 -8
  38. data/lib/graphql/dataloader/source.rb +2 -2
  39. data/lib/graphql/dig.rb +1 -1
  40. data/lib/graphql/execution/errors.rb +1 -9
  41. data/lib/graphql/execution/interpreter/runtime.rb +2 -9
  42. data/lib/graphql/execution/interpreter.rb +0 -22
  43. data/lib/graphql/execution/lazy.rb +1 -1
  44. data/lib/graphql/execution/lookahead.rb +6 -13
  45. data/lib/graphql/execution/multiplex.rb +50 -107
  46. data/lib/graphql/execution.rb +11 -3
  47. data/lib/graphql/introspection/dynamic_fields.rb +3 -8
  48. data/lib/graphql/introspection/entry_points.rb +2 -15
  49. data/lib/graphql/introspection.rb +4 -4
  50. data/lib/graphql/language/document_from_schema_definition.rb +0 -17
  51. data/lib/graphql/pagination/connections.rb +2 -28
  52. data/lib/graphql/query/context.rb +1 -185
  53. data/lib/graphql/query/literal_input.rb +8 -13
  54. data/lib/graphql/query/validation_pipeline.rb +8 -37
  55. data/lib/graphql/query/variables.rb +22 -18
  56. data/lib/graphql/query.rb +5 -35
  57. data/lib/graphql/railtie.rb +0 -104
  58. data/lib/graphql/relay.rb +0 -15
  59. data/lib/graphql/rubocop/graphql/default_required_true.rb +4 -4
  60. data/lib/graphql/schema/addition.rb +1 -8
  61. data/lib/graphql/schema/argument.rb +18 -25
  62. data/lib/graphql/schema/build_from_definition.rb +0 -1
  63. data/lib/graphql/schema/directive.rb +4 -21
  64. data/lib/graphql/schema/enum.rb +1 -18
  65. data/lib/graphql/schema/enum_value.rb +0 -22
  66. data/lib/graphql/schema/field.rb +22 -194
  67. data/lib/graphql/schema/input_object.rb +10 -57
  68. data/lib/graphql/schema/interface.rb +0 -25
  69. data/lib/graphql/schema/introspection_system.rb +3 -8
  70. data/lib/graphql/schema/late_bound_type.rb +2 -2
  71. data/lib/graphql/schema/list.rb +0 -6
  72. data/lib/graphql/schema/loader.rb +0 -1
  73. data/lib/graphql/schema/member/base_dsl_methods.rb +0 -5
  74. data/lib/graphql/schema/member/build_type.rb +4 -6
  75. data/lib/graphql/schema/member/has_arguments.rb +14 -18
  76. data/lib/graphql/schema/member/has_fields.rb +2 -2
  77. data/lib/graphql/schema/member/has_interfaces.rb +0 -2
  78. data/lib/graphql/schema/member.rb +0 -6
  79. data/lib/graphql/schema/mutation.rb +0 -9
  80. data/lib/graphql/schema/non_null.rb +1 -7
  81. data/lib/graphql/schema/object.rb +0 -40
  82. data/lib/graphql/schema/relay_classic_mutation.rb +17 -28
  83. data/lib/graphql/schema/scalar.rb +0 -15
  84. data/lib/graphql/schema/union.rb +0 -16
  85. data/lib/graphql/schema/warden.rb +1 -1
  86. data/lib/graphql/schema/wrapper.rb +0 -5
  87. data/lib/graphql/schema.rb +107 -949
  88. data/lib/graphql/static_validation/base_visitor.rb +4 -21
  89. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +12 -12
  90. data/lib/graphql/static_validation/validator.rb +2 -24
  91. data/lib/graphql/static_validation.rb +0 -2
  92. data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +38 -1
  93. data/lib/graphql/subscriptions/event.rb +1 -1
  94. data/lib/graphql/subscriptions/instrumentation.rb +0 -51
  95. data/lib/graphql/subscriptions.rb +4 -13
  96. data/lib/graphql/tracing/platform_tracing.rb +0 -23
  97. data/lib/graphql/tracing.rb +0 -1
  98. data/lib/graphql/types/iso_8601_date_time.rb +8 -1
  99. data/lib/graphql/types/relay/connection_behaviors.rb +4 -7
  100. data/lib/graphql/types/relay/default_relay.rb +0 -10
  101. data/lib/graphql/types/relay/node_behaviors.rb +5 -1
  102. data/lib/graphql/types/relay.rb +0 -2
  103. data/lib/graphql/version.rb +1 -1
  104. data/lib/graphql.rb +12 -65
  105. metadata +15 -129
  106. data/lib/graphql/analysis/analyze_query.rb +0 -98
  107. data/lib/graphql/analysis/field_usage.rb +0 -45
  108. data/lib/graphql/analysis/max_query_complexity.rb +0 -26
  109. data/lib/graphql/analysis/max_query_depth.rb +0 -26
  110. data/lib/graphql/analysis/query_complexity.rb +0 -88
  111. data/lib/graphql/analysis/query_depth.rb +0 -43
  112. data/lib/graphql/analysis/reducer_state.rb +0 -48
  113. data/lib/graphql/argument.rb +0 -131
  114. data/lib/graphql/authorization.rb +0 -82
  115. data/lib/graphql/backtrace/legacy_tracer.rb +0 -56
  116. data/lib/graphql/backwards_compatibility.rb +0 -61
  117. data/lib/graphql/base_type.rb +0 -232
  118. data/lib/graphql/boolean_type.rb +0 -2
  119. data/lib/graphql/compatibility/execution_specification/counter_schema.rb +0 -53
  120. data/lib/graphql/compatibility/execution_specification/specification_schema.rb +0 -200
  121. data/lib/graphql/compatibility/execution_specification.rb +0 -436
  122. data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +0 -111
  123. data/lib/graphql/compatibility/lazy_execution_specification.rb +0 -215
  124. data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +0 -87
  125. data/lib/graphql/compatibility/query_parser_specification/query_assertions.rb +0 -79
  126. data/lib/graphql/compatibility/query_parser_specification.rb +0 -266
  127. data/lib/graphql/compatibility/schema_parser_specification.rb +0 -682
  128. data/lib/graphql/compatibility.rb +0 -5
  129. data/lib/graphql/define/assign_argument.rb +0 -12
  130. data/lib/graphql/define/assign_connection.rb +0 -13
  131. data/lib/graphql/define/assign_enum_value.rb +0 -18
  132. data/lib/graphql/define/assign_global_id_field.rb +0 -11
  133. data/lib/graphql/define/assign_mutation_function.rb +0 -34
  134. data/lib/graphql/define/assign_object_field.rb +0 -42
  135. data/lib/graphql/define/defined_object_proxy.rb +0 -53
  136. data/lib/graphql/define/instance_definable.rb +0 -240
  137. data/lib/graphql/define/no_definition_error.rb +0 -7
  138. data/lib/graphql/define/non_null_with_bang.rb +0 -16
  139. data/lib/graphql/define/type_definer.rb +0 -31
  140. data/lib/graphql/define.rb +0 -31
  141. data/lib/graphql/deprecated_dsl.rb +0 -55
  142. data/lib/graphql/directive/deprecated_directive.rb +0 -2
  143. data/lib/graphql/directive/include_directive.rb +0 -2
  144. data/lib/graphql/directive/skip_directive.rb +0 -2
  145. data/lib/graphql/directive.rb +0 -107
  146. data/lib/graphql/enum_type.rb +0 -133
  147. data/lib/graphql/execution/execute.rb +0 -333
  148. data/lib/graphql/execution/flatten.rb +0 -40
  149. data/lib/graphql/execution/typecast.rb +0 -50
  150. data/lib/graphql/field/resolve.rb +0 -59
  151. data/lib/graphql/field.rb +0 -226
  152. data/lib/graphql/float_type.rb +0 -2
  153. data/lib/graphql/function.rb +0 -128
  154. data/lib/graphql/id_type.rb +0 -2
  155. data/lib/graphql/input_object_type.rb +0 -138
  156. data/lib/graphql/int_type.rb +0 -2
  157. data/lib/graphql/interface_type.rb +0 -72
  158. data/lib/graphql/internal_representation/document.rb +0 -27
  159. data/lib/graphql/internal_representation/node.rb +0 -206
  160. data/lib/graphql/internal_representation/print.rb +0 -51
  161. data/lib/graphql/internal_representation/rewrite.rb +0 -184
  162. data/lib/graphql/internal_representation/scope.rb +0 -88
  163. data/lib/graphql/internal_representation/visit.rb +0 -36
  164. data/lib/graphql/internal_representation.rb +0 -7
  165. data/lib/graphql/list_type.rb +0 -80
  166. data/lib/graphql/non_null_type.rb +0 -71
  167. data/lib/graphql/object_type.rb +0 -130
  168. data/lib/graphql/query/arguments.rb +0 -189
  169. data/lib/graphql/query/arguments_cache.rb +0 -24
  170. data/lib/graphql/query/executor.rb +0 -52
  171. data/lib/graphql/query/serial_execution/field_resolution.rb +0 -92
  172. data/lib/graphql/query/serial_execution/operation_resolution.rb +0 -19
  173. data/lib/graphql/query/serial_execution/selection_resolution.rb +0 -23
  174. data/lib/graphql/query/serial_execution/value_resolution.rb +0 -87
  175. data/lib/graphql/query/serial_execution.rb +0 -40
  176. data/lib/graphql/relay/array_connection.rb +0 -83
  177. data/lib/graphql/relay/base_connection.rb +0 -189
  178. data/lib/graphql/relay/connection_instrumentation.rb +0 -54
  179. data/lib/graphql/relay/connection_resolve.rb +0 -43
  180. data/lib/graphql/relay/connection_type.rb +0 -41
  181. data/lib/graphql/relay/edge.rb +0 -27
  182. data/lib/graphql/relay/edge_type.rb +0 -19
  183. data/lib/graphql/relay/edges_instrumentation.rb +0 -39
  184. data/lib/graphql/relay/global_id_resolve.rb +0 -18
  185. data/lib/graphql/relay/mongo_relation_connection.rb +0 -50
  186. data/lib/graphql/relay/mutation/instrumentation.rb +0 -23
  187. data/lib/graphql/relay/mutation/resolve.rb +0 -56
  188. data/lib/graphql/relay/mutation/result.rb +0 -38
  189. data/lib/graphql/relay/mutation.rb +0 -106
  190. data/lib/graphql/relay/node.rb +0 -39
  191. data/lib/graphql/relay/page_info.rb +0 -7
  192. data/lib/graphql/relay/relation_connection.rb +0 -188
  193. data/lib/graphql/relay/type_extensions.rb +0 -32
  194. data/lib/graphql/scalar_type.rb +0 -91
  195. data/lib/graphql/schema/catchall_middleware.rb +0 -35
  196. data/lib/graphql/schema/default_parse_error.rb +0 -10
  197. data/lib/graphql/schema/default_type_error.rb +0 -17
  198. data/lib/graphql/schema/member/accepts_definition.rb +0 -164
  199. data/lib/graphql/schema/member/cached_graphql_definition.rb +0 -58
  200. data/lib/graphql/schema/member/instrumentation.rb +0 -131
  201. data/lib/graphql/schema/middleware_chain.rb +0 -82
  202. data/lib/graphql/schema/possible_types.rb +0 -44
  203. data/lib/graphql/schema/rescue_middleware.rb +0 -60
  204. data/lib/graphql/schema/timeout_middleware.rb +0 -88
  205. data/lib/graphql/schema/traversal.rb +0 -228
  206. data/lib/graphql/schema/validation.rb +0 -313
  207. data/lib/graphql/static_validation/default_visitor.rb +0 -15
  208. data/lib/graphql/static_validation/no_validate_visitor.rb +0 -10
  209. data/lib/graphql/string_type.rb +0 -2
  210. data/lib/graphql/subscriptions/subscription_root.rb +0 -76
  211. data/lib/graphql/tracing/skylight_tracing.rb +0 -70
  212. data/lib/graphql/types/relay/node_field.rb +0 -24
  213. data/lib/graphql/types/relay/nodes_field.rb +0 -43
  214. data/lib/graphql/union_type.rb +0 -115
  215. data/lib/graphql/upgrader/member.rb +0 -937
  216. 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
- 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
525
- end
526
- 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
119
+ GraphQL::Schema::BuildFromDefinition.from_definition(
120
+ definition_or_path,
121
+ default_resolve: default_resolve,
122
+ parser: parser,
123
+ using: using,
124
+ )
641
125
  end
642
126
  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
@@ -1258,11 +449,7 @@ module GraphQL
1258
449
  when Module
1259
450
  type_or_name
1260
451
  else
1261
- raise ArgumentError, <<-ERR
1262
- Invariant: unexpected field owner for #{field_name.inspect}: #{type_or_name.inspect} (#{type_or_name.class})
1263
-
1264
- This is probably a bug in GraphQL-Ruby, please report this error on GitHub: https://github.com/rmosolgo/graphql-ruby/issues/new?template=bug_report.md
1265
- ERR
452
+ raise GraphQL::InvariantError, "Unexpected field owner for #{field_name.inspect}: #{type_or_name.inspect} (#{type_or_name.class})"
1266
453
  end
1267
454
 
1268
455
  if parent_type.kind.fields? && (field = parent_type.get_field(field_name, context))
@@ -1397,13 +584,11 @@ ERR
1397
584
  end
1398
585
 
1399
586
  def using_ast_analysis?
1400
- analysis_engine == GraphQL::Analysis::AST
587
+ true
1401
588
  end
1402
589
 
1403
590
  def interpreter?
1404
- query_execution_strategy == GraphQL::Execution::Interpreter &&
1405
- mutation_execution_strategy == GraphQL::Execution::Interpreter &&
1406
- subscription_execution_strategy == GraphQL::Execution::Interpreter
591
+ true
1407
592
  end
1408
593
 
1409
594
  attr_writer :interpreter
@@ -1522,7 +707,7 @@ ERR
1522
707
  end
1523
708
 
1524
709
  after_lazy(first_resolved_type) do |resolved_type|
1525
- 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))
1526
711
  if resolved_value
1527
712
  [resolved_type, resolved_value]
1528
713
  else
@@ -1561,11 +746,11 @@ ERR
1561
746
  end
1562
747
 
1563
748
  def visible?(member, ctx)
1564
- member.type_class.visible?(ctx)
749
+ member.visible?(ctx)
1565
750
  end
1566
751
 
1567
752
  def accessible?(member, ctx)
1568
- member.type_class.accessible?(ctx)
753
+ member.accessible?(ctx)
1569
754
  end
1570
755
 
1571
756
  # This hook is called when a client tries to access one or more
@@ -1615,8 +800,15 @@ ERR
1615
800
  unauthorized_object(unauthorized_error)
1616
801
  end
1617
802
 
1618
- def type_error(type_err, ctx)
1619
- 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
1620
812
  end
1621
813
 
1622
814
  # A function to call when {#execute} receives an invalid query string
@@ -1639,17 +831,7 @@ ERR
1639
831
  end
1640
832
 
1641
833
  def instrument(instrument_step, instrumenter, options = {})
1642
- if instrument_step == :field
1643
- 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"
1644
- end
1645
-
1646
- step = if instrument_step == :field && options[:after_built_ins]
1647
- :field_after_built_ins
1648
- else
1649
- instrument_step
1650
- end
1651
-
1652
- own_instrumenters[step] << instrumenter
834
+ own_instrumenters[instrument_step] << instrumenter
1653
835
  end
1654
836
 
1655
837
  # Add several directives at once
@@ -1686,9 +868,6 @@ ERR
1686
868
  end
1687
869
 
1688
870
  def query_analyzer(new_analyzer)
1689
- if new_analyzer == GraphQL::Authorization::Analyzer
1690
- GraphQL::Deprecation.warn("The Authorization query analyzer is deprecated. Authorizing at query runtime is generally a better idea.")
1691
- end
1692
871
  own_query_analyzers << new_analyzer
1693
872
  end
1694
873
 
@@ -1696,16 +875,6 @@ ERR
1696
875
  find_inherited_value(:query_analyzers, EMPTY_ARRAY) + own_query_analyzers
1697
876
  end
1698
877
 
1699
- def middleware(new_middleware = nil)
1700
- if new_middleware
1701
- 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"
1702
- own_middleware << new_middleware
1703
- else
1704
- # TODO make sure this is cached when running a query
1705
- MiddlewareChain.new(steps: all_middleware, final_step: GraphQL::Execution::Execute::FieldResolveStep)
1706
- end
1707
- end
1708
-
1709
878
  def multiplex_analyzer(new_analyzer)
1710
879
  own_multiplex_analyzers << new_analyzer
1711
880
  end
@@ -1758,17 +927,12 @@ ERR
1758
927
  # }
1759
928
  #
1760
929
  # @see {Query#initialize} for query keyword arguments
1761
- # @see {Execution::Multiplex#run_queries} for multiplex keyword arguments
930
+ # @see {Execution::Multiplex#run_all} for multiplex keyword arguments
1762
931
  # @param queries [Array<Hash>] Keyword arguments for each query
1763
932
  # @param context [Hash] Multiplex-level context
1764
933
  # @return [Array<Hash>] One result for each query in the input
1765
934
  def multiplex(queries, **kwargs)
1766
- schema = if interpreter?
1767
- self
1768
- else
1769
- graphql_definition
1770
- end
1771
- GraphQL::Execution::Multiplex.run_all(schema, queries, **kwargs)
935
+ GraphQL::Execution::Multiplex.run_all(self, queries, **kwargs)
1772
936
  end
1773
937
 
1774
938
  def instrumenters
@@ -1780,14 +944,10 @@ ERR
1780
944
 
1781
945
  # @api private
1782
946
  def add_subscription_extension_if_necessary
1783
- if interpreter? && !defined?(@subscription_extension_added) && subscription && self.subscriptions
947
+ if !defined?(@subscription_extension_added) && subscription && self.subscriptions
1784
948
  @subscription_extension_added = true
1785
- if subscription.singleton_class.ancestors.include?(Subscriptions::SubscriptionRoot)
1786
- GraphQL::Deprecation.warn("`extend Subscriptions::SubscriptionRoot` is no longer required; you may remove it from #{self}'s `subscription` root type (#{subscription}).")
1787
- else
1788
- subscription.all_field_definitions.each do |field|
1789
- field.extension(Subscriptions::DefaultSubscriptionResolveExtension)
1790
- end
949
+ subscription.all_field_definitions.each do |field|
950
+ field.extension(Subscriptions::DefaultSubscriptionResolveExtension)
1791
951
  end
1792
952
  end
1793
953
  end
@@ -1796,6 +956,60 @@ ERR
1796
956
  query.context.errors.push(GraphQL::ExecutionError.new("This query is too large to execute."))
1797
957
  end
1798
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
+
1799
1013
  private
1800
1014
 
1801
1015
  # @param t [Module, Array<Module>]
@@ -1905,68 +1119,12 @@ ERR
1905
1119
  @defined_query_analyzers ||= []
1906
1120
  end
1907
1121
 
1908
- def all_middleware
1909
- find_inherited_value(:all_middleware, EMPTY_ARRAY) + own_middleware
1910
- end
1911
-
1912
- def own_middleware
1913
- @own_middleware ||= []
1914
- end
1915
-
1916
1122
  def own_multiplex_analyzers
1917
1123
  @own_multiplex_analyzers ||= []
1918
1124
  end
1919
1125
  end
1920
1126
 
1921
- def dataloader_class
1922
- self.class.dataloader_class
1923
- end
1924
-
1925
1127
  # Install these here so that subclasses will also install it.
1926
- use(GraphQL::Pagination::Connections)
1927
-
1928
- protected
1929
-
1930
- def rescues?
1931
- !!@rescue_middleware
1932
- end
1933
-
1934
- # Lazily create a middleware and add it to the schema
1935
- # (Don't add it if it's not used)
1936
- def rescue_middleware
1937
- @rescue_middleware ||= GraphQL::Schema::RescueMiddleware.new.tap { |m| middleware.insert(0, m) }
1938
- end
1939
-
1940
- private
1941
-
1942
- def rebuild_artifacts
1943
- if @rebuilding_artifacts
1944
- 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."
1945
- else
1946
- @rebuilding_artifacts = true
1947
- @introspection_system = Schema::IntrospectionSystem.new(self)
1948
- traversal = Traversal.new(self)
1949
- @types = traversal.type_map
1950
- @root_types = [query, mutation, subscription]
1951
- @instrumented_field_map = traversal.instrumented_field_map
1952
- @type_reference_map = traversal.type_reference_map
1953
- @union_memberships = traversal.union_memberships
1954
- @find_cache = {}
1955
- @finder = Finder.new(self)
1956
- end
1957
- ensure
1958
- @rebuilding_artifacts = false
1959
- end
1960
-
1961
- class CyclicalDefinitionError < GraphQL::Error
1962
- end
1963
-
1964
- def with_definition_error_check
1965
- if @definition_error
1966
- raise @definition_error
1967
- else
1968
- yield
1969
- end
1970
- end
1128
+ self.connections = GraphQL::Pagination::Connections.new(schema: self)
1971
1129
  end
1972
1130
  end