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