inputType<>() and Type<>() can not be the same
VladislavSumin opened this issue · 5 comments
data class UserDTO(
val id: Long,
val name: String,
)
mutation("users") {
resolver { user: UserDTO ->
println(user)
user
}
}
inputType<UserDTO>()
type<UserDTO>()
when run this configuration i have no error, but query not working, playground show schema infinity loading, inside js console:
buildClientSchema.mjs:256 Uncaught Error: Introspection must provide output type for fields, but received: UserDTO!.
when i use UserDTO only as input or output type so works prerfect
I find bug inside MutableSchemaDefinition:
fun <T : Definition>addType(type: T, target: ArrayList<T>, typeCategory: String){
<....>
if(type.checkEqualName(objects, scalars, unions, enums)){ <--- missed inputObjects here
throw SchemaException("Cannot add $typeCategory type with duplicated name ${type.name}")
}
target.add(type)
}
but i don`t understand why input and output objects can not have same name?
As far as I know, this is a GraphQL limitation. There can't be two types with the same name, and type and input type are two different things.
My workaround for this is to create two classes, anyway in most of the cases the input representation of a type does not have the same properties (eg. the input should have no ID), so this is not a big problem
@VladislavSumin, I don't think you can have the same class for both type and input type.
However, you can use interfaces to the rescue:
interface UserDTO(
val id: Long
val name: String
)
data class UserDTOWhereInput: UserDTO(
override val id: Long,
override val name: String,
)
mutation("users") {
resolver { userInput: UserDTOWhereInput ->
println(userInput)
val user = users.filter { user -> user.id == userInput.id}
println("do something with this $user")
user
}
}
type<UserDTO>()
inputType<UserDTOWhereInput>()
Hope it helps
I try to use this solution:
type<UserDTO>()
inputType<UserDTOWhereInput>{
name = "UserDTOInput"
}
that work perfectly.
Then we only need to correct the name verification to take into account inputObjects
if(type.checkEqualName(objects, scalars, unions, enums)){ <--- missed inputObjects here
Yes, this is a limitation by the GraphQL spec, which can be found here §3.10 Input Objects
The GraphQL Object type (ObjectTypeDefinition) defined above is inappropriate for re‐use here, because Object types can contain fields that define arguments or contain references to interfaces and unions, neither of which is appropriate for use as an input argument. For this reason, input objects have a separate type in the system.
And you will also see this limitation in other implementations/parsers of GraphQL
An example using the IntelliJ GraphQL plugin can be seen here:
If you want to use the same Kotlin Class in both a Type
and Input Type
, then the solution proposed by @VladislavSumin is exactly how you should solve this 👍