File tree Expand file tree Collapse file tree
test/Fusion.Composition.Tests Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -136,7 +136,7 @@ public static List<IDirective> GetPossibleFusionLookupDirectivesById(
136136
137137 public static void RemoveUnreferencedDefinitions (
138138 this MutableSchemaDefinition schema ,
139- ImmutableSortedSet < MutableSchemaDefinition > sourceSchemas )
139+ IReadOnlySet < string > preservedTypeNames )
140140 {
141141 var touchedDefinitions = new HashSet < ITypeSystemMember > ( ) ;
142142 var backlog = new Stack < ITypeSystemMember > ( ) ;
@@ -161,8 +161,6 @@ public static void RemoveUnreferencedDefinitions(
161161 backlog . Push ( schema . SubscriptionType ) ;
162162 }
163163
164- var preservedTypeNames = GetPreservedTypeNames ( sourceSchemas ) ;
165-
166164 foreach ( var typeName in preservedTypeNames )
167165 {
168166 if ( schema . Types . TryGetType ( typeName , out var inputType ) )
@@ -260,7 +258,8 @@ private static List<IDirective> GetFusionLookupDirectives(
260258 /// Returns a list of type names for types that must be preserved in the merged schema
261259 /// even if they are not directly referenced.
262260 /// </summary>
263- private static HashSet < string > GetPreservedTypeNames ( ImmutableSortedSet < MutableSchemaDefinition > sourceSchemas )
261+ public static HashSet < string > GetPreservedTypeNames (
262+ ImmutableSortedSet < MutableSchemaDefinition > sourceSchemas )
264263 {
265264 var preservedTypeNames = new HashSet < string > ( ) ;
266265
Original file line number Diff line number Diff line change @@ -78,6 +78,18 @@ public CompositionResult<MutableSchemaDefinition> Compose()
7878 return enrichmentResult . Errors ;
7979 }
8080
81+ // Prune unreachable definitions from each source schema before validation, so types
82+ // stripped by @excludeByTag (or otherwise unreferenced) are not validated or merged.
83+ if ( _schemaComposerOptions . Merger . RemoveUnreferencedDefinitions )
84+ {
85+ var preservedTypeNames = MutableSchemaDefinitionExtensions . GetPreservedTypeNames ( schemas ) ;
86+
87+ foreach ( var schema in schemas )
88+ {
89+ schema . RemoveUnreferencedDefinitions ( preservedTypeNames ) ;
90+ }
91+ }
92+
8193 // Validate Source Schemas
8294 var validationResult =
8395 new SourceSchemaValidator ( schemas , s_sourceSchemaRules , _log ) . Validate ( ) ;
Original file line number Diff line number Diff line change @@ -107,7 +107,8 @@ public CompositionResult<MutableSchemaDefinition> Merge()
107107 // Remove unreferenced definitions.
108108 if ( _options . RemoveUnreferencedDefinitions )
109109 {
110- mergedSchema . RemoveUnreferencedDefinitions ( _schemas ) ;
110+ mergedSchema . RemoveUnreferencedDefinitions (
111+ MutableSchemaDefinitionExtensions . GetPreservedTypeNames ( _schemas ) ) ;
111112 }
112113
113114 // Add Fusion definitions.
Original file line number Diff line number Diff line change @@ -41,6 +41,76 @@ type Product {
4141 entry . Message ) ;
4242 }
4343
44+ [ Fact ]
45+ public void Compose_OrphanedTypeAfterTagExclusion_DoesNotProduceShareableError ( )
46+ {
47+ // arrange
48+ // Schema A's Product is only reachable via Mutation. When Mutation is removed by
49+ // tag exclusion, Product becomes orphaned. Without pruning, Product.name would
50+ // collide with Schema B's Product.name and trigger an InvalidFieldSharing error.
51+ var schemaComposer = new SchemaComposer (
52+ [
53+ new SourceSchemaText (
54+ "A" ,
55+ """
56+ type Query {
57+ book(id: ID!): Book @lookup
58+ }
59+
60+ type Mutation @tag(name: "internal") {
61+ createProduct(name: String!): Product
62+ }
63+
64+ type Book {
65+ id: ID!
66+ title: String!
67+ }
68+
69+ type Product {
70+ id: ID!
71+ name: String!
72+ }
73+
74+ directive @tag(name: String!) repeatable on OBJECT
75+ """ ) ,
76+ new SourceSchemaText (
77+ "B" ,
78+ """
79+ type Query {
80+ productById(id: ID!): Product @lookup
81+ }
82+
83+ type Product {
84+ id: ID!
85+ name: String!
86+ }
87+ """ )
88+ ] ,
89+ new SchemaComposerOptions
90+ {
91+ Merger = { AddFusionDefinitions = false } ,
92+ SourceSchemas =
93+ {
94+ [ "A" ] = new SourceSchemaOptions
95+ {
96+ Preprocessor = new SourceSchemaPreprocessorOptions
97+ {
98+ ExcludeByTag = [ "internal" ]
99+ }
100+ }
101+ }
102+ } ,
103+ new CompositionLog ( ) ) ;
104+
105+ // act
106+ var result = schemaComposer . Compose ( ) ;
107+
108+ // assert
109+ Assert . True ( result . IsSuccess ) ;
110+ Assert . False ( result . Value . Types . ContainsName ( "Mutation" ) ) ;
111+ Assert . True ( result . Value . Types . ContainsName ( "Product" ) ) ;
112+ }
113+
44114 [ Fact ]
45115 public void Compose_WithExtensions_AppliesExtensions ( )
46116 {
You can’t perform that action at this time.
0 commit comments