dgs-codegen
dgs-codegen copied to clipboard
feat(#389): allow templating for generated Java / Kotlin class names
Adds an optional nameTemplate
input parameter to the plugin, allowing customization of the generated Java / Kotlin class names.
The following template variables are supported:
- name - the original name of the class
- schemaType - the GraphQL schema type (Type, Input, Interface, Enum)
The default value for this new property is null. In this case the output will be identical to the current one.
Examples:
Given an original class name Person
and schema type Type
:
- null -> Person
- "{name}GraphQL{schemaType}" -> PersonGraphQLType
- "{name}GraphQL" -> PersonGraphQL
- "{name}{schemaType}" -> PersonType
Hi @BlasiusSecundus! Thank you for opening this PR, I am actively looking into this. In the meantime, could you please resolve the conflicts?
I have resolved conflicts. However, when running the tests locally I saw KotlinCodeGenTest
failing with errors like this one:
error: unresolved reference: fasterxml
import com.fasterxml.jackson.`annotation`.JsonProperty
^
error: cannot access built-in declaration 'kotlin.String'. Ensure that you have a dependency on the Kotlin standard library
import kotlin.String
I have not noticed this before, and this also happens on master branch, so I think this should not be related to my PR.
@BlasiusSecundus Hello, thank you for your work on this PR. We find it to be incredibly valuable for our use case.
Regarding the KotlinCodeGenTest
failure you mentioned, I've checked out the latest master branch and it seems that the issue may have been resolved there.
I rebased and resolved the conflicts. The aforementioned error still occurs on my machine (asl on master), but the CI build job ran successfully (on my forked repo at least). So maybe this is something related to my local setup only, I'll check.
@BlasiusSecundus Thank you for taking the time to rebase and resolve the conflicts. It's good to hear that the CI build job ran successfully on your forked repo.
@congotej I noticed your previous comment about actively looking into this PR. Could I kindly ask for an update on the current status of this PR? We're really looking forward to benefiting from this feature. Thank you!
Btw. This PR should also address issue https://github.com/Netflix/dgs-codegen/issues/323
@srinivasankavitha @congotej don't mean to rush you but can you please review this? If there's any changes expected, please let us know. We've been eagerly waiting for this one.
Hi - apologies for the delayed responses on this PR. Could you please elaborate on how this feature would be useful for the projects you are working with? Is it more to address code readability when working with generated types? The plugin itself is designed to do a few things well, and imo, over time we've added way too many customizations already that are making this hard to maintain and ensure correctness. I'm hesitant to add more feature flags unless they really make it worth the maintenance cost.
Could you please elaborate on how this feature would be useful for the projects you are working with?
For example, you have a Person
class in the domain layer, and a Person
class in the (generated) API layer. Without such a feature, a naming conflict would result either in hard-to-read code (e.g. using fully qualified names), or would require manual workarounds (such as using imports alias or typealias
in Kotlin) - neither results in an optimal developer experience.
Is it more to address code readability when working with generated types?
Essentially yes, It makes the code much easier to read. (Is that Person
from the domain layer or the API layer? - a prefix/suffix communicates that immediately)
I'm hesitant to add more feature flags unless they really make it worth the maintenance cost.
This feature is meant to be an equivalent of OpenAPI Generator's modelNamePrefix
/ modelNameSuffix
settings. I think this feature would be used widely enough to justify the maintenance costs - which should not be that huge considering this is a quite simple feature.
The plugin itself is designed to do a few things well, and imo, over time we've added way too many customizations already that are making this hard to maintain and ensure correctness. I'm hesitant to add more feature flags unless they really make it worth the maintenance cost.
I agree with your point about there being too many customizations. However, lack of this feature causes too much confusion and conflicts, as @BlasiusSecundus pointed out above. We resorted to adding manual prefixes to our graphql types to overcome the conflicts but that has led to much more confusion and chaos on the consumer side as this made our types from one particular repo out-of-sync with the naming convention that the rest of our types follow. This is especially painful given that some of these types are exposed to the rest of the world (via a graphql api for devs). Hope this feature will be available soon.
@srinivasankavitha @congotej what do you think?
@paulbakker and I discussed this and we will merge this after some testing on our end. Thanks for the PR contribution!
This Feature will be of great help to avoid conflicts and readability, waiting for this one!!!!!
I agree with @SankarshanDudhate ! We are following Person
class and PersonType
for graphql to avoid conflicts. This would standardize the codegen. However, would love to see the possibility of having Person
domain class and Person
type in graphql with no conflicts.
I tested this with a random test schema, and get some compilation issues because the naming isn't applied everywhere, it looks like.
Example schema:
type Query {
lolomo: [ShowCategory]
search(searchFilter: SearchFilter!): [Show]
}
input SearchFilter {
title: String!
}
type ShowCategory {
id: Int
name: String
shows: [Show]
}
interface Show @key(fields: "showId"){
showId: Int
title: String
artworkUrl: String
}
type Movie implements Show{
showId: Int
title: String
artworkUrl: String
director: String
}
type Series implements Show {
showId: Int
title: String
artworkUrl: String
episodes: Int
}
E.g. this generates
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "__typename"
)
@JsonSubTypes({
@JsonSubTypes.Type(value = Movie.class, name = "Movie"),
@JsonSubTypes.Type(value = Series.class, name = "Series")
})
public interface DgsInterfaceShowGenerated {
Naming I configured: nameTemplate = 'Dgs{schemaType}{name}Generated'
@BlasiusSecundus can you look into this?
@paulbakker Thank you for the review and testing! Ill fix the issue of course and will add a test case for this scenario.
At first glance the problem seems to be that for the Movie
type it generated DgsTypeMovieGenerated
(which is correct), but in the Jackson annotations they were referenced using their untemplated names (which obviously resulted in compilation errors).