11# frozen_string_literal: true
22
33require_relative "composer/base_validator"
4- require_relative "composer/supergraph_directives"
54require_relative "composer/validate_interfaces"
65require_relative "composer/validate_type_resolvers"
76require_relative "composer/type_resolver_config"
@@ -23,6 +22,9 @@ class Composer
2322
2423 # @api private
2524 BASIC_VALUE_MERGER = -> ( values_by_location , _info ) { values_by_location . values . find { !_1 . nil? } }
25+
26+ # @api private
27+ VISIBILITY_PROFILES_MERGER = -> ( values_by_location , _info ) { values_by_location . values . reduce ( :& ) }
2628
2729 # @api private
2830 BASIC_ROOT_FIELD_LOCATION_SELECTOR = -> ( locations , _info ) { locations . last }
@@ -52,6 +54,7 @@ def initialize(
5254 query_name : "Query" ,
5355 mutation_name : "Mutation" ,
5456 subscription_name : "Subscription" ,
57+ visibility_profiles : [ ] ,
5558 description_merger : nil ,
5659 deprecation_merger : nil ,
5760 default_value_merger : nil ,
@@ -71,6 +74,7 @@ def initialize(
7174 @resolver_map = { }
7275 @resolver_configs = { }
7376 @mapped_type_names = { }
77+ @visibility_profiles = Set . new ( visibility_profiles )
7478 @subgraph_directives_by_name_and_location = nil
7579 @subgraph_types_by_name_and_location = nil
7680 @schema_directives = nil
@@ -85,9 +89,9 @@ def perform(locations_input)
8589
8690 directives_to_omit = [
8791 GraphQL ::Stitching . stitch_directive ,
88- KeyDirective . graphql_name ,
89- ResolverDirective . graphql_name ,
90- SourceDirective . graphql_name ,
92+ Directives :: SupergraphKey . graphql_name ,
93+ Directives :: SupergraphResolver . graphql_name ,
94+ Directives :: SupergraphSource . graphql_name ,
9195 ]
9296
9397 # "directive_name" => "location" => subgraph_directive
@@ -181,6 +185,10 @@ def perform(locations_input)
181185 expand_abstract_resolvers ( schema , schemas )
182186 apply_supergraph_directives ( schema , @resolver_map , @field_map )
183187
188+ if ( visibility_def = schema . directives [ GraphQL ::Stitching . visibility_directive ] )
189+ visibility_def . get_argument ( "profiles" ) . default_value ( @visibility_profiles . to_a . sort )
190+ end
191+
184192 supergraph = Supergraph . from_definition ( schema , executables : executables )
185193
186194 COMPOSITION_VALIDATORS . each do |validator_class |
@@ -237,7 +245,7 @@ def build_scalar_type(type_name, types_by_location)
237245
238246 builder = self
239247
240- Class . new ( GraphQL ::Schema :: Scalar ) do
248+ Class . new ( GraphQL ::Stitching :: Supergraph :: BaseScalar ) do
241249 graphql_name ( type_name )
242250 description ( builder . merge_descriptions ( type_name , types_by_location ) )
243251 builder . build_merged_directives ( type_name , types_by_location , self )
@@ -264,7 +272,7 @@ def build_enum_type(type_name, types_by_location, enum_usage)
264272 end
265273 end
266274
267- Class . new ( GraphQL ::Schema :: Enum ) do
275+ Class . new ( GraphQL ::Stitching :: Supergraph :: BaseEnum ) do
268276 graphql_name ( type_name )
269277 description ( builder . merge_descriptions ( type_name , types_by_location ) )
270278 builder . build_merged_directives ( type_name , types_by_location , self )
@@ -286,7 +294,7 @@ def build_enum_type(type_name, types_by_location, enum_usage)
286294 def build_object_type ( type_name , types_by_location )
287295 builder = self
288296
289- Class . new ( GraphQL ::Schema :: Object ) do
297+ Class . new ( GraphQL ::Stitching :: Supergraph :: BaseObject ) do
290298 graphql_name ( type_name )
291299 description ( builder . merge_descriptions ( type_name , types_by_location ) )
292300
@@ -306,7 +314,7 @@ def build_interface_type(type_name, types_by_location)
306314 builder = self
307315
308316 Module . new do
309- include GraphQL ::Schema :: Interface
317+ include GraphQL ::Stitching :: Supergraph :: BaseInterface
310318 graphql_name ( type_name )
311319 description ( builder . merge_descriptions ( type_name , types_by_location ) )
312320
@@ -325,7 +333,7 @@ def build_interface_type(type_name, types_by_location)
325333 def build_union_type ( type_name , types_by_location )
326334 builder = self
327335
328- Class . new ( GraphQL ::Schema :: Union ) do
336+ Class . new ( GraphQL ::Stitching :: Supergraph :: BaseUnion ) do
329337 graphql_name ( type_name )
330338 description ( builder . merge_descriptions ( type_name , types_by_location ) )
331339
@@ -340,7 +348,7 @@ def build_union_type(type_name, types_by_location)
340348 def build_input_object_type ( type_name , types_by_location )
341349 builder = self
342350
343- Class . new ( GraphQL ::Schema :: InputObject ) do
351+ Class . new ( GraphQL ::Stitching :: Supergraph :: BaseInputObject ) do
344352 graphql_name ( type_name )
345353 description ( builder . merge_descriptions ( type_name , types_by_location ) )
346354 builder . build_merged_arguments ( type_name , types_by_location , self )
@@ -451,6 +459,7 @@ def build_merged_directives(type_name, members_by_location, owner, field_name: n
451459 end
452460
453461 directives_by_name_location . each do |directive_name , directives_by_location |
462+ kwarg_merger = @directive_kwarg_merger
454463 directive_class = @schema_directives [ directive_name ]
455464 next unless directive_class
456465
@@ -467,8 +476,20 @@ def build_merged_directives(type_name, members_by_location, owner, field_name: n
467476 end
468477 end
469478
479+ if directive_class . graphql_name == GraphQL ::Stitching . visibility_directive
480+ unless GraphQL ::Stitching . supports_visibility?
481+ raise CompositionError , "Using `@#{ GraphQL ::Stitching . visibility_directive } ` directive " \
482+ "for schema visibility controls requires GraphQL Ruby v2.4.15 or later."
483+ end
484+
485+ if ( profiles = kwarg_values_by_name_location [ "profiles" ] )
486+ @visibility_profiles . merge ( profiles . each_value . reduce ( &:| ) )
487+ kwarg_merger = VISIBILITY_PROFILES_MERGER
488+ end
489+ end
490+
470491 kwargs = kwarg_values_by_name_location . each_with_object ( { } ) do |( kwarg_name , kwarg_values_by_location ) , memo |
471- memo [ kwarg_name . to_sym ] = @directive_kwarg_merger . call ( kwarg_values_by_location , {
492+ memo [ kwarg_name . to_sym ] = kwarg_merger . call ( kwarg_values_by_location , {
472493 type_name : type_name ,
473494 field_name : field_name ,
474495 argument_name : argument_name ,
@@ -693,8 +714,8 @@ def apply_supergraph_directives(schema, resolvers_by_type_name, locations_by_typ
693714
694715 keys_for_type . each do |key , locations |
695716 locations . each do |location |
696- schema_directives [ KeyDirective . graphql_name ] ||= KeyDirective
697- type . directive ( KeyDirective , key : key , location : location )
717+ schema_directives [ Directives :: SupergraphKey . graphql_name ] ||= Directives :: SupergraphKey
718+ type . directive ( Directives :: SupergraphKey , key : key , location : location )
698719 end
699720 end
700721
@@ -710,8 +731,8 @@ def apply_supergraph_directives(schema, resolvers_by_type_name, locations_by_typ
710731 type_name : ( resolver . type_name if resolver . type_name != type_name ) ,
711732 }
712733
713- schema_directives [ ResolverDirective . graphql_name ] ||= ResolverDirective
714- type . directive ( ResolverDirective , **params . tap ( &:compact! ) )
734+ schema_directives [ Directives :: SupergraphResolver . graphql_name ] ||= Directives :: SupergraphResolver
735+ type . directive ( Directives :: SupergraphResolver , **params . tap ( &:compact! ) )
715736 end
716737 end
717738
@@ -737,8 +758,8 @@ def apply_supergraph_directives(schema, resolvers_by_type_name, locations_by_typ
737758
738759 # Apply source directives to annotate the possible locations of each field
739760 locations_for_field . each do |location |
740- schema_directives [ SourceDirective . graphql_name ] ||= SourceDirective
741- field . directive ( SourceDirective , location : location )
761+ schema_directives [ Directives :: SupergraphSource . graphql_name ] ||= Directives :: SupergraphSource
762+ field . directive ( Directives :: SupergraphSource , location : location )
742763 end
743764 end
744765 end
0 commit comments