From 862460e26e8dc6ddf3a4265b51a06b153c21b63b Mon Sep 17 00:00:00 2001 From: Dariusz Kuc <9501705+dariuszkuc@users.noreply.github.com> Date: Wed, 17 Apr 2024 15:26:17 -0500 Subject: [PATCH] feat: ability to specify `@GraphQLName` on input types w/o suffix (#1960) ### :pencil: Description Currently input types are always suffixed with `Input` which is problematic as there are use cases where users might want to provide different custom name. This change adds check whether specified type is input only and if thats the case it does not attempt to add `Input` suffix. ### :link: Related Issues Supersedes https://github.com/ExpediaGroup/graphql-kotlin/pull/1949 --- .../internal/extensions/kClassExtensions.kt | 10 +++++++-- .../extensions/KClassExtensionsTest.kt | 16 +++++++++++++- .../customizing-schemas/renaming-fields.md | 21 +++++++++++++++++++ 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/generator/graphql-kotlin-schema-generator/src/main/kotlin/com/expediagroup/graphql/generator/internal/extensions/kClassExtensions.kt b/generator/graphql-kotlin-schema-generator/src/main/kotlin/com/expediagroup/graphql/generator/internal/extensions/kClassExtensions.kt index e8280831da..122d8c7d72 100644 --- a/generator/graphql-kotlin-schema-generator/src/main/kotlin/com/expediagroup/graphql/generator/internal/extensions/kClassExtensions.kt +++ b/generator/graphql-kotlin-schema-generator/src/main/kotlin/com/expediagroup/graphql/generator/internal/extensions/kClassExtensions.kt @@ -1,5 +1,5 @@ /* - * Copyright 2022 Expedia, Inc + * Copyright 2024 Expedia, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package com.expediagroup.graphql.generator.internal.extensions +import com.expediagroup.graphql.generator.annotations.GraphQLValidObjectLocations import com.expediagroup.graphql.generator.exceptions.CouldNotGetNameOfKClassException import com.expediagroup.graphql.generator.hooks.SchemaGeneratorHooks import com.expediagroup.graphql.generator.internal.filters.functionFilters @@ -28,6 +29,7 @@ import kotlin.reflect.KProperty import kotlin.reflect.KVisibility import kotlin.reflect.full.declaredMemberFunctions import kotlin.reflect.full.declaredMemberProperties +import kotlin.reflect.full.findAnnotation import kotlin.reflect.full.findParameterByName import kotlin.reflect.full.isSubclassOf import kotlin.reflect.full.memberFunctions @@ -84,12 +86,16 @@ internal fun KClass<*>.isListType(isDirective: Boolean = false): Boolean = this. @Throws(CouldNotGetNameOfKClassException::class) internal fun KClass<*>.getSimpleName(isInputClass: Boolean = false): String { + val isInputOnlyLocation = this.findAnnotation().let { + it != null && it.locations.size == 1 && it.locations.contains(GraphQLValidObjectLocations.Locations.INPUT_OBJECT) + } + val name = this.getGraphQLName() ?: this.simpleName ?: throw CouldNotGetNameOfKClassException(this) return when { - isInputClass -> if (name.endsWith(INPUT_SUFFIX, true)) name else "$name$INPUT_SUFFIX" + isInputClass -> if (name.endsWith(INPUT_SUFFIX, true) || isInputOnlyLocation) name else "$name$INPUT_SUFFIX" else -> name } } diff --git a/generator/graphql-kotlin-schema-generator/src/test/kotlin/com/expediagroup/graphql/generator/internal/extensions/KClassExtensionsTest.kt b/generator/graphql-kotlin-schema-generator/src/test/kotlin/com/expediagroup/graphql/generator/internal/extensions/KClassExtensionsTest.kt index d1b70be74c..64593acc73 100644 --- a/generator/graphql-kotlin-schema-generator/src/test/kotlin/com/expediagroup/graphql/generator/internal/extensions/KClassExtensionsTest.kt +++ b/generator/graphql-kotlin-schema-generator/src/test/kotlin/com/expediagroup/graphql/generator/internal/extensions/KClassExtensionsTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2022 Expedia, Inc + * Copyright 2024 Expedia, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,6 +19,7 @@ package com.expediagroup.graphql.generator.internal.extensions import com.expediagroup.graphql.generator.annotations.GraphQLIgnore import com.expediagroup.graphql.generator.annotations.GraphQLName import com.expediagroup.graphql.generator.annotations.GraphQLUnion +import com.expediagroup.graphql.generator.annotations.GraphQLValidObjectLocations import com.expediagroup.graphql.generator.exceptions.CouldNotGetNameOfKClassException import com.expediagroup.graphql.generator.hooks.NoopSchemaGeneratorHooks import com.expediagroup.graphql.generator.hooks.SchemaGeneratorHooks @@ -77,6 +78,13 @@ open class KClassExtensionsTest { @GraphQLName("MyClassRenamedInput") class MyClassCustomNameInput + @GraphQLValidObjectLocations([GraphQLValidObjectLocations.Locations.INPUT_OBJECT]) + class MyInputClassWithoutSuffix + + @GraphQLValidObjectLocations([GraphQLValidObjectLocations.Locations.INPUT_OBJECT]) + @GraphQLName("MyClass") + class MyInputClassWithoutSuffixUsingCustomName + protected class MyProtectedClass class MyPublicClass @@ -378,4 +386,10 @@ open class KClassExtensionsTest { assertFalse(IgnoredClass::class.isValidAdditionalType(true)) assertFalse(IgnoredClass::class.isValidAdditionalType(false)) } + + @Test + fun `@GraphQLName does not apply input suffix on input only classes`() { + assertEquals("MyInputClassWithoutSuffix", MyInputClassWithoutSuffix::class.getSimpleName(isInputClass = true)) + assertEquals("MyClass", MyInputClassWithoutSuffixUsingCustomName::class.getSimpleName(isInputClass = true)) + } } diff --git a/website/docs/schema-generator/customizing-schemas/renaming-fields.md b/website/docs/schema-generator/customizing-schemas/renaming-fields.md index 2a1e1c5309..1fa2b9cf36 100644 --- a/website/docs/schema-generator/customizing-schemas/renaming-fields.md +++ b/website/docs/schema-generator/customizing-schemas/renaming-fields.md @@ -20,6 +20,27 @@ type MyCustomName { } ``` +:::info +By default, in order to differentiate between input and output types, all input type names are auto generated with additional +`Input` suffix. Suffix is appended only if input type name does not already end with `Input`. If you would like to change this +behavior and avoid extra suffix, you need to explicitly specify that this is an input only type. + +```kotlin +// GraphQL input object type name: MyInputType +@GraphQLValidObjectLocations([GraphQLValidObjectLocations.Locations.INPUT_OBJECT]) +data class MyInputType(val id: ID) +``` + +You can also rename input types + +```kotlin +// GraphQL input object type name: MyCustomInputType +@GraphQLValidObjectLocations([GraphQLValidObjectLocations.Locations.INPUT_OBJECT]) +@GraphQLName("MyCustomInputType") +data class MyInputType(val id: ID) +``` +::: + ## Known Issues Due to how we deserialize input classes, if you rename a field of an input class or an enum value you must also annotate