aPureBase / KGraphQL

Pure Kotlin GraphQL implementation
https://kgraphql.io
MIT License
298 stars 58 forks source link

Allow users to provide custom generic type resolver #195

Closed thevietto closed 1 year ago

thevietto commented 1 year ago

Allow users to add their custom Generic Type Resolver in order to use generic types in schema.

The idea is based on graphql-java implementation: https://javadoc.io/static/com.graphql-java/graphql-java/14.0/graphql/execution/ValueUnboxer.html

example

data class ClassWithOptionalField(val value: Optional<Int>)

val schema = defaultSchema {
    configure {
        genericTypeResolver = object : DefaultGenericTypeResolver() {
            override fun unbox(obj: Any) = when (obj) {
                is Optional<*> -> obj.orElse(null)
                else -> super.unbox(obj)
            }

            override fun resolveMonad(type: KType): KType = when {
                type.jvmErasure.isSubclassOf(Optional::class) ->
                    type.arguments.firstOrNull()?.type?.withNullability(true)
                        ?: throw SchemaException("Could not get the type of the first argument for the type $type")

                else -> super.resolveMonad(type)
            }
        }
    }

    type<ClassWithOptionalField>()
    query("data1") {
        resolver<ClassWithOptionalField> {
            ClassWithOptionalField(Optional.ofNullable(42))
        }
    }
    query("data2") {
        resolver<ClassWithOptionalField> {
            ClassWithOptionalField(Optional.ofNullable(null))
        }
    }
}

assertThat(
    deserialize(schema.executeBlocking("{data1 {value}}")).extract<String>("data/data1/value"),
    equalTo(42)
)
assertThat(
    deserialize(schema.executeBlocking("{data2 {value}}")).extract<String>("data/data2/value"),
    equalTo(null)
)