major: v4 alpha (#505)

This commit is contained in:
Ryan Brink
2023-09-04 00:22:46 -04:00
committed by GitHub
parent 904cc6816d
commit f2786fec08
54 changed files with 1531 additions and 558 deletions

View File

@ -1,20 +1,51 @@
package io.bkbn.kompendium.json.schema
import io.bkbn.kompendium.json.schema.definition.EnumDefinition
import io.bkbn.kompendium.json.schema.definition.JsonSchema
import io.bkbn.kompendium.json.schema.definition.TypeDefinition
import kotlinx.serialization.SerialName
import kotlinx.serialization.Transient
import kotlin.reflect.KClass
import kotlin.reflect.KProperty1
import kotlin.reflect.KType
import kotlin.reflect.full.findAnnotation
import kotlin.reflect.full.hasAnnotation
import kotlin.reflect.full.memberProperties
import kotlin.reflect.full.primaryConstructor
class KotlinXSchemaConfigurator : SchemaConfigurator {
override fun serializableMemberProperties(clazz: KClass<*>): Collection<KProperty1<out Any, *>> =
clazz.memberProperties
override fun serializableMemberProperties(clazz: KClass<*>): Collection<KProperty1<out Any, *>> {
return clazz.memberProperties
.filterNot { it.hasAnnotation<Transient>() }
.filter { clazz.primaryConstructor?.parameters?.map { it.name }?.contains(it.name) ?: true }
}
override fun serializableName(property: KProperty1<out Any, *>): String =
property.annotations
.filterIsInstance<SerialName>()
.firstOrNull()?.value ?: property.name
override fun sealedTypeEnrichment(
implementationType: KType,
implementationSchema: JsonSchema,
): JsonSchema {
return if (implementationSchema is TypeDefinition && implementationSchema.type == "object") {
implementationSchema.copy(
required = implementationSchema.required?.plus("type"),
properties = implementationSchema.properties?.plus(
mapOf(
"type" to EnumDefinition("string", enum = setOf(determineTypeQualifier(implementationType)))
)
)
)
} else {
implementationSchema
}
}
private fun determineTypeQualifier(type: KType): String {
val nameOverrideAnnotation = (type.classifier as KClass<*>).findAnnotation<SerialName>()
return nameOverrideAnnotation?.value ?: (type.classifier as KClass<*>).qualifiedName!!
}
}

View File

@ -1,17 +1,16 @@
package io.bkbn.kompendium.json.schema
import io.bkbn.kompendium.json.schema.definition.JsonSchema
import kotlin.reflect.KClass
import kotlin.reflect.KProperty1
import kotlin.reflect.full.memberProperties
import kotlin.reflect.KType
interface SchemaConfigurator {
fun serializableMemberProperties(clazz: KClass<*>): Collection<KProperty1<out Any, *>>
fun serializableName(property: KProperty1<out Any, *>): String
open class Default : SchemaConfigurator {
override fun serializableMemberProperties(clazz: KClass<*>): Collection<KProperty1<out Any, *>> =
clazz.memberProperties
override fun serializableName(property: KProperty1<out Any, *>): String = property.name
}
fun sealedTypeEnrichment(
implementationType: KType,
implementationSchema: JsonSchema
): JsonSchema
}

View File

@ -25,15 +25,18 @@ object SealedObjectHandler {
val subclasses = clazz.sealedSubclasses
.map { it.createType(type.arguments) }
.map { t ->
SchemaGenerator.fromTypeToSchema(t, cache, schemaConfigurator, enrichment).let { js ->
if (js is TypeDefinition && js.type == "object") {
val slug = t.getSlug(enrichment)
cache[slug] = js
ReferenceDefinition(t.getReferenceSlug(enrichment))
} else {
js
SchemaGenerator.fromTypeToSchema(t, cache, schemaConfigurator, enrichment)
.let {
schemaConfigurator.sealedTypeEnrichment(t, it)
}.let { js ->
if (js is TypeDefinition && js.type == "object") {
val slug = t.getSlug(enrichment)
cache[slug] = js
ReferenceDefinition(t.getReferenceSlug(enrichment))
} else {
js
}
}
}
}
.toSet()
return AnyOfDefinition(subclasses)

View File

@ -13,7 +13,7 @@ object Helpers {
fun KType.getSlug(enrichment: Enrichment? = null) = when (enrichment) {
is TypeEnrichment<*> -> getEnrichedSlug(enrichment)
is PropertyEnrichment -> error("Slugs should not be generated for field enrichments")
null -> getSimpleSlug()
else -> getSimpleSlug()
}
fun KType.getSimpleSlug(): String = when {
@ -26,7 +26,7 @@ object Helpers {
fun KType.getReferenceSlug(enrichment: Enrichment? = null): String = when (enrichment) {
is TypeEnrichment<*> -> getSimpleReferenceSlug() + "-${enrichment.id}"
is PropertyEnrichment -> error("Reference slugs should never be generated for field enrichments")
null -> getSimpleReferenceSlug()
else -> getSimpleReferenceSlug()
}
private fun KType.getSimpleReferenceSlug() = when {