graphql 2.4.1 → 2.4.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 12a25d94ae9348527390bad889be7c918390c0a1b133735612ac5a80ca0c6633
4
- data.tar.gz: de4bb61a31dc643d359157dff498410f70a5a7bd18d6c254463a2a5294706949
3
+ metadata.gz: bbf9779d0fbc1da481a481d987489b980818c5ea6afb352f4e65f0654ea14163
4
+ data.tar.gz: 91528aabb657b8602c7f3143b6a9dc3a770a336f6a31af0f89fce1c27e5e00a0
5
5
  SHA512:
6
- metadata.gz: f85c5a5e4ab0083862c990fe6cd3f0ed99d36a414721d4c3d0a7a3e5c59042cdc5611a6b74d10d0e18525d9e51a32dc6aa1a2349c789b04dae75a835f4bb322a
7
- data.tar.gz: e0304dded75753771417672c704054a1daec13ab428ed92f97dbdcee2771f21874bfb6aedf9bd0054806ed97b4483b98376f03526b129d96628735c1933f0d35
6
+ metadata.gz: c73cedf9cd1fc6ab4d91f026dfe627cb1490d5888d1252f591b944359e1f537a479c5d7f7ceed691ddd79883ae1ba027dfb952e969d14617e6a19becee792aa6
7
+ data.tar.gz: 4d429bb74350c9fbbaa0e33498ccb193acfa6691f62342b38923965e69bc23bb377e6ade8a56b8f5d5c785ea24a2f6e04a47a8384000a45140d320e7461c6832
@@ -404,7 +404,7 @@ module GraphQL
404
404
  end
405
405
  end
406
406
 
407
- entry_point_types.compact! # TODO why is this necessary?!
407
+ entry_point_types.compact! # Root types might be nil
408
408
  entry_point_types.flatten! # handle multiple defns
409
409
  entry_point_types.each { |t| add_type(t, true) }
410
410
 
@@ -21,11 +21,27 @@ module GraphQL
21
21
  if migration_errors
22
22
  schema.visibility_profile_class = Migration
23
23
  end
24
+ @preload = preload
24
25
  @profiles = profiles
25
26
  @cached_profiles = {}
26
27
  @dynamic = dynamic
27
28
  @migration_errors = migration_errors
28
29
  if preload
30
+ # Traverse the schema now (and in the *_configured hooks below)
31
+ # To make sure things are loaded during boot
32
+ @preloaded_types = Set.new
33
+ types_to_visit = [
34
+ @schema.query,
35
+ @schema.mutation,
36
+ @schema.subscription,
37
+ *@schema.introspection_system.types.values,
38
+ *@schema.introspection_system.entry_points.map { |ep| ep.type.unwrap },
39
+ *@schema.orphan_types,
40
+ ]
41
+ # Root types may have been nil:
42
+ types_to_visit.compact!
43
+ ensure_all_loaded(types_to_visit)
44
+
29
45
  profiles.each do |profile_name, example_ctx|
30
46
  example_ctx[:visibility_profile] = profile_name
31
47
  prof = profile_for(example_ctx, profile_name)
@@ -34,6 +50,45 @@ module GraphQL
34
50
  end
35
51
  end
36
52
 
53
+ # @api private
54
+ def query_configured(query_type)
55
+ if @preload
56
+ ensure_all_loaded([query_type])
57
+ end
58
+ end
59
+
60
+ # @api private
61
+ def mutation_configured(mutation_type)
62
+ if @preload
63
+ ensure_all_loaded([mutation_type])
64
+ end
65
+ end
66
+
67
+ # @api private
68
+ def subscription_configured(subscription_type)
69
+ if @preload
70
+ ensure_all_loaded([subscription_type])
71
+ end
72
+ end
73
+
74
+ # @api private
75
+ def orphan_types_configured(orphan_types)
76
+ if @preload
77
+ ensure_all_loaded(orphan_types)
78
+ end
79
+ end
80
+
81
+ # @api private
82
+ def introspection_system_configured(introspection_system)
83
+ if @preload
84
+ introspection_types = [
85
+ *@schema.introspection_system.types.values,
86
+ *@schema.introspection_system.entry_points.map { |ep| ep.type.unwrap },
87
+ ]
88
+ ensure_all_loaded(introspection_types)
89
+ end
90
+ end
91
+
37
92
  # Make another Visibility for `schema` based on this one
38
93
  # @return [Visibility]
39
94
  # @api private
@@ -70,6 +125,19 @@ module GraphQL
70
125
  @schema.visibility_profile_class.new(context: context, schema: @schema)
71
126
  end
72
127
  end
128
+
129
+ private
130
+
131
+ def ensure_all_loaded(types_to_visit)
132
+ while (type = types_to_visit.shift)
133
+ if type.kind.fields? && @preloaded_types.add?(type)
134
+ type.all_field_definitions.each do |field_defn|
135
+ field_defn.ensure_loaded
136
+ types_to_visit << field_defn.type.unwrap
137
+ end
138
+ end
139
+ end
140
+ end
73
141
  end
74
142
  end
75
143
  end
@@ -445,7 +445,12 @@ module GraphQL
445
445
  dup_defn = new_query_object || yield
446
446
  raise GraphQL::Error, "Second definition of `query(...)` (#{dup_defn.inspect}) is invalid, already configured with #{@query_object.inspect}"
447
447
  elsif use_visibility_profile?
448
- @query_object = block_given? ? lazy_load_block : new_query_object
448
+ if block_given?
449
+ @query_object = lazy_load_block
450
+ else
451
+ @query_object = new_query_object
452
+ self.visibility.query_configured(@query_object)
453
+ end
449
454
  else
450
455
  @query_object = new_query_object || lazy_load_block.call
451
456
  add_type_and_traverse(@query_object, root: true)
@@ -453,6 +458,8 @@ module GraphQL
453
458
  nil
454
459
  elsif @query_object.is_a?(Proc)
455
460
  @query_object = @query_object.call
461
+ self.visibility&.query_configured(@query_object)
462
+ @query_object
456
463
  else
457
464
  @query_object || find_inherited_value(:query)
458
465
  end
@@ -472,7 +479,12 @@ module GraphQL
472
479
  dup_defn = new_mutation_object || yield
473
480
  raise GraphQL::Error, "Second definition of `mutation(...)` (#{dup_defn.inspect}) is invalid, already configured with #{@mutation_object.inspect}"
474
481
  elsif use_visibility_profile?
475
- @mutation_object = block_given? ? lazy_load_block : new_mutation_object
482
+ if block_given?
483
+ @mutation_object = lazy_load_block
484
+ else
485
+ @mutation_object = new_mutation_object
486
+ self.visibility.mutation_configured(@mutation_object)
487
+ end
476
488
  else
477
489
  @mutation_object = new_mutation_object || lazy_load_block.call
478
490
  add_type_and_traverse(@mutation_object, root: true)
@@ -480,6 +492,8 @@ module GraphQL
480
492
  nil
481
493
  elsif @mutation_object.is_a?(Proc)
482
494
  @mutation_object = @mutation_object.call
495
+ self.visibility&.mutation_configured(@query_object)
496
+ @mutation_object
483
497
  else
484
498
  @mutation_object || find_inherited_value(:mutation)
485
499
  end
@@ -499,7 +513,12 @@ module GraphQL
499
513
  dup_defn = new_subscription_object || yield
500
514
  raise GraphQL::Error, "Second definition of `subscription(...)` (#{dup_defn.inspect}) is invalid, already configured with #{@subscription_object.inspect}"
501
515
  elsif use_visibility_profile?
502
- @subscription_object = block_given? ? lazy_load_block : new_subscription_object
516
+ if block_given?
517
+ @subscription_object = lazy_load_block
518
+ else
519
+ @subscription_object = new_subscription_object
520
+ self.visibility.subscription_configured(@subscription_object)
521
+ end
503
522
  add_subscription_extension_if_necessary
504
523
  else
505
524
  @subscription_object = new_subscription_object || lazy_load_block.call
@@ -510,6 +529,7 @@ module GraphQL
510
529
  elsif @subscription_object.is_a?(Proc)
511
530
  @subscription_object = @subscription_object.call
512
531
  add_subscription_extension_if_necessary
532
+ self.visibility.subscription_configured(@subscription_object)
513
533
  @subscription_object
514
534
  else
515
535
  @subscription_object || find_inherited_value(:subscription)
@@ -695,20 +715,27 @@ module GraphQL
695
715
  type.fields(context)
696
716
  end
697
717
 
718
+ # Pass a custom introspection module here to use it for this schema.
719
+ # @param new_introspection_namespace [Module] If given, use this module for custom introspection on the schema
720
+ # @return [Module, nil] The configured namespace, if there is one
698
721
  def introspection(new_introspection_namespace = nil)
699
722
  if new_introspection_namespace
700
723
  @introspection = new_introspection_namespace
701
724
  # reset this cached value:
702
725
  @introspection_system = nil
726
+ introspection_system
727
+ @introspection
703
728
  else
704
729
  @introspection || find_inherited_value(:introspection)
705
730
  end
706
731
  end
707
732
 
733
+ # @return [Schema::IntrospectionSystem] Based on {introspection}
708
734
  def introspection_system
709
735
  if !@introspection_system
710
736
  @introspection_system = Schema::IntrospectionSystem.new(self)
711
737
  @introspection_system.resolve_late_bindings
738
+ self.visibility&.introspection_system_configured(@introspection_system)
712
739
  end
713
740
  @introspection_system
714
741
  end
@@ -952,6 +979,13 @@ module GraphQL
952
979
  end
953
980
  end
954
981
 
982
+ # Tell the schema about these types so that they can be registered as implementations of interfaces in the schema.
983
+ #
984
+ # This method must be used when an object type is connected to the schema as an interface implementor but
985
+ # 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.
986
+ #
987
+ # @param new_orphan_types [Array<Class<GraphQL::Schema::Object>>] Object types to register as implementations of interfaces in the schema.
988
+ # @return [Array<Class<GraphQL::Schema::Object>>] All previously-registered orphan types for this schema
955
989
  def orphan_types(*new_orphan_types)
956
990
  if new_orphan_types.any?
957
991
  new_orphan_types = new_orphan_types.flatten
@@ -968,6 +1002,7 @@ module GraphQL
968
1002
  end
969
1003
  add_type_and_traverse(new_orphan_types, root: false) unless use_visibility_profile?
970
1004
  own_orphan_types.concat(new_orphan_types.flatten)
1005
+ self.visibility&.orphan_types_configured(new_orphan_types)
971
1006
  end
972
1007
 
973
1008
  inherited_ot = find_inherited_value(:orphan_types, nil)
@@ -14,7 +14,9 @@ module GraphQL
14
14
  node_name: parent_type.graphql_name
15
15
  ))
16
16
  else
17
- message = "Field '#{node.name}' doesn't exist on type '#{parent_type.graphql_name}'#{context.did_you_mean_suggestion(node.name, context.types.fields(parent_type).map(&:graphql_name))}"
17
+ possible_fields = possible_fields(context, parent_type)
18
+ suggestion = context.did_you_mean_suggestion(node.name, possible_fields)
19
+ message = "Field '#{node.name}' doesn't exist on type '#{parent_type.graphql_name}'#{suggestion}"
18
20
  add_error(GraphQL::StaticValidation::FieldsAreDefinedOnTypeError.new(
19
21
  message,
20
22
  nodes: node,
@@ -26,6 +28,13 @@ module GraphQL
26
28
  super
27
29
  end
28
30
  end
31
+
32
+ private
33
+
34
+ def possible_fields(context, parent_type)
35
+ return EmptyObjects::EMPTY_ARRAY if parent_type.kind.leaf?
36
+ context.types.fields(parent_type).map(&:graphql_name)
37
+ end
29
38
  end
30
39
  end
31
40
  end
@@ -25,7 +25,7 @@ module GraphQL
25
25
  def validate_field_selections(ast_node, resolved_type)
26
26
  msg = if resolved_type.nil?
27
27
  nil
28
- elsif resolved_type.kind.scalar? && ast_node.selections.any?
28
+ elsif ast_node.selections.any? && resolved_type.kind.leaf?
29
29
  selection_strs = ast_node.selections.map do |n|
30
30
  case n
31
31
  when GraphQL::Language::Nodes::InlineFragment
@@ -38,7 +38,7 @@ module GraphQL
38
38
  raise "Invariant: unexpected selection node: #{n}"
39
39
  end
40
40
  end
41
- "Selections can't be made on scalars (%{node_name} returns #{resolved_type.graphql_name} but has selections [#{selection_strs.join(", ")}])"
41
+ "Selections can't be made on #{resolved_type.kind.name.sub("_", " ").downcase}s (%{node_name} returns #{resolved_type.graphql_name} but has selections [#{selection_strs.join(", ")}])"
42
42
  elsif resolved_type.kind.fields? && ast_node.selections.empty?
43
43
  "Field must have selections (%{node_name} returns #{resolved_type.graphql_name} but has no selections. Did you mean '#{ast_node.name} { ... }'?)"
44
44
  else
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
- VERSION = "2.4.1"
3
+ VERSION = "2.4.2"
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphql
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.1
4
+ version: 2.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Mosolgo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-11-04 00:00:00.000000000 Z
11
+ date: 2024-11-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: base64