Thanks to visit codestin.com
Credit goes to GitHub.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -198,9 +198,13 @@ public void forEachFieldDefinition(GraphQLSchema schema, Consumer<GraphQLFieldDe
return;
}

var fieldVisibility = schema.getCodeRegistry().getFieldVisibility();
for (String objectTypeName : objectTypeNames) {
GraphQLObjectType type = (GraphQLObjectType) assertNotNull(schema.getType(objectTypeName));
consumer.accept(assertNotNull(type.getField(fieldName), "No field %s found for type %s", fieldName, objectTypeName));
// Use field visibility to allow custom visibility implementations to provide placeholder fields
// for fields that don't exist on the local schema (e.g., in federated subgraphs)
GraphQLFieldDefinition field = fieldVisibility.getFieldDefinition(type, fieldName);
consumer.accept(assertNotNull(field, "No field %s found for type %s", fieldName, objectTypeName));
}
}

Expand All @@ -223,7 +227,8 @@ private GraphQLFieldDefinition getOneFieldDefinition(GraphQLSchema schema) {

String objectTypeName = objectTypeNames.iterator().next();
GraphQLObjectType type = (GraphQLObjectType) assertNotNull(schema.getType(objectTypeName));
return assertNotNull(type.getField(fieldName), "No field %s found for type %s", fieldName, objectTypeName);
var fieldVisibility = schema.getCodeRegistry().getFieldVisibility();
return assertNotNull(fieldVisibility.getFieldDefinition(type, fieldName), "No field %s found for type %s", fieldName, objectTypeName);
}

private static GraphQLFieldDefinition resolveIntrospectionField(GraphQLSchema schema, Set<String> objectTypeNames, String fieldName) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,85 @@ class ExecutableNormalizedFieldTest extends Specification {
dogFields.collect { it.name } == ["id", "name", "woof"]
}

def "forEachFieldDefinition respects custom GraphqlFieldVisibility"() {
// This test verifies that ExecutableNormalizedField.forEachFieldDefinition() uses
// GraphqlFieldVisibility to look up fields. This is important for federated subgraphs
// where the supergraph may have fields that don't exist in the local schema, but
// a custom visibility can provide placeholder field definitions.
String schema = """
type Query{
pet: Pet
}
type Pet {
id: ID
name: String
}
"""

// Create a custom visibility that provides a "virtual" field that doesn't exist on the type
def customVisibility = new graphql.schema.visibility.GraphqlFieldVisibility() {
@Override
List<graphql.schema.GraphQLFieldDefinition> getFieldDefinitions(graphql.schema.GraphQLFieldsContainer fieldsContainer) {
def fields = new ArrayList<>(fieldsContainer.getFieldDefinitions())
// Add a virtual "age" field for Pet type
if (fieldsContainer.name == "Pet") {
fields.add(graphql.schema.GraphQLFieldDefinition.newFieldDefinition()
.name("age")
.type(graphql.Scalars.GraphQLInt)
.build())
}
return fields
}

@Override
graphql.schema.GraphQLFieldDefinition getFieldDefinition(graphql.schema.GraphQLFieldsContainer fieldsContainer, String fieldName) {
// First check if the field exists on the type
def field = fieldsContainer.getFieldDefinition(fieldName)
if (field != null) {
return field
}
// Provide virtual "age" field for Pet type
if (fieldsContainer.name == "Pet" && fieldName == "age") {
return graphql.schema.GraphQLFieldDefinition.newFieldDefinition()
.name("age")
.type(graphql.Scalars.GraphQLInt)
.build()
}
return null
}
}

GraphQLSchema graphQLSchema = TestUtil.schema(schema)

// Rebuild schema with custom visibility
def codeRegistry = graphql.schema.GraphQLCodeRegistry.newCodeRegistry(graphQLSchema.getCodeRegistry())
.fieldVisibility(customVisibility)
.build()
graphQLSchema = graphQLSchema.transform { builder -> builder.codeRegistry(codeRegistry) }

// Query that includes the "virtual" age field that exists only through visibility
String query = """
{
pet {
id
name
age
}
}
"""
Document document = TestUtil.parseQuery(query)

when:
// This should succeed because the visibility provides the "age" field
def normalizedOperation = ExecutableNormalizedOperationFactory.createExecutableNormalizedOperation(
graphQLSchema, document, null, CoercedVariables.emptyVariables())
def pet = normalizedOperation.getTopLevelFields()[0]
def fieldNames = pet.getChildren().collect { it.name }

then:
// The age field should be found via the custom visibility
fieldNames.contains("age")
fieldNames.containsAll(["id", "name", "age"])
}

}
Loading