graphql 2.3.7 → 2.4.7
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.
- checksums.yaml +4 -4
- data/lib/generators/graphql/install_generator.rb +46 -0
- data/lib/generators/graphql/orm_mutations_base.rb +1 -1
- data/lib/generators/graphql/templates/base_resolver.erb +2 -0
- data/lib/generators/graphql/type_generator.rb +1 -1
- data/lib/graphql/analysis/field_usage.rb +1 -1
- data/lib/graphql/analysis/query_complexity.rb +3 -3
- data/lib/graphql/analysis/visitor.rb +8 -7
- data/lib/graphql/analysis.rb +4 -4
- data/lib/graphql/autoload.rb +38 -0
- data/lib/graphql/current.rb +52 -0
- data/lib/graphql/dataloader/async_dataloader.rb +7 -6
- data/lib/graphql/dataloader/source.rb +7 -4
- data/lib/graphql/dataloader.rb +40 -19
- data/lib/graphql/execution/interpreter/arguments_cache.rb +5 -10
- data/lib/graphql/execution/interpreter/resolve.rb +13 -9
- data/lib/graphql/execution/interpreter/runtime.rb +35 -31
- data/lib/graphql/execution/interpreter.rb +6 -4
- data/lib/graphql/execution/lookahead.rb +18 -11
- data/lib/graphql/introspection/directive_type.rb +1 -1
- data/lib/graphql/introspection/entry_points.rb +2 -2
- data/lib/graphql/introspection/field_type.rb +1 -1
- data/lib/graphql/introspection/schema_type.rb +6 -11
- data/lib/graphql/introspection/type_type.rb +5 -5
- data/lib/graphql/invalid_null_error.rb +1 -1
- data/lib/graphql/language/cache.rb +13 -0
- data/lib/graphql/language/comment.rb +18 -0
- data/lib/graphql/language/document_from_schema_definition.rb +62 -34
- data/lib/graphql/language/lexer.rb +18 -15
- data/lib/graphql/language/nodes.rb +24 -16
- data/lib/graphql/language/parser.rb +14 -1
- data/lib/graphql/language/printer.rb +31 -15
- data/lib/graphql/language/sanitized_printer.rb +1 -1
- data/lib/graphql/language.rb +6 -6
- data/lib/graphql/pagination/connection.rb +1 -1
- data/lib/graphql/query/context/scoped_context.rb +1 -1
- data/lib/graphql/query/context.rb +13 -6
- data/lib/graphql/query/null_context.rb +3 -5
- data/lib/graphql/query/variable_validation_error.rb +1 -1
- data/lib/graphql/query.rb +72 -18
- data/lib/graphql/railtie.rb +7 -0
- data/lib/graphql/rubocop/graphql/field_type_in_block.rb +144 -0
- data/lib/graphql/rubocop/graphql/root_types_in_block.rb +38 -0
- data/lib/graphql/rubocop.rb +2 -0
- data/lib/graphql/schema/addition.rb +2 -1
- data/lib/graphql/schema/always_visible.rb +6 -2
- data/lib/graphql/schema/argument.rb +14 -1
- data/lib/graphql/schema/build_from_definition.rb +9 -1
- data/lib/graphql/schema/directive/flagged.rb +2 -2
- data/lib/graphql/schema/directive.rb +1 -1
- data/lib/graphql/schema/enum.rb +71 -23
- data/lib/graphql/schema/enum_value.rb +10 -2
- data/lib/graphql/schema/field/connection_extension.rb +1 -1
- data/lib/graphql/schema/field/scope_extension.rb +1 -1
- data/lib/graphql/schema/field.rb +102 -47
- data/lib/graphql/schema/field_extension.rb +1 -1
- data/lib/graphql/schema/has_single_input_argument.rb +5 -2
- data/lib/graphql/schema/input_object.rb +90 -39
- data/lib/graphql/schema/interface.rb +22 -5
- data/lib/graphql/schema/introspection_system.rb +5 -16
- data/lib/graphql/schema/loader.rb +1 -1
- data/lib/graphql/schema/member/base_dsl_methods.rb +15 -0
- data/lib/graphql/schema/member/has_arguments.rb +36 -23
- data/lib/graphql/schema/member/has_directives.rb +3 -3
- data/lib/graphql/schema/member/has_fields.rb +26 -6
- data/lib/graphql/schema/member/has_interfaces.rb +4 -4
- data/lib/graphql/schema/member/has_unresolved_type_error.rb +5 -1
- data/lib/graphql/schema/member/has_validators.rb +1 -1
- data/lib/graphql/schema/object.rb +8 -0
- data/lib/graphql/schema/printer.rb +1 -0
- data/lib/graphql/schema/relay_classic_mutation.rb +0 -1
- data/lib/graphql/schema/resolver.rb +12 -14
- data/lib/graphql/schema/subscription.rb +2 -2
- data/lib/graphql/schema/type_expression.rb +2 -2
- data/lib/graphql/schema/union.rb +1 -1
- data/lib/graphql/schema/validator/all_validator.rb +62 -0
- data/lib/graphql/schema/validator/required_validator.rb +28 -4
- data/lib/graphql/schema/validator.rb +3 -1
- data/lib/graphql/schema/visibility/migration.rb +188 -0
- data/lib/graphql/schema/visibility/profile.rb +359 -0
- data/lib/graphql/schema/visibility/visit.rb +190 -0
- data/lib/graphql/schema/visibility.rb +294 -0
- data/lib/graphql/schema/warden.rb +179 -16
- data/lib/graphql/schema.rb +348 -94
- data/lib/graphql/static_validation/base_visitor.rb +6 -5
- data/lib/graphql/static_validation/literal_validator.rb +4 -4
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +1 -1
- data/lib/graphql/static_validation/rules/argument_names_are_unique.rb +1 -1
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +3 -2
- data/lib/graphql/static_validation/rules/directives_are_defined.rb +3 -3
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +2 -0
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +12 -2
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +2 -2
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +8 -7
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
- data/lib/graphql/static_validation/rules/fragment_types_exist.rb +12 -2
- data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +1 -1
- data/lib/graphql/static_validation/rules/mutation_root_exists.rb +1 -1
- data/lib/graphql/static_validation/rules/no_definitions_are_present.rb +1 -1
- data/lib/graphql/static_validation/rules/query_root_exists.rb +1 -1
- data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +4 -4
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +3 -3
- data/lib/graphql/static_validation/rules/subscription_root_exists.rb +1 -1
- data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +1 -1
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +18 -27
- data/lib/graphql/static_validation/rules/variable_names_are_unique.rb +1 -1
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +2 -2
- data/lib/graphql/static_validation/rules/variables_are_input_types.rb +11 -2
- data/lib/graphql/static_validation/validation_context.rb +18 -2
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +3 -2
- data/lib/graphql/subscriptions/broadcast_analyzer.rb +10 -4
- data/lib/graphql/subscriptions/event.rb +1 -1
- data/lib/graphql/subscriptions/serialize.rb +2 -0
- data/lib/graphql/subscriptions.rb +6 -4
- data/lib/graphql/testing/helpers.rb +10 -6
- data/lib/graphql/tracing/notifications_trace.rb +2 -2
- data/lib/graphql/types/relay/connection_behaviors.rb +12 -2
- data/lib/graphql/types/relay/edge_behaviors.rb +11 -1
- data/lib/graphql/types/relay/page_info_behaviors.rb +4 -0
- data/lib/graphql/types.rb +18 -11
- data/lib/graphql/unauthorized_enum_value_error.rb +13 -0
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +53 -45
- metadata +31 -8
- data/lib/graphql/language/token.rb +0 -34
- data/lib/graphql/schema/invalid_type_error.rb +0 -7
data/lib/graphql/schema.rb
CHANGED
@@ -5,7 +5,6 @@ require "graphql/schema/always_visible"
|
|
5
5
|
require "graphql/schema/base_64_encoder"
|
6
6
|
require "graphql/schema/find_inherited_value"
|
7
7
|
require "graphql/schema/finder"
|
8
|
-
require "graphql/schema/invalid_type_error"
|
9
8
|
require "graphql/schema/introspection_system"
|
10
9
|
require "graphql/schema/late_bound_type"
|
11
10
|
require "graphql/schema/null_mask"
|
@@ -46,6 +45,7 @@ require "graphql/schema/mutation"
|
|
46
45
|
require "graphql/schema/has_single_input_argument"
|
47
46
|
require "graphql/schema/relay_classic_mutation"
|
48
47
|
require "graphql/schema/subscription"
|
48
|
+
require "graphql/schema/visibility"
|
49
49
|
|
50
50
|
module GraphQL
|
51
51
|
# A GraphQL schema which may be queried with {GraphQL::Query}.
|
@@ -73,6 +73,9 @@ module GraphQL
|
|
73
73
|
class Schema
|
74
74
|
extend GraphQL::Schema::Member::HasAstNode
|
75
75
|
extend GraphQL::Schema::FindInheritedValue
|
76
|
+
extend Autoload
|
77
|
+
|
78
|
+
autoload :BUILT_IN_TYPES, "graphql/schema/built_in_types"
|
76
79
|
|
77
80
|
class DuplicateNamesError < GraphQL::Error
|
78
81
|
attr_reader :duplicated_name
|
@@ -162,6 +165,7 @@ module GraphQL
|
|
162
165
|
# re-apply them here
|
163
166
|
mods = trace_modules_for(:default)
|
164
167
|
mods.each { |mod| new_class.include(mod) }
|
168
|
+
new_class.include(DefaultTraceClass)
|
165
169
|
trace_mode(:default, new_class)
|
166
170
|
backtrace_class = Class.new(new_class)
|
167
171
|
backtrace_class.include(GraphQL::Backtrace::Trace)
|
@@ -204,24 +208,19 @@ module GraphQL
|
|
204
208
|
@own_trace_modes ||= {}
|
205
209
|
end
|
206
210
|
|
207
|
-
module DefaultTraceClass
|
208
|
-
end
|
209
|
-
|
210
|
-
private_constant :DefaultTraceClass
|
211
|
-
|
212
211
|
def build_trace_mode(mode)
|
213
212
|
case mode
|
214
213
|
when :default
|
215
214
|
# Use the superclass's default mode if it has one, or else start an inheritance chain at the built-in base class.
|
216
|
-
base_class = (superclass.respond_to?(:trace_class_for) && superclass.trace_class_for(mode)) || GraphQL::Tracing::Trace
|
217
|
-
Class.new(base_class) do
|
215
|
+
base_class = (superclass.respond_to?(:trace_class_for) && superclass.trace_class_for(mode, build: true)) || GraphQL::Tracing::Trace
|
216
|
+
const_set(:DefaultTrace, Class.new(base_class) do
|
218
217
|
include DefaultTraceClass
|
219
|
-
end
|
218
|
+
end)
|
220
219
|
when :default_backtrace
|
221
220
|
schema_base_class = trace_class_for(:default, build: true)
|
222
|
-
Class.new(schema_base_class) do
|
221
|
+
const_set(:DefaultTraceBacktrace, Class.new(schema_base_class) do
|
223
222
|
include(GraphQL::Backtrace::Trace)
|
224
|
-
end
|
223
|
+
end)
|
225
224
|
else
|
226
225
|
# First, see if the superclass has a custom-defined class for this.
|
227
226
|
# Then, if it doesn't, use this class's default trace
|
@@ -237,7 +236,7 @@ module GraphQL
|
|
237
236
|
add_trace_options_for(mode, default_options)
|
238
237
|
|
239
238
|
Class.new(base_class) do
|
240
|
-
mods.
|
239
|
+
!mods.empty? && include(*mods)
|
241
240
|
end
|
242
241
|
end
|
243
242
|
end
|
@@ -321,8 +320,11 @@ module GraphQL
|
|
321
320
|
GraphQL::StaticValidation::Validator.new(schema: self)
|
322
321
|
end
|
323
322
|
|
323
|
+
# Add `plugin` to this schema
|
324
|
+
# @param plugin [#use] A Schema plugin
|
325
|
+
# @return void
|
324
326
|
def use(plugin, **kwargs)
|
325
|
-
if kwargs.
|
327
|
+
if !kwargs.empty?
|
326
328
|
plugin.use(self, **kwargs)
|
327
329
|
else
|
328
330
|
plugin.use(self)
|
@@ -338,6 +340,10 @@ module GraphQL
|
|
338
340
|
# @return [Hash<String => Class>] A dictionary of type classes by their GraphQL name
|
339
341
|
# @see get_type Which is more efficient for finding _one type_ by name, because it doesn't merge hashes.
|
340
342
|
def types(context = GraphQL::Query::NullContext.instance)
|
343
|
+
if use_visibility_profile?
|
344
|
+
types = Visibility::Profile.from_context(context, self)
|
345
|
+
return types.all_types_h
|
346
|
+
end
|
341
347
|
all_types = non_introspection_types.merge(introspection_system.types)
|
342
348
|
visible_types = {}
|
343
349
|
all_types.each do |k, v|
|
@@ -363,27 +369,36 @@ module GraphQL
|
|
363
369
|
end
|
364
370
|
|
365
371
|
# @param type_name [String]
|
372
|
+
# @param context [GraphQL::Query::Context] Used for filtering definitions at query-time
|
373
|
+
# @param use_visibility_profile Private, for migration to {Schema::Visibility}
|
366
374
|
# @return [Module, nil] A type, or nil if there's no type called `type_name`
|
367
|
-
def get_type(type_name, context = GraphQL::Query::NullContext.instance)
|
375
|
+
def get_type(type_name, context = GraphQL::Query::NullContext.instance, use_visibility_profile = use_visibility_profile?)
|
376
|
+
if use_visibility_profile
|
377
|
+
return Visibility::Profile.from_context(context, self).type(type_name)
|
378
|
+
end
|
368
379
|
local_entry = own_types[type_name]
|
369
380
|
type_defn = case local_entry
|
370
381
|
when nil
|
371
382
|
nil
|
372
383
|
when Array
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
384
|
+
if context.respond_to?(:types) && context.types.is_a?(GraphQL::Schema::Visibility::Profile)
|
385
|
+
local_entry
|
386
|
+
else
|
387
|
+
visible_t = nil
|
388
|
+
warden = Warden.from_context(context)
|
389
|
+
local_entry.each do |t|
|
390
|
+
if warden.visible_type?(t, context)
|
391
|
+
if visible_t.nil?
|
392
|
+
visible_t = t
|
393
|
+
else
|
394
|
+
raise DuplicateNamesError.new(
|
395
|
+
duplicated_name: type_name, duplicated_definition_1: visible_t.inspect, duplicated_definition_2: t.inspect
|
396
|
+
)
|
397
|
+
end
|
383
398
|
end
|
384
399
|
end
|
400
|
+
visible_t
|
385
401
|
end
|
386
|
-
visible_t
|
387
402
|
when Module
|
388
403
|
local_entry
|
389
404
|
else
|
@@ -392,7 +407,7 @@ module GraphQL
|
|
392
407
|
|
393
408
|
type_defn ||
|
394
409
|
introspection_system.types[type_name] || # todo context-specific introspection?
|
395
|
-
(superclass.respond_to?(:get_type) ? superclass.get_type(type_name, context) : nil)
|
410
|
+
(superclass.respond_to?(:get_type) ? superclass.get_type(type_name, context, use_visibility_profile) : nil)
|
396
411
|
end
|
397
412
|
|
398
413
|
# @return [Boolean] Does this schema have _any_ definition for a type named `type_name`, regardless of visibility?
|
@@ -419,55 +434,127 @@ module GraphQL
|
|
419
434
|
end
|
420
435
|
end
|
421
436
|
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
437
|
+
# Get or set the root `query { ... }` object for this schema.
|
438
|
+
#
|
439
|
+
# @example Using `Types::Query` as the entry-point
|
440
|
+
# query { Types::Query }
|
441
|
+
#
|
442
|
+
# @param new_query_object [Class<GraphQL::Schema::Object>] The root type to use for queries
|
443
|
+
# @param lazy_load_block If a block is given, then it will be called when GraphQL-Ruby needs the root query type.
|
444
|
+
# @return [Class<GraphQL::Schema::Object>, nil] The configured query root type, if there is one.
|
445
|
+
def query(new_query_object = nil, &lazy_load_block)
|
446
|
+
if new_query_object || block_given?
|
428
447
|
if @query_object
|
429
|
-
|
448
|
+
dup_defn = new_query_object || yield
|
449
|
+
raise GraphQL::Error, "Second definition of `query(...)` (#{dup_defn.inspect}) is invalid, already configured with #{@query_object.inspect}"
|
450
|
+
elsif use_visibility_profile?
|
451
|
+
if block_given?
|
452
|
+
if visibility.preload?
|
453
|
+
@query_object = lazy_load_block.call
|
454
|
+
self.visibility.query_configured(@query_object)
|
455
|
+
else
|
456
|
+
@query_object = lazy_load_block
|
457
|
+
end
|
458
|
+
else
|
459
|
+
@query_object = new_query_object
|
460
|
+
self.visibility.query_configured(@query_object)
|
461
|
+
end
|
430
462
|
else
|
431
|
-
@query_object = new_query_object
|
432
|
-
add_type_and_traverse(
|
433
|
-
nil
|
463
|
+
@query_object = new_query_object || lazy_load_block.call
|
464
|
+
add_type_and_traverse(@query_object, root: true)
|
434
465
|
end
|
466
|
+
nil
|
467
|
+
elsif @query_object.is_a?(Proc)
|
468
|
+
@query_object = @query_object.call
|
469
|
+
self.visibility&.query_configured(@query_object)
|
470
|
+
@query_object
|
435
471
|
else
|
436
472
|
@query_object || find_inherited_value(:query)
|
437
473
|
end
|
438
474
|
end
|
439
475
|
|
440
|
-
|
441
|
-
|
476
|
+
# Get or set the root `mutation { ... }` object for this schema.
|
477
|
+
#
|
478
|
+
# @example Using `Types::Mutation` as the entry-point
|
479
|
+
# mutation { Types::Mutation }
|
480
|
+
#
|
481
|
+
# @param new_mutation_object [Class<GraphQL::Schema::Object>] The root type to use for mutations
|
482
|
+
# @param lazy_load_block If a block is given, then it will be called when GraphQL-Ruby needs the root mutation type.
|
483
|
+
# @return [Class<GraphQL::Schema::Object>, nil] The configured mutation root type, if there is one.
|
484
|
+
def mutation(new_mutation_object = nil, &lazy_load_block)
|
485
|
+
if new_mutation_object || block_given?
|
442
486
|
if @mutation_object
|
443
|
-
|
487
|
+
dup_defn = new_mutation_object || yield
|
488
|
+
raise GraphQL::Error, "Second definition of `mutation(...)` (#{dup_defn.inspect}) is invalid, already configured with #{@mutation_object.inspect}"
|
489
|
+
elsif use_visibility_profile?
|
490
|
+
if block_given?
|
491
|
+
if visibility.preload?
|
492
|
+
@mutation_object = lazy_load_block.call
|
493
|
+
self.visibility.mutation_configured(@mutation_object)
|
494
|
+
else
|
495
|
+
@mutation_object = lazy_load_block
|
496
|
+
end
|
497
|
+
else
|
498
|
+
@mutation_object = new_mutation_object
|
499
|
+
self.visibility.mutation_configured(@mutation_object)
|
500
|
+
end
|
444
501
|
else
|
445
|
-
@mutation_object = new_mutation_object
|
446
|
-
add_type_and_traverse(
|
447
|
-
nil
|
502
|
+
@mutation_object = new_mutation_object || lazy_load_block.call
|
503
|
+
add_type_and_traverse(@mutation_object, root: true)
|
448
504
|
end
|
505
|
+
nil
|
506
|
+
elsif @mutation_object.is_a?(Proc)
|
507
|
+
@mutation_object = @mutation_object.call
|
508
|
+
self.visibility&.mutation_configured(@mutation_object)
|
509
|
+
@mutation_object
|
449
510
|
else
|
450
511
|
@mutation_object || find_inherited_value(:mutation)
|
451
512
|
end
|
452
513
|
end
|
453
514
|
|
454
|
-
|
455
|
-
|
515
|
+
# Get or set the root `subscription { ... }` object for this schema.
|
516
|
+
#
|
517
|
+
# @example Using `Types::Subscription` as the entry-point
|
518
|
+
# subscription { Types::Subscription }
|
519
|
+
#
|
520
|
+
# @param new_subscription_object [Class<GraphQL::Schema::Object>] The root type to use for subscriptions
|
521
|
+
# @param lazy_load_block If a block is given, then it will be called when GraphQL-Ruby needs the root subscription type.
|
522
|
+
# @return [Class<GraphQL::Schema::Object>, nil] The configured subscription root type, if there is one.
|
523
|
+
def subscription(new_subscription_object = nil, &lazy_load_block)
|
524
|
+
if new_subscription_object || block_given?
|
456
525
|
if @subscription_object
|
457
|
-
|
526
|
+
dup_defn = new_subscription_object || yield
|
527
|
+
raise GraphQL::Error, "Second definition of `subscription(...)` (#{dup_defn.inspect}) is invalid, already configured with #{@subscription_object.inspect}"
|
528
|
+
elsif use_visibility_profile?
|
529
|
+
if block_given?
|
530
|
+
if visibility.preload?
|
531
|
+
@subscription_object = lazy_load_block.call
|
532
|
+
visibility.subscription_configured(@subscription_object)
|
533
|
+
else
|
534
|
+
@subscription_object = lazy_load_block
|
535
|
+
end
|
536
|
+
else
|
537
|
+
@subscription_object = new_subscription_object
|
538
|
+
self.visibility.subscription_configured(@subscription_object)
|
539
|
+
end
|
540
|
+
add_subscription_extension_if_necessary
|
458
541
|
else
|
459
|
-
@subscription_object = new_subscription_object
|
542
|
+
@subscription_object = new_subscription_object || lazy_load_block.call
|
460
543
|
add_subscription_extension_if_necessary
|
461
|
-
add_type_and_traverse(
|
462
|
-
nil
|
544
|
+
add_type_and_traverse(@subscription_object, root: true)
|
463
545
|
end
|
546
|
+
nil
|
547
|
+
elsif @subscription_object.is_a?(Proc)
|
548
|
+
@subscription_object = @subscription_object.call
|
549
|
+
add_subscription_extension_if_necessary
|
550
|
+
self.visibility.subscription_configured(@subscription_object)
|
551
|
+
@subscription_object
|
464
552
|
else
|
465
553
|
@subscription_object || find_inherited_value(:subscription)
|
466
554
|
end
|
467
555
|
end
|
468
556
|
|
469
|
-
# @
|
470
|
-
# @return [GraphQL::ObjectType, nil]
|
557
|
+
# @api private
|
471
558
|
def root_type_for_operation(operation)
|
472
559
|
case operation
|
473
560
|
when "query"
|
@@ -481,10 +568,16 @@ module GraphQL
|
|
481
568
|
end
|
482
569
|
end
|
483
570
|
|
571
|
+
# @return [Array<Class>] The root types (query, mutation, subscription) defined for this schema
|
484
572
|
def root_types
|
485
|
-
|
573
|
+
if use_visibility_profile?
|
574
|
+
[query, mutation, subscription].compact
|
575
|
+
else
|
576
|
+
@root_types
|
577
|
+
end
|
486
578
|
end
|
487
579
|
|
580
|
+
# @api private
|
488
581
|
def warden_class
|
489
582
|
if defined?(@warden_class)
|
490
583
|
@warden_class
|
@@ -495,12 +588,48 @@ module GraphQL
|
|
495
588
|
end
|
496
589
|
end
|
497
590
|
|
591
|
+
# @api private
|
498
592
|
attr_writer :warden_class
|
499
593
|
|
594
|
+
# @api private
|
595
|
+
def visibility_profile_class
|
596
|
+
if defined?(@visibility_profile_class)
|
597
|
+
@visibility_profile_class
|
598
|
+
elsif superclass.respond_to?(:visibility_profile_class)
|
599
|
+
superclass.visibility_profile_class
|
600
|
+
else
|
601
|
+
GraphQL::Schema::Visibility::Profile
|
602
|
+
end
|
603
|
+
end
|
604
|
+
|
605
|
+
# @api private
|
606
|
+
attr_writer :visibility_profile_class, :use_visibility_profile
|
607
|
+
# @api private
|
608
|
+
attr_accessor :visibility
|
609
|
+
# @api private
|
610
|
+
def use_visibility_profile?
|
611
|
+
if defined?(@use_visibility_profile)
|
612
|
+
@use_visibility_profile
|
613
|
+
elsif superclass.respond_to?(:use_visibility_profile?)
|
614
|
+
superclass.use_visibility_profile?
|
615
|
+
else
|
616
|
+
false
|
617
|
+
end
|
618
|
+
end
|
619
|
+
|
500
620
|
# @param type [Module] The type definition whose possible types you want to see
|
621
|
+
# @param context [GraphQL::Query::Context] used for filtering visible possible types at runtime
|
622
|
+
# @param use_visibility_profile Private, for migration to {Schema::Visibility}
|
501
623
|
# @return [Hash<String, Module>] All possible types, if no `type` is given.
|
502
624
|
# @return [Array<Module>] Possible types for `type`, if it's given.
|
503
|
-
def possible_types(type = nil, context = GraphQL::Query::NullContext.instance)
|
625
|
+
def possible_types(type = nil, context = GraphQL::Query::NullContext.instance, use_visibility_profile = use_visibility_profile?)
|
626
|
+
if use_visibility_profile
|
627
|
+
if type
|
628
|
+
return Visibility::Profile.from_context(context, self).possible_types(type)
|
629
|
+
else
|
630
|
+
raise "Schema.possible_types is not implemented for `use_visibility_profile?`"
|
631
|
+
end
|
632
|
+
end
|
504
633
|
if type
|
505
634
|
# TODO duck-typing `.possible_types` would probably be nicer here
|
506
635
|
if type.kind.union?
|
@@ -518,7 +647,7 @@ module GraphQL
|
|
518
647
|
introspection_system.possible_types[type] ||
|
519
648
|
(
|
520
649
|
superclass.respond_to?(:possible_types) ?
|
521
|
-
superclass.possible_types(type, context) :
|
650
|
+
superclass.possible_types(type, context, use_visibility_profile) :
|
522
651
|
EMPTY_ARRAY
|
523
652
|
)
|
524
653
|
end
|
@@ -565,7 +694,7 @@ module GraphQL
|
|
565
694
|
# and generally speaking, we won't inherit any values.
|
566
695
|
# So optimize the most common case -- don't create a duplicate Hash.
|
567
696
|
inherited_value = find_inherited_value(:references_to, EMPTY_HASH)
|
568
|
-
if inherited_value.
|
697
|
+
if !inherited_value.empty?
|
569
698
|
inherited_value.merge(own_references_to)
|
570
699
|
else
|
571
700
|
own_references_to
|
@@ -573,9 +702,8 @@ module GraphQL
|
|
573
702
|
end
|
574
703
|
end
|
575
704
|
|
576
|
-
def type_from_ast(ast_node, context:
|
577
|
-
|
578
|
-
GraphQL::Schema::TypeExpression.build_type(type_owner, ast_node)
|
705
|
+
def type_from_ast(ast_node, context: self.query_class.new(self, "{ __typename }").context)
|
706
|
+
GraphQL::Schema::TypeExpression.build_type(context.query.types, ast_node)
|
579
707
|
end
|
580
708
|
|
581
709
|
def get_field(type_or_name, field_name, context = GraphQL::Query::NullContext.instance)
|
@@ -605,20 +733,27 @@ module GraphQL
|
|
605
733
|
type.fields(context)
|
606
734
|
end
|
607
735
|
|
736
|
+
# Pass a custom introspection module here to use it for this schema.
|
737
|
+
# @param new_introspection_namespace [Module] If given, use this module for custom introspection on the schema
|
738
|
+
# @return [Module, nil] The configured namespace, if there is one
|
608
739
|
def introspection(new_introspection_namespace = nil)
|
609
740
|
if new_introspection_namespace
|
610
741
|
@introspection = new_introspection_namespace
|
611
742
|
# reset this cached value:
|
612
743
|
@introspection_system = nil
|
744
|
+
introspection_system
|
745
|
+
@introspection
|
613
746
|
else
|
614
747
|
@introspection || find_inherited_value(:introspection)
|
615
748
|
end
|
616
749
|
end
|
617
750
|
|
751
|
+
# @return [Schema::IntrospectionSystem] Based on {introspection}
|
618
752
|
def introspection_system
|
619
753
|
if !@introspection_system
|
620
754
|
@introspection_system = Schema::IntrospectionSystem.new(self)
|
621
755
|
@introspection_system.resolve_late_bindings
|
756
|
+
self.visibility&.introspection_system_configured(@introspection_system)
|
622
757
|
end
|
623
758
|
@introspection_system
|
624
759
|
end
|
@@ -722,6 +857,7 @@ module GraphQL
|
|
722
857
|
res[:errors]
|
723
858
|
end
|
724
859
|
|
860
|
+
# @param new_query_class [Class<GraphQL::Query>] A subclass to use when executing queries
|
725
861
|
def query_class(new_query_class = NOT_CONFIGURED)
|
726
862
|
if NOT_CONFIGURED.equal?(new_query_class)
|
727
863
|
@query_class || (superclass.respond_to?(:query_class) ? superclass.query_class : GraphQL::Query)
|
@@ -732,13 +868,11 @@ module GraphQL
|
|
732
868
|
|
733
869
|
attr_writer :validate_max_errors
|
734
870
|
|
735
|
-
def validate_max_errors(new_validate_max_errors =
|
736
|
-
if new_validate_max_errors
|
737
|
-
@validate_max_errors
|
738
|
-
elsif defined?(@validate_max_errors)
|
739
|
-
@validate_max_errors
|
871
|
+
def validate_max_errors(new_validate_max_errors = NOT_CONFIGURED)
|
872
|
+
if NOT_CONFIGURED.equal?(new_validate_max_errors)
|
873
|
+
defined?(@validate_max_errors) ? @validate_max_errors : find_inherited_value(:validate_max_errors)
|
740
874
|
else
|
741
|
-
|
875
|
+
@validate_max_errors = new_validate_max_errors
|
742
876
|
end
|
743
877
|
end
|
744
878
|
|
@@ -769,16 +903,6 @@ module GraphQL
|
|
769
903
|
@analysis_engine || find_inherited_value(:analysis_engine, self.default_analysis_engine)
|
770
904
|
end
|
771
905
|
|
772
|
-
def using_ast_analysis?
|
773
|
-
true
|
774
|
-
end
|
775
|
-
|
776
|
-
def interpreter?
|
777
|
-
true
|
778
|
-
end
|
779
|
-
|
780
|
-
attr_writer :interpreter
|
781
|
-
|
782
906
|
def error_bubbling(new_error_bubbling = nil)
|
783
907
|
if !new_error_bubbling.nil?
|
784
908
|
warn("error_bubbling(#{new_error_bubbling.inspect}) is deprecated; the default value of `false` will be the only option in GraphQL-Ruby 3.0")
|
@@ -856,7 +980,7 @@ module GraphQL
|
|
856
980
|
# @param new_extra_types [Module] Type definitions to include in printing and introspection, even though they aren't referenced in the schema
|
857
981
|
# @return [Array<Module>] Type definitions added to this schema
|
858
982
|
def extra_types(*new_extra_types)
|
859
|
-
if new_extra_types.
|
983
|
+
if !new_extra_types.empty?
|
860
984
|
new_extra_types = new_extra_types.flatten
|
861
985
|
@own_extra_types ||= []
|
862
986
|
@own_extra_types.concat(new_extra_types)
|
@@ -873,11 +997,18 @@ module GraphQL
|
|
873
997
|
end
|
874
998
|
end
|
875
999
|
|
1000
|
+
# Tell the schema about these types so that they can be registered as implementations of interfaces in the schema.
|
1001
|
+
#
|
1002
|
+
# This method must be used when an object type is connected to the schema as an interface implementor but
|
1003
|
+
# not as a return type of a field. In that case, if the object type isn't registered here, GraphQL-Ruby won't be able to find it.
|
1004
|
+
#
|
1005
|
+
# @param new_orphan_types [Array<Class<GraphQL::Schema::Object>>] Object types to register as implementations of interfaces in the schema.
|
1006
|
+
# @return [Array<Class<GraphQL::Schema::Object>>] All previously-registered orphan types for this schema
|
876
1007
|
def orphan_types(*new_orphan_types)
|
877
|
-
if new_orphan_types.
|
1008
|
+
if !new_orphan_types.empty?
|
878
1009
|
new_orphan_types = new_orphan_types.flatten
|
879
1010
|
non_object_types = new_orphan_types.reject { |ot| ot.is_a?(Class) && ot < GraphQL::Schema::Object }
|
880
|
-
if non_object_types.
|
1011
|
+
if !non_object_types.empty?
|
881
1012
|
raise ArgumentError, <<~ERR
|
882
1013
|
Only object type classes should be added as `orphan_types(...)`.
|
883
1014
|
|
@@ -887,13 +1018,14 @@ module GraphQL
|
|
887
1018
|
To add other types to your schema, you might want `extra_types`: https://graphql-ruby.org/schema/definition.html#extra-types
|
888
1019
|
ERR
|
889
1020
|
end
|
890
|
-
add_type_and_traverse(new_orphan_types, root: false)
|
1021
|
+
add_type_and_traverse(new_orphan_types, root: false) unless use_visibility_profile?
|
891
1022
|
own_orphan_types.concat(new_orphan_types.flatten)
|
1023
|
+
self.visibility&.orphan_types_configured(new_orphan_types)
|
892
1024
|
end
|
893
1025
|
|
894
1026
|
inherited_ot = find_inherited_value(:orphan_types, nil)
|
895
1027
|
if inherited_ot
|
896
|
-
if own_orphan_types.
|
1028
|
+
if !own_orphan_types.empty?
|
897
1029
|
inherited_ot + own_orphan_types
|
898
1030
|
else
|
899
1031
|
inherited_ot
|
@@ -919,6 +1051,8 @@ module GraphQL
|
|
919
1051
|
end
|
920
1052
|
end
|
921
1053
|
|
1054
|
+
|
1055
|
+
# @param new_default_logger [#log] Something to use for logging messages
|
922
1056
|
def default_logger(new_default_logger = NOT_CONFIGURED)
|
923
1057
|
if NOT_CONFIGURED.equal?(new_default_logger)
|
924
1058
|
if defined?(@default_logger)
|
@@ -939,6 +1073,7 @@ module GraphQL
|
|
939
1073
|
end
|
940
1074
|
end
|
941
1075
|
|
1076
|
+
# @param new_context_class [Class<GraphQL::Query::Context>] A subclass to use when executing queries
|
942
1077
|
def context_class(new_context_class = nil)
|
943
1078
|
if new_context_class
|
944
1079
|
@context_class = new_context_class
|
@@ -947,6 +1082,20 @@ module GraphQL
|
|
947
1082
|
end
|
948
1083
|
end
|
949
1084
|
|
1085
|
+
# Register a handler for errors raised during execution. The handlers can return a new value or raise a new error.
|
1086
|
+
#
|
1087
|
+
# @example Handling "not found" with a client-facing error
|
1088
|
+
# rescue_from(ActiveRecord::NotFound) { raise GraphQL::ExecutionError, "An object could not be found" }
|
1089
|
+
#
|
1090
|
+
# @param err_classes [Array<StandardError>] Classes which should be rescued by `handler_block`
|
1091
|
+
# @param handler_block The code to run when one of those errors is raised during execution
|
1092
|
+
# @yieldparam error [StandardError] An instance of one of the configured `err_classes`
|
1093
|
+
# @yieldparam object [Object] The current application object in the query when the error was raised
|
1094
|
+
# @yieldparam arguments [GraphQL::Query::Arguments] The current field arguments when the error was raised
|
1095
|
+
# @yieldparam context [GraphQL::Query::Context] The context for the currently-running operation
|
1096
|
+
# @yieldreturn [Object] Some object to use in the place where this error was raised
|
1097
|
+
# @raise [GraphQL::ExecutionError] In the handler, raise to add a client-facing error to the response
|
1098
|
+
# @raise [StandardError] In the handler, raise to crash the query with a developer-facing error
|
950
1099
|
def rescue_from(*err_classes, &handler_block)
|
951
1100
|
err_classes.each do |err_class|
|
952
1101
|
Execution::Errors.register_rescue_from(err_class, error_handlers[:subclass_handlers], handler_block)
|
@@ -1013,8 +1162,24 @@ module GraphQL
|
|
1013
1162
|
end
|
1014
1163
|
end
|
1015
1164
|
|
1016
|
-
|
1017
|
-
|
1165
|
+
# GraphQL-Ruby calls this method during execution when it needs the application to determine the type to use for an object.
|
1166
|
+
#
|
1167
|
+
# Usually, this object was returned from a field whose return type is an {GraphQL::Schema::Interface} or a {GraphQL::Schema::Union}.
|
1168
|
+
# But this method is called in other cases, too -- for example, when {GraphQL::Schema::Argument.loads} cases an object to be directly loaded from the database.
|
1169
|
+
#
|
1170
|
+
# @example Returning a GraphQL type based on the object's class name
|
1171
|
+
# class MySchema < GraphQL::Schema
|
1172
|
+
# def resolve_type(_abs_type, object, _context)
|
1173
|
+
# graphql_type_name = "Types::#{object.class.name}Type"
|
1174
|
+
# graphql_type_name.constantize # If this raises a NameError, then come implement special cases in this method
|
1175
|
+
# end
|
1176
|
+
# end
|
1177
|
+
# @param abstract_type [Class, Module, nil] The Interface or Union type which is being resolved, if there is one
|
1178
|
+
# @param application_object [Object] The object returned from a field whose type must be determined
|
1179
|
+
# @param context [GraphQL::Query::Context] The query context for the currently-executing query
|
1180
|
+
# @return [Class<GraphQL::Schema::Object] The Object type definition to use for `obj`
|
1181
|
+
def resolve_type(abstract_type, application_object, context)
|
1182
|
+
raise GraphQL::RequiredImplementationMissingError, "#{self.name}.resolve_type(abstract_type, application_object, context) must be implemented to use Union types, Interface types, or `loads:` (tried to resolve: #{abstract_type.name})"
|
1018
1183
|
end
|
1019
1184
|
# rubocop:enable Lint/DuplicateMethods
|
1020
1185
|
|
@@ -1029,15 +1194,45 @@ module GraphQL
|
|
1029
1194
|
child_class.own_trace_modes[name] = child_class.build_trace_mode(name)
|
1030
1195
|
end
|
1031
1196
|
child_class.singleton_class.prepend(ResolveTypeWithType)
|
1032
|
-
super
|
1033
|
-
end
|
1034
1197
|
|
1035
|
-
|
1036
|
-
|
1198
|
+
if use_visibility_profile?
|
1199
|
+
vis = self.visibility
|
1200
|
+
child_class.visibility = vis.dup_for(child_class)
|
1201
|
+
end
|
1202
|
+
super
|
1037
1203
|
end
|
1038
1204
|
|
1039
|
-
|
1040
|
-
|
1205
|
+
# Fetch an object based on an incoming ID and the current context. This method should return an object
|
1206
|
+
# from your application, or return `nil` if there is no object or the object shouldn't be available to this operation.
|
1207
|
+
#
|
1208
|
+
# @example Fetching an object with Rails's GlobalID
|
1209
|
+
# def self.object_from_id(object_id, _context)
|
1210
|
+
# GlobalID.find(global_id)
|
1211
|
+
# # TODO: use `context[:current_user]` to determine if this object is authorized.
|
1212
|
+
# end
|
1213
|
+
# @param object_id [String] The ID to fetch an object for. This may be client-provided (as in `node(id: ...)` or `loads:`) or previously stored by the schema (eg, by the `ObjectCache`)
|
1214
|
+
# @param context [GraphQL::Query::Context] The context for the currently-executing operation
|
1215
|
+
# @return [Object, nil] The application which `object_id` references, or `nil` if there is no object or the current operation shouldn't have access to the object
|
1216
|
+
# @see id_from_object which produces these IDs
|
1217
|
+
def object_from_id(object_id, context)
|
1218
|
+
raise GraphQL::RequiredImplementationMissingError, "#{self.name}.object_from_id(object_id, context) must be implemented to load by ID (tried to load from id `#{object_id}`)"
|
1219
|
+
end
|
1220
|
+
|
1221
|
+
# Return a stable ID string for `object` so that it can be refetched later, using {.object_from_id}.
|
1222
|
+
#
|
1223
|
+
# {GlobalID}(https://github.com/rails/globalid) and {SQIDs}(https://sqids.org/ruby) can both be used to create IDs.
|
1224
|
+
#
|
1225
|
+
# @example Using Rails's GlobalID to generate IDs
|
1226
|
+
# def self.id_from_object(application_object, graphql_type, context)
|
1227
|
+
# application_object.to_gid_param
|
1228
|
+
# end
|
1229
|
+
#
|
1230
|
+
# @param application_object [Object] Some object encountered by GraphQL-Ruby while running a query
|
1231
|
+
# @param graphql_type [Class, Module] The type that GraphQL-Ruby is using for `application_object` during this query
|
1232
|
+
# @param context [GraphQL::Query::Context] The context for the operation that is currently running
|
1233
|
+
# @return [String] A stable identifier which can be passed to {.object_from_id} later to re-fetch `application_object`
|
1234
|
+
def id_from_object(application_object, graphql_type, context)
|
1235
|
+
raise GraphQL::RequiredImplementationMissingError, "#{self.name}.id_from_object(application_object, graphql_type, context) must be implemented to create global ids (tried to create an id for `#{application_object.inspect}`)"
|
1041
1236
|
end
|
1042
1237
|
|
1043
1238
|
def visible?(member, ctx)
|
@@ -1053,6 +1248,10 @@ module GraphQL
|
|
1053
1248
|
Member::HasDirectives.get_directives(self, @own_schema_directives, :schema_directives)
|
1054
1249
|
end
|
1055
1250
|
|
1251
|
+
# Called when a type is needed by name at runtime
|
1252
|
+
def load_type(type_name, ctx)
|
1253
|
+
get_type(type_name, ctx)
|
1254
|
+
end
|
1056
1255
|
# This hook is called when an object fails an `authorized?` check.
|
1057
1256
|
# You might report to your bug tracker here, so you can correct
|
1058
1257
|
# the field resolvers not to return unauthorized objects.
|
@@ -1088,6 +1287,16 @@ module GraphQL
|
|
1088
1287
|
unauthorized_object(unauthorized_error)
|
1089
1288
|
end
|
1090
1289
|
|
1290
|
+
# Called at runtime when GraphQL-Ruby encounters a mismatch between the application behavior
|
1291
|
+
# and the GraphQL type system.
|
1292
|
+
#
|
1293
|
+
# The default implementation of this method is to follow the GraphQL specification,
|
1294
|
+
# but you can override this to report errors to your bug tracker or customize error handling.
|
1295
|
+
# @param type_error [GraphQL::Error] several specific error classes are passed here, see the default implementation for details
|
1296
|
+
# @param context [GraphQL::Query::Context] the context for the currently-running operation
|
1297
|
+
# @return [void]
|
1298
|
+
# @raise [GraphQL::ExecutionError] to return this error to the client
|
1299
|
+
# @raise [GraphQL::Error] to crash the query and raise a developer-facing error
|
1091
1300
|
def type_error(type_error, ctx)
|
1092
1301
|
case type_error
|
1093
1302
|
when GraphQL::InvalidNullError
|
@@ -1126,12 +1335,12 @@ module GraphQL
|
|
1126
1335
|
# Add several directives at once
|
1127
1336
|
# @param new_directives [Class]
|
1128
1337
|
def directives(*new_directives)
|
1129
|
-
if new_directives.
|
1338
|
+
if !new_directives.empty?
|
1130
1339
|
new_directives.flatten.each { |d| directive(d) }
|
1131
1340
|
end
|
1132
1341
|
|
1133
1342
|
inherited_dirs = find_inherited_value(:directives, default_directives)
|
1134
|
-
if own_directives.
|
1343
|
+
if !own_directives.empty?
|
1135
1344
|
inherited_dirs.merge(own_directives)
|
1136
1345
|
else
|
1137
1346
|
inherited_dirs
|
@@ -1142,7 +1351,11 @@ module GraphQL
|
|
1142
1351
|
# @param new_directive [Class]
|
1143
1352
|
# @return void
|
1144
1353
|
def directive(new_directive)
|
1145
|
-
|
1354
|
+
if use_visibility_profile?
|
1355
|
+
own_directives[new_directive.graphql_name] = new_directive
|
1356
|
+
else
|
1357
|
+
add_type_and_traverse(new_directive, root: false)
|
1358
|
+
end
|
1146
1359
|
end
|
1147
1360
|
|
1148
1361
|
def default_directives
|
@@ -1179,6 +1392,7 @@ module GraphQL
|
|
1179
1392
|
# @param mode [Symbol] Trace module will only be used for this trade mode
|
1180
1393
|
# @param options [Hash] Keywords that will be passed to the tracing class during `#initialize`
|
1181
1394
|
# @return [void]
|
1395
|
+
# @see GraphQL::Tracing::Trace for available tracing methods
|
1182
1396
|
def trace_with(trace_mod, mode: :default, **options)
|
1183
1397
|
if mode.is_a?(Array)
|
1184
1398
|
mode.each { |m| trace_with(trace_mod, mode: m, **options) }
|
@@ -1256,6 +1470,8 @@ module GraphQL
|
|
1256
1470
|
trace_class_for_mode.new(**trace_options)
|
1257
1471
|
end
|
1258
1472
|
|
1473
|
+
# @param new_analyzer [Class<GraphQL::Analysis::Analyzer>] An analyzer to run on queries to this schema
|
1474
|
+
# @see GraphQL::Analysis the analysis system
|
1259
1475
|
def query_analyzer(new_analyzer)
|
1260
1476
|
own_query_analyzers << new_analyzer
|
1261
1477
|
end
|
@@ -1264,6 +1480,8 @@ module GraphQL
|
|
1264
1480
|
find_inherited_value(:query_analyzers, EMPTY_ARRAY) + own_query_analyzers
|
1265
1481
|
end
|
1266
1482
|
|
1483
|
+
# @param new_analyzer [Class<GraphQL::Analysis::Analyzer>] An analyzer to run on multiplexes to this schema
|
1484
|
+
# @see GraphQL::Analysis the analysis system
|
1267
1485
|
def multiplex_analyzer(new_analyzer)
|
1268
1486
|
own_multiplex_analyzers << new_analyzer
|
1269
1487
|
end
|
@@ -1336,7 +1554,8 @@ module GraphQL
|
|
1336
1554
|
|
1337
1555
|
# @api private
|
1338
1556
|
def add_subscription_extension_if_necessary
|
1339
|
-
|
1557
|
+
# TODO: when there's a proper API for extending root types, migrat this to use it.
|
1558
|
+
if !defined?(@subscription_extension_added) && @subscription_object.is_a?(Class) && self.subscriptions
|
1340
1559
|
@subscription_extension_added = true
|
1341
1560
|
subscription.all_field_definitions.each do |field|
|
1342
1561
|
if !field.extensions.any? { |ext| ext.is_a?(Subscriptions::DefaultSubscriptionResolveExtension) }
|
@@ -1346,6 +1565,11 @@ module GraphQL
|
|
1346
1565
|
end
|
1347
1566
|
end
|
1348
1567
|
|
1568
|
+
# Called when execution encounters a `SystemStackError`. By default, it adds a client-facing error to the response.
|
1569
|
+
# You could modify this method to report this error to your bug tracker.
|
1570
|
+
# @param query [GraphQL::Query]
|
1571
|
+
# @param err [SystemStackError]
|
1572
|
+
# @return [void]
|
1349
1573
|
def query_stack_error(query, err)
|
1350
1574
|
query.context.errors.push(GraphQL::ExecutionError.new("This query is too large to execute."))
|
1351
1575
|
end
|
@@ -1404,11 +1628,34 @@ module GraphQL
|
|
1404
1628
|
end
|
1405
1629
|
end
|
1406
1630
|
|
1631
|
+
# Returns `DidYouMean` if it's defined.
|
1632
|
+
# Override this to return `nil` if you don't want to use `DidYouMean`
|
1633
|
+
def did_you_mean(new_dym = NOT_CONFIGURED)
|
1634
|
+
if NOT_CONFIGURED.equal?(new_dym)
|
1635
|
+
if defined?(@did_you_mean)
|
1636
|
+
@did_you_mean
|
1637
|
+
else
|
1638
|
+
find_inherited_value(:did_you_mean, defined?(DidYouMean) ? DidYouMean : nil)
|
1639
|
+
end
|
1640
|
+
else
|
1641
|
+
@did_you_mean = new_dym
|
1642
|
+
end
|
1643
|
+
end
|
1644
|
+
|
1407
1645
|
private
|
1408
1646
|
|
1409
1647
|
def add_trace_options_for(mode, new_options)
|
1410
|
-
|
1411
|
-
|
1648
|
+
if mode == :default
|
1649
|
+
own_trace_modes.each do |mode_name, t_class|
|
1650
|
+
if t_class <= DefaultTraceClass
|
1651
|
+
t_opts = trace_options_for(mode_name)
|
1652
|
+
t_opts.merge!(new_options)
|
1653
|
+
end
|
1654
|
+
end
|
1655
|
+
else
|
1656
|
+
t_opts = trace_options_for(mode)
|
1657
|
+
t_opts.merge!(new_options)
|
1658
|
+
end
|
1412
1659
|
nil
|
1413
1660
|
end
|
1414
1661
|
|
@@ -1485,7 +1732,7 @@ module GraphQL
|
|
1485
1732
|
end
|
1486
1733
|
|
1487
1734
|
def own_references_to
|
1488
|
-
@own_references_to ||= {}.
|
1735
|
+
@own_references_to ||= {}.compare_by_identity
|
1489
1736
|
end
|
1490
1737
|
|
1491
1738
|
def non_introspection_types
|
@@ -1501,7 +1748,7 @@ module GraphQL
|
|
1501
1748
|
end
|
1502
1749
|
|
1503
1750
|
def own_possible_types
|
1504
|
-
@own_possible_types ||= {}.
|
1751
|
+
@own_possible_types ||= {}.compare_by_identity
|
1505
1752
|
end
|
1506
1753
|
|
1507
1754
|
def own_union_memberships
|
@@ -1552,5 +1799,12 @@ module GraphQL
|
|
1552
1799
|
|
1553
1800
|
# Install these here so that subclasses will also install it.
|
1554
1801
|
self.connections = GraphQL::Pagination::Connections.new(schema: self)
|
1802
|
+
|
1803
|
+
# @api private
|
1804
|
+
module DefaultTraceClass
|
1805
|
+
end
|
1555
1806
|
end
|
1556
1807
|
end
|
1808
|
+
|
1809
|
+
require "graphql/schema/loader"
|
1810
|
+
require "graphql/schema/printer"
|