Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DataFetchResult generaton #1431

Merged
merged 20 commits into from
Feb 24, 2024
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
159 changes: 81 additions & 78 deletions docs/codegen-options.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ public class GraphQLCodegenGradleTask extends DefaultTask implements GraphQLCode
private Set<String> typesAsInterfaces = new HashSet<>();
private Set<String> resolverArgumentAnnotations = new HashSet<>();
private Set<String> parametrizedResolverAnnotations = new HashSet<>();
private Set<String> fieldsWithDataFetcherResult = new HashSet<>();
private final RelayConfig relayConfig = new RelayConfig();


Expand Down Expand Up @@ -193,6 +194,8 @@ public void generate() throws Exception {
fieldsWithoutResolvers != null ? fieldsWithoutResolvers : new HashSet<>());
mappingConfig.setFieldsToExcludeFromGeneration(
fieldsToExcludeFromGeneration != null ? fieldsToExcludeFromGeneration : new HashSet<>());
mappingConfig.setFieldsWithDataFetcherResult(
fieldsWithDataFetcherResult != null ? fieldsWithDataFetcherResult : new HashSet<>());
mappingConfig.setTypesAsInterfaces(
typesAsInterfaces != null ? typesAsInterfaces : new HashSet<>());
mappingConfig.setResolverArgumentAnnotations(
Expand Down Expand Up @@ -815,6 +818,17 @@ public void setFieldsToExcludeFromGeneration(Set<String> fieldsToExcludeFromGene
this.fieldsToExcludeFromGeneration = fieldsToExcludeFromGeneration;
}

@Input
@Optional
@Override
public Set<String> getFieldsWithDataFetcherResult() {
return fieldsWithDataFetcherResult;
}

public void setFieldsWithDataFetcherResult(Set<String> fieldsWithDataFetcherResult) {
this.fieldsWithDataFetcherResult = fieldsWithDataFetcherResult;
}

@Input
@Optional
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,9 @@ public class GraphQLCodegenMojo extends AbstractMojo implements GraphQLCodegenCo
@Parameter
private String[] fieldsToExcludeFromGeneration;

@Parameter
private String[] fieldsWithDataFetcherResult;

@Parameter
private RelayConfig relayConfig = new RelayConfig();

Expand Down Expand Up @@ -305,6 +308,7 @@ public void execute() throws MojoExecutionException {
mappingConfig.setFieldsWithResolvers(mapToHashSet(fieldsWithResolvers));
mappingConfig.setFieldsWithoutResolvers(mapToHashSet(fieldsWithoutResolvers));
mappingConfig.setFieldsToExcludeFromGeneration(mapToHashSet(fieldsToExcludeFromGeneration));
mappingConfig.setFieldsWithDataFetcherResult(mapToHashSet(fieldsWithDataFetcherResult));
mappingConfig.setRelayConfig(relayConfig);

mappingConfig.setGenerateClient(generateClient);
Expand Down Expand Up @@ -627,6 +631,11 @@ public Set<String> getFieldsToExcludeFromGeneration() {
return mapToHashSet(fieldsToExcludeFromGeneration);
}

@Override
public Set<String> getFieldsWithDataFetcherResult() {
return mapToHashSet(fieldsWithDataFetcherResult);
}

@Override
public Boolean getGenerateAllMethodInProjection() {
return generateAllMethodInProjection;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,17 @@
import com.kobylynskyi.graphql.codegen.model.NamedDefinition;
import com.kobylynskyi.graphql.codegen.model.graphql.GraphQLOperation;
import com.kobylynskyi.graphql.codegen.utils.Utils;
import graphql.language.Directive;
import graphql.language.InputValueDefinition;
import graphql.language.NullValue;

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static java.util.Arrays.asList;

Expand Down Expand Up @@ -108,7 +111,8 @@ public boolean isPrimitive(String possiblyPrimitiveType) {

@Override
public NamedDefinition getLanguageType(MappingContext mappingContext, String graphQLType, String name,
String parentTypeName, boolean mandatory, boolean collection) {
String parentTypeName, boolean mandatory, boolean collection,
List<Directive> directives) {
Map<String, String> customTypesMapping = mappingContext.getCustomTypesMapping();
Set<String> serializeFieldsUsingObjectMapper = mappingContext.getUseObjectMapperForRequestSerialization();
String langTypeName;
Expand All @@ -122,6 +126,9 @@ public NamedDefinition getLanguageType(MappingContext mappingContext, String gra
} else {
langTypeName = DataModelMapper.getModelClassNameWithPrefixAndSuffix(mappingContext, graphQLType);
}

langTypeName = wrapWithDataFetcherResultIfRequired(mappingContext, directives, langTypeName, name);

if (serializeFieldsUsingObjectMapper.contains(graphQLType) ||
(name != null && parentTypeName != null &&
serializeFieldsUsingObjectMapper.contains(parentTypeName + "." + name))) {
Expand Down Expand Up @@ -164,4 +171,26 @@ public String wrapApiDefaultValueIfRequired(MappingContext mappingContext, Named
}
}

}
private String wrapWithDataFetcherResultIfRequired(MappingContext mappingContext,
List<Directive> directives,
String langTypeName,
String name) {
Set<String> fieldsWithDataFetcherResult = mappingContext.getFieldsWithDataFetcherResult();
Set<String> directivesNames = directives.stream()
.map(directive -> "@" + directive.getName())
.collect(Collectors.toSet());

// Create the representation of 'name'
String nameRepresentation = langTypeName + "." + name;

boolean shouldWrap = directivesNames.stream().anyMatch(fieldsWithDataFetcherResult::contains)
|| fieldsWithDataFetcherResult.contains(langTypeName)
|| fieldsWithDataFetcherResult.contains(nameRepresentation);

if (shouldWrap) {
langTypeName = "graphql.execution.DataFetcherResult<" + langTypeName + ">";
}

return langTypeName;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,9 @@ private ParameterDefinition mapField(MappingContext mappingContext,
ExtendedFieldDefinition fieldDef,
ExtendedDefinition<?, ?> parentDefinition) {
NamedDefinition namedDefinition = graphQLTypeMapper
.getLanguageType(mappingContext, fieldDef.getType(), fieldDef.getName(), parentDefinition.getName());
.getLanguageType(mappingContext, fieldDef.getType(), fieldDef.getName(), parentDefinition.getName(),
fieldDef.getDirectives()
);

ParameterDefinition parameter = new ParameterDefinition();
parameter.setName(dataModelMapper.capitalizeIfRestricted(mappingContext, fieldDef.getName()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,23 @@ public NamedDefinition getLanguageType(MappingContext mappingContext, Type<?> gr
return getLanguageType(mappingContext, graphqlType, name, parentTypeName, false, false);
}

/**
* Convert GraphQL type to a corresponding language-specific type (java/scala/kotlin/etc)
*
* @param mappingContext Global mapping context
* @param graphqlType GraphQL type
* @param name GraphQL type name
* @param parentTypeName Name of the parent type
* @param directives GraphQL field directives
* @return Corresponding language-specific type (java/scala/kotlin/etc)
*/
public NamedDefinition getLanguageType(MappingContext mappingContext, Type<?> graphqlType, String name,
String parentTypeName, List<Directive> directives) {
return getLanguageType(mappingContext, graphqlType, name, parentTypeName, false, false,
directives
);
}

/**
* Convert GraphQL type to a corresponding language-specific type (java/scala/kotlin/etc)
*
Expand All @@ -231,12 +248,32 @@ public NamedDefinition getLanguageType(MappingContext mappingContext, Type<?> gr
public NamedDefinition getLanguageType(MappingContext mappingContext, Type<?> graphqlType,
String name, String parentTypeName,
boolean mandatory, boolean collection) {
return getLanguageType(mappingContext, graphqlType, name, parentTypeName, mandatory, collection,
Collections.emptyList()
);
}

/**
* Convert GraphQL type to a corresponding language-specific type (java/scala/kotlin/etc)
*
* @param mappingContext Global mapping context
* @param graphqlType GraphQL type
* @param name GraphQL type name
* @param parentTypeName Name of the parent type
* @param mandatory GraphQL type is non-null
* @param collection GraphQL type is collection
* @param directives GraphQL field directives
* @return Corresponding language-specific type (java/scala/kotlin/etc)
*/
public NamedDefinition getLanguageType(MappingContext mappingContext, Type<?> graphqlType,
String name, String parentTypeName,
boolean mandatory, boolean collection, List<Directive> directives) {
if (graphqlType instanceof TypeName) {
return getLanguageType(mappingContext, ((TypeName) graphqlType).getName(), name, parentTypeName, mandatory,
collection);
collection, directives);
} else if (graphqlType instanceof ListType) {
NamedDefinition mappedCollectionType = getLanguageType(mappingContext, ((ListType) graphqlType).getType(),
name, parentTypeName, false, true);
name, parentTypeName, false, true, directives);
if (mappedCollectionType.isInterfaceOrUnion() &&
isInterfaceOrUnion(mappingContext, parentTypeName)) {
mappedCollectionType.setJavaName(
Expand All @@ -247,8 +284,8 @@ public NamedDefinition getLanguageType(MappingContext mappingContext, Type<?> gr
}
return mappedCollectionType;
} else if (graphqlType instanceof NonNullType) {
return getLanguageType(mappingContext, ((NonNullType) graphqlType).getType(), name, parentTypeName, true,
collection);
return getLanguageType(mappingContext, ((NonNullType) graphqlType).getType(), name, parentTypeName,
true, collection, directives);
}
throw new IllegalArgumentException("Unknown type: " + graphqlType);
}
Expand All @@ -262,10 +299,12 @@ public NamedDefinition getLanguageType(MappingContext mappingContext, Type<?> gr
* @param parentTypeName Name of the parent type
* @param mandatory GraphQL type is non-null
* @param collection GraphQL type is collection
* @param directives GraphQL field directives
* @return Corresponding language-specific type (java/scala/kotlin/etc)
*/
public NamedDefinition getLanguageType(MappingContext mappingContext, String graphQLType, String name,
String parentTypeName, boolean mandatory, boolean collection) {
String parentTypeName, boolean mandatory, boolean collection,
List<Directive> directives) {
Map<String, String> customTypesMapping = mappingContext.getCustomTypesMapping();
Set<String> serializeFieldsUsingObjectMapper = mappingContext.getUseObjectMapperForRequestSerialization();
String langTypeName;
Expand Down Expand Up @@ -329,5 +368,4 @@ protected boolean isInterfaceOrUnion(MappingContext mappingContext, String graph
return mappingContext.getInterfacesName().contains(graphQLType) ||
mappingContext.getUnionsNames().contains(graphQLType);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,21 @@ public interface GraphQLCodegenConfiguration {
*/
Set<String> getFieldsToExcludeFromGeneration();

/**
* Fields that require DataFetcherResult.
*
* <p>Values should be defined here in format: TypeName, TypeName.fieldName, @directive
*
*
* <p>E.g.:
* <ul>
* <li>{@code @dataFetcherResult}</li>
* </ul>
*
* @return Set of types and fields that should have DataFetcherResult.
*/
Set<String> getFieldsWithDataFetcherResult();

/**
* Specifies whether return types of generated API interface should be wrapped into <code>java.util.Optional</code>
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ public class MappingConfig implements GraphQLCodegenConfiguration, Combinable<Ma
private Set<String> fieldsWithResolvers = new HashSet<>();
private Set<String> fieldsWithoutResolvers = new HashSet<>();
private Set<String> fieldsToExcludeFromGeneration = new HashSet<>();
private Set<String> fieldsWithDataFetcherResult = new HashSet<>();

// parent interfaces configs:
private String queryResolverParentInterface;
Expand Down Expand Up @@ -195,6 +196,7 @@ public void combine(MappingConfig source) {
parametrizedInputSuffix = getValueOrDefaultToThis(source,
GraphQLCodegenConfiguration::getParametrizedInputSuffix);
fieldsWithResolvers = combineSet(fieldsWithResolvers, source.fieldsWithResolvers);
fieldsWithDataFetcherResult = combineSet(fieldsWithDataFetcherResult, source.fieldsWithDataFetcherResult);
fieldsWithoutResolvers = combineSet(fieldsWithoutResolvers, source.fieldsWithoutResolvers);
fieldsToExcludeFromGeneration = combineSet(fieldsToExcludeFromGeneration, source.fieldsToExcludeFromGeneration);
customTypesMapping = combineMap(customTypesMapping, source.customTypesMapping);
Expand Down Expand Up @@ -622,6 +624,15 @@ public void setFieldsToExcludeFromGeneration(Set<String> fieldsToExcludeFromGene
this.fieldsToExcludeFromGeneration = fieldsToExcludeFromGeneration;
}

@Override
public Set<String> getFieldsWithDataFetcherResult() {
return fieldsWithDataFetcherResult;
}

public void setFieldsWithDataFetcherResult(Set<String> fieldsWithDataFetcherResult) {
this.fieldsWithDataFetcherResult = fieldsWithDataFetcherResult;
}

@Override
public String getQueryResolverParentInterface() {
return queryResolverParentInterface;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,11 @@ public Set<String> getFieldsToExcludeFromGeneration() {
return config.getFieldsToExcludeFromGeneration();
}

@Override
public Set<String> getFieldsWithDataFetcherResult() {
return config.getFieldsWithDataFetcherResult();
}

@Override
public Boolean getGenerateClient() {
return config.getGenerateClient();
Expand Down
Loading