Skip to content

Add support for generated @deprecated arguments from @GraphQLDeprecated #2075

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package com.expediagroup.graphql.generator.internal.types

import com.expediagroup.graphql.generator.SchemaGenerator
import com.expediagroup.graphql.generator.exceptions.InvalidInputFieldTypeException
import com.expediagroup.graphql.generator.internal.extensions.getDeprecationReason
import com.expediagroup.graphql.generator.internal.extensions.getGraphQLDescription
import com.expediagroup.graphql.generator.internal.extensions.getKClass
import com.expediagroup.graphql.generator.internal.extensions.getName
Expand Down Expand Up @@ -50,12 +51,15 @@ internal fun generateArgument(generator: SchemaGenerator, parameter: KParameter)
val typeInfo = GraphQLKTypeMetadata(inputType = true, fieldName = parameter.getName(), fieldAnnotations = parameter.annotations)
val graphQLType = generateGraphQLType(generator = generator, type = unwrappedType, typeInfo)

// Deprecation of arguments is currently unsupported: https://youtrack.jetbrains.com/issue/KT-25643
val builder = GraphQLArgument.newArgument()
.name(parameter.getName())
.description(parameter.getGraphQLDescription())
.type(graphQLType.safeCast())

parameter.getDeprecationReason()?.let {
builder.deprecate(it)
}

generateDirectives(generator, parameter, DirectiveLocation.ARGUMENT_DEFINITION).forEach {
builder.withAppliedDirective(it)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import graphql.schema.GraphQLNonNull
import graphql.schema.GraphQLObjectType
import org.junit.jupiter.api.Test
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertNotNull
import kotlin.test.assertTrue

Expand Down Expand Up @@ -74,6 +75,18 @@ class DirectiveTests {
assertEquals("this query is also deprecated", graphqlDeprecatedQuery.deprecationReason)
}

@Test
fun `SchemaGenerator marks deprecated fields within queries`() {
val schema = toSchema(queries = listOf(TopLevelObject(QueryWithDeprecatedFields())), config = testSchemaConfig())
val topLevelQuery = schema.getObjectType("Query")
val query = topLevelQuery.getFieldDefinition("graphqlQueryWithDeprecatedFields")

assertFalse(query.isDeprecated)
val deprecatedArgument = query.getArgument("something")
assertTrue(deprecatedArgument.isDeprecated)
assertEquals("This field is deprecated", deprecatedArgument.deprecationReason)
}

@Test
fun `Default directive names are normalized`() {
val wiring = object : KotlinSchemaDirectiveWiring {}
Expand Down Expand Up @@ -155,6 +168,8 @@ class QueryWithDeprecatedFields {

@Deprecated("this query is also deprecated", replaceWith = ReplaceWith("shinyNewQuery"))
fun graphqlDeprecatedQueryWithReplacement(something: String) = something

fun graphqlQueryWithDeprecatedFields(@GraphQLDeprecated("This field is deprecated") something: String, replacement: String) = "$something -> $replacement"
}

data class ClassWithDeprecatedField(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.expediagroup.graphql.generator.internal.types

import com.expediagroup.graphql.generator.annotations.GraphQLDeprecated
import com.expediagroup.graphql.generator.annotations.GraphQLDescription
import com.expediagroup.graphql.generator.annotations.GraphQLName
import com.expediagroup.graphql.generator.exceptions.InvalidInputFieldTypeException
Expand All @@ -33,6 +34,7 @@ import kotlin.reflect.full.findParameterByName
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
import kotlin.test.assertNotNull
import kotlin.test.assertTrue

class GenerateArgumentTest : TypeTestHelper() {

Expand All @@ -51,6 +53,8 @@ class GenerateArgumentTest : TypeTestHelper() {

fun changeName(@GraphQLName("newName") input: String) = input

fun deprecate(@GraphQLDeprecated("Deprecated") input: String, replacement: String) = "$input -> $replacement"

fun idClass(idArg: ID) = "Your id is $idArg"

fun interfaceArg(input: MyInterface) = input.id
Expand Down Expand Up @@ -108,6 +112,16 @@ class GenerateArgumentTest : TypeTestHelper() {
assertEquals("newName", result.name)
}

@Test
fun `Argument can be deprecated with @GraphqlDeprecated`() {
val kParameter = ArgumentTestClass::deprecate.findParameterByName("input")
assertNotNull(kParameter)
val result = generateArgument(generator, kParameter)

assertTrue(result.isDeprecated, "The argument should be marked as deprecated")
assertEquals("Deprecated", result.deprecationReason, "The deprecation reason should match")
}

@Test
fun `Wrapper ID class argument type is valid`() {
val kParameter = ArgumentTestClass::idClass.findParameterByName("idArg")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,23 @@ type Query {

A side-effect of using `@Deprecated` is that it marks your own Kotlin code as being deprecated, which may not be what you want. Using `@GraphQLDeprecated` you can add the `@deprecated` directive to the GraphQL schema, but not have your Kotlin code show up as deprecated in your editor.

### Deprecating Fields
```kotlin
class SimpleQuery {
@GraphQLDeprecated(message = "this query is deprecated", replaceWith = ReplaceWith("shinyNewQuery"))
fun simpleDeprecatedQuery(): Boolean = false

fun shinyNewQuery(): Boolean = true
}
```

### Deprecating Arguments
You can also use `@GraphQLDeprecated` to deprecate individual arguments in your GraphQL schema. This allows you to notify clients that a specific argument is deprecated and optionally provide them with guidance on replacement arguments.

```kotlin
class QueryWithDeprecatedArgument {
fun exampleQuery(@GraphQLDeprecated(message = "Use 'newArg' instead") oldArg: String?, newArg: String): String {
return "Received: ${newArg}"
}
}
```
Loading