From 30ac67de11b8dd3e66b67939405f8b35cc71a350 Mon Sep 17 00:00:00 2001 From: Kavitha Srinivasan <41588701+srinivasankavitha@users.noreply.github.com> Date: Tue, 23 Apr 2024 22:07:51 -0700 Subject: [PATCH] Add a __typename method on projections for selection. (#685) * Use concrete types for JsonSubType annotations on interfaces if available. * Add a __typename() method to select on projections. --- .../generators/java/ClientApiGenerator.kt | 29 +++++++++++++++++++ .../clientapi/ClientApiGenFragmentTest.kt | 4 +++ .../clientapi/ClientApiGenProjectionTest.kt | 12 ++++---- .../clientapi/ClientApiGenQueryTest.kt | 6 ++-- 4 files changed, 42 insertions(+), 9 deletions(-) diff --git a/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/java/ClientApiGenerator.kt b/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/java/ClientApiGenerator.kt index 61595cbf0..f42c80b38 100644 --- a/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/java/ClientApiGenerator.kt +++ b/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/java/ClientApiGenerator.kt @@ -256,6 +256,20 @@ class ClientApiGenerator(private val config: CodeGenConfig, private val document .build() ) + val typeVariable = TypeVariableName.get("$clazzName") + javaType.addMethod( + MethodSpec.methodBuilder(TypeNameMetaFieldDef.name) + .returns(typeVariable) + .addCode( + """ + |getFields().put("${TypeNameMetaFieldDef.name}", null); + |return this; + """.trimMargin() + ) + .addModifiers(Modifier.PUBLIC) + .build() + ) + if (generatedClasses.contains(clazzName)) return CodeGenResult() else generatedClasses.add(clazzName) val fieldDefinitions = type.fieldDefinitions() + document.definitions.filterIsInstance().filter { it.name == type.name }.flatMap { it.fieldDefinitions } @@ -534,6 +548,21 @@ class ClientApiGenerator(private val config: CodeGenConfig, private val document .build() ) + // add a method for setting the __typename + val typeVariable = TypeVariableName.get("$clazzName") + javaType.addMethod( + MethodSpec.methodBuilder(TypeNameMetaFieldDef.name) + .returns(typeVariable) + .addCode( + """ + |getFields().put("${TypeNameMetaFieldDef.name}", null); + |return this; + """.trimMargin() + ) + .addModifiers(Modifier.PUBLIC) + .build() + ) + val fieldDefinitions = type.fieldDefinitions() + document.definitions .filterIsInstance() diff --git a/graphql-dgs-codegen-core/src/test/kotlin/com/netflix/graphql/dgs/codegen/clientapi/ClientApiGenFragmentTest.kt b/graphql-dgs-codegen-core/src/test/kotlin/com/netflix/graphql/dgs/codegen/clientapi/ClientApiGenFragmentTest.kt index b4ed2e7b5..e156974c2 100644 --- a/graphql-dgs-codegen-core/src/test/kotlin/com/netflix/graphql/dgs/codegen/clientapi/ClientApiGenFragmentTest.kt +++ b/graphql-dgs-codegen-core/src/test/kotlin/com/netflix/graphql/dgs/codegen/clientapi/ClientApiGenFragmentTest.kt @@ -61,6 +61,7 @@ class ClientApiGenFragmentTest { assertThat(codeGenResult.clientProjections.size).isEqualTo(3) assertThat(codeGenResult.clientProjections[0].typeSpec.name).isEqualTo("SearchProjectionRoot") assertThat(codeGenResult.clientProjections[0].typeSpec.methodSpecs).extracting("name").contains("title") + assertThat(codeGenResult.clientProjections[0].typeSpec.methodSpecs).extracting("name").contains("__typename") assertThat(codeGenResult.clientProjections[1].typeSpec.name).isEqualTo("MovieFragmentProjection") assertThat(codeGenResult.clientProjections[1].typeSpec.methodSpecs).extracting("name").contains("duration") assertThat(codeGenResult.clientProjections[1].typeSpec.methodSpecs).extracting("name").contains("title") @@ -114,8 +115,10 @@ class ClientApiGenFragmentTest { assertThat(codeGenResult.clientProjections.size).isEqualTo(4) assertThat(codeGenResult.clientProjections[0].typeSpec.name).isEqualTo("SearchProjectionRoot") + assertThat(codeGenResult.clientProjections[0].typeSpec.methodSpecs).extracting("name").contains("__typename") assertThat(codeGenResult.clientProjections[1].typeSpec.name).isEqualTo("ShowProjection") assertThat(codeGenResult.clientProjections[1].typeSpec.methodSpecs).extracting("name").contains("title") + assertThat(codeGenResult.clientProjections[1].typeSpec.methodSpecs).extracting("name").contains("__typename") assertThat(codeGenResult.clientProjections[2].typeSpec.name).isEqualTo("MovieFragmentProjection") assertThat(codeGenResult.clientProjections[2].typeSpec.methodSpecs).extracting("name").contains("duration") assertThat(codeGenResult.clientProjections[2].typeSpec.methodSpecs).extracting("name").contains("title") @@ -160,6 +163,7 @@ class ClientApiGenFragmentTest { assertThat(codeGenResult.clientProjections.size).isEqualTo(3) assertThat(codeGenResult.clientProjections[0].typeSpec.name).isEqualTo("SearchProjectionRoot") + assertThat(codeGenResult.clientProjections[0].typeSpec.methodSpecs).extracting("name").contains("__typename") assertThat(codeGenResult.clientProjections[0].typeSpec.methodSpecs).extracting("name").contains("onMovie") assertThat(codeGenResult.clientProjections[0].typeSpec.methodSpecs).extracting("name").contains("onActor") assertThat(codeGenResult.clientProjections[1].typeSpec.name).isEqualTo("MovieFragmentProjection") diff --git a/graphql-dgs-codegen-core/src/test/kotlin/com/netflix/graphql/dgs/codegen/clientapi/ClientApiGenProjectionTest.kt b/graphql-dgs-codegen-core/src/test/kotlin/com/netflix/graphql/dgs/codegen/clientapi/ClientApiGenProjectionTest.kt index 5cedef197..230af8561 100644 --- a/graphql-dgs-codegen-core/src/test/kotlin/com/netflix/graphql/dgs/codegen/clientapi/ClientApiGenProjectionTest.kt +++ b/graphql-dgs-codegen-core/src/test/kotlin/com/netflix/graphql/dgs/codegen/clientapi/ClientApiGenProjectionTest.kt @@ -367,8 +367,8 @@ class ClientApiGenProjectionTest { val projections = codeGenResult.clientProjections assertThat(projections.size).isEqualTo(1) assertThat(projections[0].typeSpec.name).isEqualTo("PeopleProjectionRoot") - assertThat(projections[0].typeSpec.methodSpecs.size).isEqualTo(3) - assertThat(projections[0].typeSpec.methodSpecs).extracting("name").contains("name", "email") + assertThat(projections[0].typeSpec.methodSpecs.size).isEqualTo(4) + assertThat(projections[0].typeSpec.methodSpecs).extracting("name").contains("name", "email", "__typename") assertCompilesJava(codeGenResult) } @@ -404,8 +404,8 @@ class ClientApiGenProjectionTest { val projections = codeGenResult.clientProjections assertThat(projections.size).isEqualTo(2) assertThat(projections[1].typeSpec.name).isEqualTo("MovieProjection") - assertThat(projections[1].typeSpec.methodSpecs.size).isEqualTo(3) - assertThat(projections[1].typeSpec.methodSpecs).extracting("name").contains("title", "director", "") + assertThat(projections[1].typeSpec.methodSpecs.size).isEqualTo(4) + assertThat(projections[1].typeSpec.methodSpecs).extracting("name").contains("title", "director", "", "__typename") assertCompilesJava(codeGenResult) } @@ -441,7 +441,7 @@ class ClientApiGenProjectionTest { val projections = codeGenResult.clientProjections assertThat(projections.size).isEqualTo(2) assertThat(projections[1].typeSpec.name).isEqualTo("MovieProjection") - assertThat(projections[1].typeSpec.methodSpecs.size).isEqualTo(3) + assertThat(projections[1].typeSpec.methodSpecs.size).isEqualTo(4) assertThat(projections[1].typeSpec.methodSpecs).extracting("name").contains("title", "director", "") assertCompilesJava(codeGenResult) @@ -716,7 +716,7 @@ class ClientApiGenProjectionTest { ).generate() val methodSpecs = codeGenResult.clientProjections[0].typeSpec.methodSpecs - assertThat(methodSpecs.size).isEqualTo(3) + assertThat(methodSpecs.size).isEqualTo(4) val methodWithArgs = methodSpecs.find { it.parameters.size > 0 && it.name == "actors" } ?: fail("Expected method not found") assertThat(methodWithArgs.parameters[0].name).isEqualTo("leadCharactersOnly") diff --git a/graphql-dgs-codegen-core/src/test/kotlin/com/netflix/graphql/dgs/codegen/clientapi/ClientApiGenQueryTest.kt b/graphql-dgs-codegen-core/src/test/kotlin/com/netflix/graphql/dgs/codegen/clientapi/ClientApiGenQueryTest.kt index 5edd1cd6f..115a16511 100644 --- a/graphql-dgs-codegen-core/src/test/kotlin/com/netflix/graphql/dgs/codegen/clientapi/ClientApiGenQueryTest.kt +++ b/graphql-dgs-codegen-core/src/test/kotlin/com/netflix/graphql/dgs/codegen/clientapi/ClientApiGenQueryTest.kt @@ -441,11 +441,11 @@ class ClientApiGenQueryTest { assertThat(codeGenResult.javaQueryTypes[0].typeSpec.name).isEqualTo("SearchGraphQLQuery") assertThat(codeGenResult.clientProjections.size).isEqualTo(3) assertThat(codeGenResult.clientProjections[0].typeSpec.name).isEqualTo("SearchProjectionRoot") - assertThat(codeGenResult.clientProjections[0].typeSpec.methodSpecs[1].name).isEqualTo("title") + assertThat(codeGenResult.clientProjections[0].typeSpec.methodSpecs[2].name).isEqualTo("title") assertThat(codeGenResult.clientProjections[1].typeSpec.name).isEqualTo("MovieFragmentProjection") - assertThat(codeGenResult.clientProjections[1].typeSpec.methodSpecs[2].name).isEqualTo("duration") + assertThat(codeGenResult.clientProjections[1].typeSpec.methodSpecs[3].name).isEqualTo("duration") assertThat(codeGenResult.clientProjections[2].typeSpec.name).isEqualTo("SeriesFragmentProjection") - assertThat(codeGenResult.clientProjections[2].typeSpec.methodSpecs[2].name).isEqualTo("episodes") + assertThat(codeGenResult.clientProjections[2].typeSpec.methodSpecs[3].name).isEqualTo("episodes") assertCompilesJava( codeGenResult.clientProjections + codeGenResult.javaQueryTypes + codeGenResult.javaEnumTypes + codeGenResult.javaDataTypes + codeGenResult.javaInterfaces