From d66dcdf08d9eb4403970e29a7df6b19859bbacd9 Mon Sep 17 00:00:00 2001 From: Calvin Cestari <146856+calvincestari@users.noreply.github.com> Date: Mon, 26 May 2025 16:26:51 -0700 Subject: [PATCH 01/17] Refactor HTTP body composers --- .../api/http/DefaultHttpRequestComposer.kt | 61 ++++++++++++++----- 1 file changed, 47 insertions(+), 14 deletions(-) diff --git a/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo/api/http/DefaultHttpRequestComposer.kt b/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo/api/http/DefaultHttpRequestComposer.kt index fc8be331639..8f3943f64cc 100644 --- a/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo/api/http/DefaultHttpRequestComposer.kt +++ b/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo/api/http/DefaultHttpRequestComposer.kt @@ -50,19 +50,20 @@ class DefaultHttpRequestComposer( } val sendApqExtensions = apolloRequest.sendApqExtensions ?: false + val sendEnhancedClientAwarenessExtensions = true val sendDocument = apolloRequest.sendDocument ?: true val httpRequestBuilder = when (apolloRequest.httpMethod ?: HttpMethod.Post) { HttpMethod.Get -> { HttpRequest.Builder( method = HttpMethod.Get, - url = buildGetUrl(serverUrl, operation, customScalarAdapters, sendApqExtensions, sendDocument), + url = buildGetUrl(serverUrl, operation, customScalarAdapters, sendApqExtensions, sendDocument, sendEnhancedClientAwarenessExtensions), ).addHeader(HEADER_APOLLO_REQUIRE_PREFLIGHT, "true") } HttpMethod.Post -> { val query = if (sendDocument) operation.document() else null - val body = buildPostBody(operation, customScalarAdapters, query, apqExtensionsWriter(operation.id(), sendApqExtensions)) + val body = buildPostBody(operation, customScalarAdapters, query, extensionsWriter(operation.id(), sendApqExtensions, sendEnhancedClientAwarenessExtensions)) HttpRequest.Builder( method = HttpMethod.Post, url = serverUrl, @@ -106,9 +107,10 @@ class DefaultHttpRequestComposer( customScalarAdapters: CustomScalarAdapters, sendApqExtensions: Boolean, sendDocument: Boolean, + sendEnhancedClientAwarenessExtensions: Boolean, ): String { return serverUrl.appendQueryParameters( - composeGetParams(operation, customScalarAdapters, sendApqExtensions, sendDocument) + composeGetParams(operation, customScalarAdapters, sendApqExtensions, sendDocument, sendEnhancedClientAwarenessExtensions) ) } @@ -147,22 +149,33 @@ class DefaultHttpRequestComposer( operation: Operation, customScalarAdapters: CustomScalarAdapters, sendApqExtensions: Boolean, + sendEnhancedClientAwarenessExtensions: Boolean, query: String?, ): Map { return composePostParams( - writer, operation, customScalarAdapters, query, apqExtensionsWriter(operation.id(), sendApqExtensions) + writer, operation, customScalarAdapters, query, extensionsWriter(operation.id(), sendApqExtensions, sendEnhancedClientAwarenessExtensions) ) } - private fun apqExtensionsWriter(id: String, sendApqExtensions: Boolean): JsonWriter.() -> Unit { + private fun extensionsWriter(apqId: String, sendApqExtensions: Boolean, sendEnhancedClientAwarenessExtensions: Boolean): JsonWriter.() -> Unit { + if (!sendApqExtensions && !sendEnhancedClientAwarenessExtensions) return { } + return { - if (sendApqExtensions) { - name("extensions") - writeObject { + name("extensions") + writeObject { + if (sendApqExtensions) { name("persistedQuery") writeObject { name("version").value(1) - name("sha256Hash").value(id) + name("sha256Hash").value(apqId) + } + } + + if (sendEnhancedClientAwarenessExtensions) { + name("clientLibrary") + writeObject { + name("name").value("apollo-kotlin") + name("version").value(0) } } } @@ -179,6 +192,7 @@ class DefaultHttpRequestComposer( customScalarAdapters: CustomScalarAdapters, autoPersistQueries: Boolean, sendDocument: Boolean, + sendEnhancedClientAwareness: Boolean, ): Map { val queryParams = mutableMapOf() @@ -200,8 +214,8 @@ class DefaultHttpRequestComposer( queryParams.put("query", operation.document()) } - if (autoPersistQueries) { - val extensions = buildJsonString { + val extensions = buildJsonString { + if (autoPersistQueries) { writeObject { name("persistedQuery") writeObject { @@ -210,8 +224,24 @@ class DefaultHttpRequestComposer( } } } + + if (sendEnhancedClientAwareness) { + val extensions = buildJsonString { + writeObject { + name("clientLibrary") + writeObject { + name("name").value("apollo-kotlin") + name("version").value(0) + } + } + } + } + } + + if (!extensions.isEmpty()) { queryParams.put("extensions", extensions) } + return queryParams } @@ -241,9 +271,10 @@ class DefaultHttpRequestComposer( operation: Operation, customScalarAdapters: CustomScalarAdapters, autoPersistQueries: Boolean, + sendEnhancedClientAwarenessExtensions: Boolean, query: String?, ): HttpBody { - return buildPostBody(operation, customScalarAdapters, query, apqExtensionsWriter(operation.id(), autoPersistQueries)) + return buildPostBody(operation, customScalarAdapters, query, extensionsWriter(operation.id(), autoPersistQueries, sendEnhancedClientAwarenessExtensions)) } fun buildPostBody( @@ -283,10 +314,11 @@ class DefaultHttpRequestComposer( customScalarAdapters: CustomScalarAdapters, autoPersistQueries: Boolean, sendDocument: Boolean, + sendEnhancedClientAwarenessExtensions: Boolean, ): ByteString { return buildJsonByteString { val query = if (sendDocument) operation.document() else null - composePostParams(this, operation, customScalarAdapters, autoPersistQueries, query) + composePostParams(this, operation, customScalarAdapters, autoPersistQueries, sendEnhancedClientAwarenessExtensions, query) } } @@ -296,12 +328,13 @@ class DefaultHttpRequestComposer( ): Map { val operation = apolloRequest.operation val sendApqExtensions = apolloRequest.sendApqExtensions ?: false + val sendEnhancedClientAwarenessExtensions = true val sendDocument = apolloRequest.sendDocument ?: true val customScalarAdapters = apolloRequest.executionContext[CustomScalarAdapters] ?: CustomScalarAdapters.Empty val query = if (sendDocument) operation.document() else null return buildJsonMap { - composePostParams(this, operation, customScalarAdapters, sendApqExtensions, query) + composePostParams(this, operation, customScalarAdapters, sendApqExtensions, sendEnhancedClientAwarenessExtensions, query) } as Map } } From 1b7d9c495651a683a42905d9f8499d89104ae7d9 Mon Sep 17 00:00:00 2001 From: Calvin Cestari <146856+calvincestari@users.noreply.github.com> Date: Mon, 2 Jun 2025 14:31:29 -0700 Subject: [PATCH 02/17] Remove duplicate `extensions` declaration --- .../apollo/api/http/DefaultHttpRequestComposer.kt | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo/api/http/DefaultHttpRequestComposer.kt b/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo/api/http/DefaultHttpRequestComposer.kt index 8f3943f64cc..9cf5a296d51 100644 --- a/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo/api/http/DefaultHttpRequestComposer.kt +++ b/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo/api/http/DefaultHttpRequestComposer.kt @@ -226,13 +226,11 @@ class DefaultHttpRequestComposer( } if (sendEnhancedClientAwareness) { - val extensions = buildJsonString { + writeObject { + name("clientLibrary") writeObject { - name("clientLibrary") - writeObject { - name("name").value("apollo-kotlin") - name("version").value(0) - } + name("name").value("apollo-kotlin") + name("version").value(0) } } } From f4fc35dda5068ff68c8adb6242629c131f1455fb Mon Sep 17 00:00:00 2001 From: Calvin Cestari <146856+calvincestari@users.noreply.github.com> Date: Mon, 2 Jun 2025 14:35:10 -0700 Subject: [PATCH 03/17] Reformat file --- .../apollo/api/http/DefaultHttpRequestComposer.kt | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo/api/http/DefaultHttpRequestComposer.kt b/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo/api/http/DefaultHttpRequestComposer.kt index 9cf5a296d51..295c7e89d08 100644 --- a/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo/api/http/DefaultHttpRequestComposer.kt +++ b/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo/api/http/DefaultHttpRequestComposer.kt @@ -63,7 +63,8 @@ class DefaultHttpRequestComposer( HttpMethod.Post -> { val query = if (sendDocument) operation.document() else null - val body = buildPostBody(operation, customScalarAdapters, query, extensionsWriter(operation.id(), sendApqExtensions, sendEnhancedClientAwarenessExtensions)) + val body = + buildPostBody(operation, customScalarAdapters, query, extensionsWriter(operation.id(), sendApqExtensions, sendEnhancedClientAwarenessExtensions)) HttpRequest.Builder( method = HttpMethod.Post, url = serverUrl, @@ -157,7 +158,11 @@ class DefaultHttpRequestComposer( ) } - private fun extensionsWriter(apqId: String, sendApqExtensions: Boolean, sendEnhancedClientAwarenessExtensions: Boolean): JsonWriter.() -> Unit { + private fun extensionsWriter( + apqId: String, + sendApqExtensions: Boolean, + sendEnhancedClientAwarenessExtensions: Boolean, + ): JsonWriter.() -> Unit { if (!sendApqExtensions && !sendEnhancedClientAwarenessExtensions) return { } return { From dbde14a295a579b16c9fcc136871d0dd3537414e Mon Sep 17 00:00:00 2001 From: Calvin Cestari <146856+calvincestari@users.noreply.github.com> Date: Mon, 2 Jun 2025 16:39:55 -0700 Subject: [PATCH 04/17] Use version constant --- .../apollographql/apollo/api/http/DefaultHttpRequestComposer.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo/api/http/DefaultHttpRequestComposer.kt b/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo/api/http/DefaultHttpRequestComposer.kt index 295c7e89d08..ff70d1fcfb3 100644 --- a/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo/api/http/DefaultHttpRequestComposer.kt +++ b/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo/api/http/DefaultHttpRequestComposer.kt @@ -180,7 +180,7 @@ class DefaultHttpRequestComposer( name("clientLibrary") writeObject { name("name").value("apollo-kotlin") - name("version").value(0) + name("version").value(com.apollographql.apollo.api.apolloApiVersion) } } } From b6a81c7a393b9d1d0b83c74f14380396e5aaad99 Mon Sep 17 00:00:00 2001 From: Calvin Cestari <146856+calvincestari@users.noreply.github.com> Date: Mon, 2 Jun 2025 17:16:56 -0700 Subject: [PATCH 05/17] Add deprecated function --- .../apollo/api/http/DefaultHttpRequestComposer.kt | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo/api/http/DefaultHttpRequestComposer.kt b/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo/api/http/DefaultHttpRequestComposer.kt index ff70d1fcfb3..7423fadcbff 100644 --- a/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo/api/http/DefaultHttpRequestComposer.kt +++ b/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo/api/http/DefaultHttpRequestComposer.kt @@ -312,6 +312,19 @@ class DefaultHttpRequestComposer( } } + @Deprecated("Use new function with additional parameters instead.", ReplaceWith("buildParamsMap(operation = operation, customScalarAdapters = customScalarAdapters, autoPersistQueries = autoPersistQueries, sendDocument = sendDocument, sendEnhancedClientAwarenessExtensions = true)")) + fun buildParamsMap( + operation: Operation, + customScalarAdapters: CustomScalarAdapters, + autoPersistQueries: Boolean, + sendDocument: Boolean, + ): ByteString { + return buildJsonByteString { + val query = if (sendDocument) operation.document() else null + composePostParams(this, operation, customScalarAdapters, autoPersistQueries, true, query) + } + } + fun buildParamsMap( operation: Operation, customScalarAdapters: CustomScalarAdapters, From 59c9786f0f9bd9d1d3e8ac8ca0327d1767d0c2e7 Mon Sep 17 00:00:00 2001 From: Calvin Cestari <146856+calvincestari@users.noreply.github.com> Date: Mon, 2 Jun 2025 17:27:05 -0700 Subject: [PATCH 06/17] Update API signature files --- libraries/apollo-api/api/apollo-api.api | 3 ++- libraries/apollo-api/api/apollo-api.klib.api | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/libraries/apollo-api/api/apollo-api.api b/libraries/apollo-api/api/apollo-api.api index 876dd68907a..26e5fbe8446 100644 --- a/libraries/apollo-api/api/apollo-api.api +++ b/libraries/apollo-api/api/apollo-api.api @@ -928,8 +928,9 @@ public final class com/apollographql/apollo/api/http/DefaultHttpRequestComposer public final class com/apollographql/apollo/api/http/DefaultHttpRequestComposer$Companion { public final fun appendQueryParameters (Ljava/lang/String;Ljava/util/Map;)Ljava/lang/String; public final fun buildParamsMap (Lcom/apollographql/apollo/api/Operation;Lcom/apollographql/apollo/api/CustomScalarAdapters;ZZ)Lokio/ByteString; + public final fun buildParamsMap (Lcom/apollographql/apollo/api/Operation;Lcom/apollographql/apollo/api/CustomScalarAdapters;ZZZ)Lokio/ByteString; public final fun buildPostBody (Lcom/apollographql/apollo/api/Operation;Lcom/apollographql/apollo/api/CustomScalarAdapters;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)Lcom/apollographql/apollo/api/http/HttpBody; - public final fun buildPostBody (Lcom/apollographql/apollo/api/Operation;Lcom/apollographql/apollo/api/CustomScalarAdapters;ZLjava/lang/String;)Lcom/apollographql/apollo/api/http/HttpBody; + public final fun buildPostBody (Lcom/apollographql/apollo/api/Operation;Lcom/apollographql/apollo/api/CustomScalarAdapters;ZZLjava/lang/String;)Lcom/apollographql/apollo/api/http/HttpBody; public final fun composePayload (Lcom/apollographql/apollo/api/ApolloRequest;)Ljava/util/Map; public final fun getHEADER_ACCEPT_NAME ()Ljava/lang/String; public final fun getHEADER_ACCEPT_VALUE_DEFER ()Ljava/lang/String; diff --git a/libraries/apollo-api/api/apollo-api.klib.api b/libraries/apollo-api/api/apollo-api.klib.api index 65d009682d3..178cc062161 100644 --- a/libraries/apollo-api/api/apollo-api.klib.api +++ b/libraries/apollo-api/api/apollo-api.klib.api @@ -501,7 +501,8 @@ final class com.apollographql.apollo.api.http/DefaultHttpRequestComposer : com.a final fun (kotlin/String).appendQueryParameters(kotlin.collections/Map): kotlin/String // com.apollographql.apollo.api.http/DefaultHttpRequestComposer.Companion.appendQueryParameters|appendQueryParameters@kotlin.String(kotlin.collections.Map){}[0] final fun <#A2: com.apollographql.apollo.api/Operation.Data> buildParamsMap(com.apollographql.apollo.api/Operation<#A2>, com.apollographql.apollo.api/CustomScalarAdapters, kotlin/Boolean, kotlin/Boolean): okio/ByteString // com.apollographql.apollo.api.http/DefaultHttpRequestComposer.Companion.buildParamsMap|buildParamsMap(com.apollographql.apollo.api.Operation<0:0>;com.apollographql.apollo.api.CustomScalarAdapters;kotlin.Boolean;kotlin.Boolean){0§}[0] - final fun <#A2: com.apollographql.apollo.api/Operation.Data> buildPostBody(com.apollographql.apollo.api/Operation<#A2>, com.apollographql.apollo.api/CustomScalarAdapters, kotlin/Boolean, kotlin/String?): com.apollographql.apollo.api.http/HttpBody // com.apollographql.apollo.api.http/DefaultHttpRequestComposer.Companion.buildPostBody|buildPostBody(com.apollographql.apollo.api.Operation<0:0>;com.apollographql.apollo.api.CustomScalarAdapters;kotlin.Boolean;kotlin.String?){0§}[0] + final fun <#A2: com.apollographql.apollo.api/Operation.Data> buildParamsMap(com.apollographql.apollo.api/Operation<#A2>, com.apollographql.apollo.api/CustomScalarAdapters, kotlin/Boolean, kotlin/Boolean, kotlin/Boolean): okio/ByteString // com.apollographql.apollo.api.http/DefaultHttpRequestComposer.Companion.buildParamsMap|buildParamsMap(com.apollographql.apollo.api.Operation<0:0>;com.apollographql.apollo.api.CustomScalarAdapters;kotlin.Boolean;kotlin.Boolean;kotlin.Boolean){0§}[0] + final fun <#A2: com.apollographql.apollo.api/Operation.Data> buildPostBody(com.apollographql.apollo.api/Operation<#A2>, com.apollographql.apollo.api/CustomScalarAdapters, kotlin/Boolean, kotlin/Boolean, kotlin/String?): com.apollographql.apollo.api.http/HttpBody // com.apollographql.apollo.api.http/DefaultHttpRequestComposer.Companion.buildPostBody|buildPostBody(com.apollographql.apollo.api.Operation<0:0>;com.apollographql.apollo.api.CustomScalarAdapters;kotlin.Boolean;kotlin.Boolean;kotlin.String?){0§}[0] final fun <#A2: com.apollographql.apollo.api/Operation.Data> buildPostBody(com.apollographql.apollo.api/Operation<#A2>, com.apollographql.apollo.api/CustomScalarAdapters, kotlin/String?, kotlin/Function1): com.apollographql.apollo.api.http/HttpBody // com.apollographql.apollo.api.http/DefaultHttpRequestComposer.Companion.buildPostBody|buildPostBody(com.apollographql.apollo.api.Operation<0:0>;com.apollographql.apollo.api.CustomScalarAdapters;kotlin.String?;kotlin.Function1){0§}[0] final fun <#A2: com.apollographql.apollo.api/Operation.Data> composePayload(com.apollographql.apollo.api/ApolloRequest<#A2>): kotlin.collections/Map // com.apollographql.apollo.api.http/DefaultHttpRequestComposer.Companion.composePayload|composePayload(com.apollographql.apollo.api.ApolloRequest<0:0>){0§}[0] } From 6a77434ae3b05cf79a3c05bb64993b2ba358c201 Mon Sep 17 00:00:00 2001 From: Calvin Cestari <146856+calvincestari@users.noreply.github.com> Date: Thu, 5 Jun 2025 12:42:33 -0700 Subject: [PATCH 07/17] Adds property to client and request --- .../com/apollographql/apollo/api/ApolloRequest.kt | 11 ++++++++++- .../com/apollographql/apollo/ApolloClient.kt | 14 ++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo/api/ApolloRequest.kt b/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo/api/ApolloRequest.kt index df3c274f73d..156c496299d 100644 --- a/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo/api/ApolloRequest.kt +++ b/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo/api/ApolloRequest.kt @@ -40,6 +40,7 @@ private constructor( val retryOnError: Boolean?, @ApolloExperimental val failFastIfOffline: Boolean?, + val sendEnhancedClientAwareness: Boolean, ) : ExecutionOptions { fun newBuilder(): Builder = newBuilder(operation) @@ -59,6 +60,7 @@ private constructor( .failFastIfOffline(failFastIfOffline) .ignoreApolloClientHttpHeaders(ignoreApolloClientHttpHeaders) .ignoreUnknownKeys(ignoreUnknownKeys) + .sendEnhancedClientAwareness(sendEnhancedClientAwareness) } class Builder( @@ -90,6 +92,8 @@ private constructor( @ApolloExperimental var failFastIfOffline: Boolean? = null private set + var sendEnhancedClientAwareness: Boolean = true + private set fun requestUuid(requestUuid: Uuid) = apply { @@ -150,6 +154,10 @@ private constructor( this.failFastIfOffline = failFastIfOffline } + fun sendEnhancedClientAwareness(sendEnhancedClientAwareness: Boolean): Builder = apply { + this.sendEnhancedClientAwareness = sendEnhancedClientAwareness + } + fun build(): ApolloRequest { return ApolloRequest( operation = operation, @@ -164,7 +172,8 @@ private constructor( ignoreApolloClientHttpHeaders = ignoreApolloClientHttpHeaders, retryOnError = retryOnError, failFastIfOffline = failFastIfOffline, - ignoreUnknownKeys = ignoreUnknownKeys + ignoreUnknownKeys = ignoreUnknownKeys, + sendEnhancedClientAwareness = sendEnhancedClientAwareness, ) } } diff --git a/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo/ApolloClient.kt b/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo/ApolloClient.kt index 2730172a400..e25ca593241 100644 --- a/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo/ApolloClient.kt +++ b/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo/ApolloClient.kt @@ -86,6 +86,7 @@ private constructor( private val retryOnError: ((ApolloRequest<*>) -> Boolean)? = builder.retryOnError private val retryOnErrorInterceptor: ApolloInterceptor? = builder.retryOnErrorInterceptor private val failFastIfOffline = builder.failFastIfOffline + private val sendEnhancedClientAwareness = builder.sendEnhancedClientAwareness override val executionContext: ExecutionContext = builder.executionContext override val httpMethod: HttpMethod? = builder.httpMethod @@ -397,6 +398,18 @@ private constructor( var autoPersistedQueryInterceptor: ApolloInterceptor? = null private set + var sendEnhancedClientAwareness: Boolean = true + private set + + /** + * Configures whether client library metadata is sent in each request `extensions` key. + * Client library metadata is the Apollo Kotlin library name and version. + * + */ + fun sendEnhancedClientAwareness(sendEnhancedClientAwareness: Boolean): Builder = apply { + this.sendEnhancedClientAwareness = sendEnhancedClientAwareness + } + /** * Whether to fail fast if the device is offline. * Requires setting an interceptor that is aware of the network state with [retryOnErrorInterceptor]. @@ -963,6 +976,7 @@ private constructor( .cacheInterceptor(cacheInterceptor) .autoPersistedQueriesInterceptor(autoPersistedQueryInterceptor) .failFastIfOffline(failFastIfOffline) + .sendEnhancedClientAwareness(sendEnhancedClientAwareness) } } } From 0c03e8e823ae07d3a01e75f79c3ad55b5dae08b6 Mon Sep 17 00:00:00 2001 From: Calvin Cestari <146856+calvincestari@users.noreply.github.com> Date: Thu, 5 Jun 2025 12:42:42 -0700 Subject: [PATCH 08/17] Set value from request --- .../apollographql/apollo/api/http/DefaultHttpRequestComposer.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo/api/http/DefaultHttpRequestComposer.kt b/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo/api/http/DefaultHttpRequestComposer.kt index 7423fadcbff..7b898cefe6b 100644 --- a/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo/api/http/DefaultHttpRequestComposer.kt +++ b/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo/api/http/DefaultHttpRequestComposer.kt @@ -50,7 +50,7 @@ class DefaultHttpRequestComposer( } val sendApqExtensions = apolloRequest.sendApqExtensions ?: false - val sendEnhancedClientAwarenessExtensions = true + val sendEnhancedClientAwarenessExtensions = apolloRequest.sendEnhancedClientAwareness val sendDocument = apolloRequest.sendDocument ?: true val httpRequestBuilder = when (apolloRequest.httpMethod ?: HttpMethod.Post) { From 6a9315d609d2a14ed1e59750bf504f95d61d28d0 Mon Sep 17 00:00:00 2001 From: Calvin Cestari <146856+calvincestari@users.noreply.github.com> Date: Thu, 5 Jun 2025 12:43:48 -0700 Subject: [PATCH 09/17] Update API signature files --- libraries/apollo-api/api/apollo-api.api | 5 ++++- libraries/apollo-api/api/apollo-api.klib.api | 5 +++++ libraries/apollo-runtime/api/android/apollo-runtime.api | 2 ++ libraries/apollo-runtime/api/apollo-runtime.klib.api | 3 +++ libraries/apollo-runtime/api/jvm/apollo-runtime.api | 2 ++ 5 files changed, 16 insertions(+), 1 deletion(-) diff --git a/libraries/apollo-api/api/apollo-api.api b/libraries/apollo-api/api/apollo-api.api index 26e5fbe8446..2654939090c 100644 --- a/libraries/apollo-api/api/apollo-api.api +++ b/libraries/apollo-api/api/apollo-api.api @@ -50,7 +50,7 @@ public final class com/apollographql/apollo/api/ApolloOptionalAdapter : com/apol } public final class com/apollographql/apollo/api/ApolloRequest : com/apollographql/apollo/api/ExecutionOptions { - public synthetic fun (Lcom/apollographql/apollo/api/Operation;Ljava/util/UUID;Lcom/apollographql/apollo/api/ExecutionContext;Lcom/apollographql/apollo/api/http/HttpMethod;Ljava/util/List;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (Lcom/apollographql/apollo/api/Operation;Ljava/util/UUID;Lcom/apollographql/apollo/api/ExecutionContext;Lcom/apollographql/apollo/api/http/HttpMethod;Ljava/util/List;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;ZLkotlin/jvm/internal/DefaultConstructorMarker;)V public fun getCanBeBatched ()Ljava/lang/Boolean; public fun getEnableAutoPersistedQueries ()Ljava/lang/Boolean; public fun getExecutionContext ()Lcom/apollographql/apollo/api/ExecutionContext; @@ -64,6 +64,7 @@ public final class com/apollographql/apollo/api/ApolloRequest : com/apollographq public final fun getRetryOnError ()Ljava/lang/Boolean; public fun getSendApqExtensions ()Ljava/lang/Boolean; public fun getSendDocument ()Ljava/lang/Boolean; + public final fun getSendEnhancedClientAwareness ()Z public final fun newBuilder ()Lcom/apollographql/apollo/api/ApolloRequest$Builder; public final fun newBuilder (Lcom/apollographql/apollo/api/Operation;)Lcom/apollographql/apollo/api/ApolloRequest$Builder; } @@ -94,6 +95,7 @@ public final class com/apollographql/apollo/api/ApolloRequest$Builder : com/apol public final fun getRetryOnError ()Ljava/lang/Boolean; public fun getSendApqExtensions ()Ljava/lang/Boolean; public fun getSendDocument ()Ljava/lang/Boolean; + public final fun getSendEnhancedClientAwareness ()Z public fun httpHeaders (Ljava/util/List;)Lcom/apollographql/apollo/api/ApolloRequest$Builder; public synthetic fun httpHeaders (Ljava/util/List;)Ljava/lang/Object; public fun httpMethod (Lcom/apollographql/apollo/api/http/HttpMethod;)Lcom/apollographql/apollo/api/ApolloRequest$Builder; @@ -107,6 +109,7 @@ public final class com/apollographql/apollo/api/ApolloRequest$Builder : com/apol public synthetic fun sendApqExtensions (Ljava/lang/Boolean;)Ljava/lang/Object; public fun sendDocument (Ljava/lang/Boolean;)Lcom/apollographql/apollo/api/ApolloRequest$Builder; public synthetic fun sendDocument (Ljava/lang/Boolean;)Ljava/lang/Object; + public final fun sendEnhancedClientAwareness (Z)Lcom/apollographql/apollo/api/ApolloRequest$Builder; } public final class com/apollographql/apollo/api/ApolloResponse { diff --git a/libraries/apollo-api/api/apollo-api.klib.api b/libraries/apollo-api/api/apollo-api.klib.api index 178cc062161..15357f92a74 100644 --- a/libraries/apollo-api/api/apollo-api.klib.api +++ b/libraries/apollo-api/api/apollo-api.klib.api @@ -322,6 +322,8 @@ final class <#A: com.apollographql.apollo.api/Operation.Data> com.apollographql. final fun (): kotlin/Boolean? // com.apollographql.apollo.api/ApolloRequest.sendApqExtensions.|(){}[0] final val sendDocument // com.apollographql.apollo.api/ApolloRequest.sendDocument|{}sendDocument[0] final fun (): kotlin/Boolean? // com.apollographql.apollo.api/ApolloRequest.sendDocument.|(){}[0] + final val sendEnhancedClientAwareness // com.apollographql.apollo.api/ApolloRequest.sendEnhancedClientAwareness|{}sendEnhancedClientAwareness[0] + final fun (): kotlin/Boolean // com.apollographql.apollo.api/ApolloRequest.sendEnhancedClientAwareness.|(){}[0] final fun <#A1: com.apollographql.apollo.api/Operation.Data> newBuilder(com.apollographql.apollo.api/Operation<#A1>): com.apollographql.apollo.api/ApolloRequest.Builder<#A1> // com.apollographql.apollo.api/ApolloRequest.newBuilder|newBuilder(com.apollographql.apollo.api.Operation<0:0>){0§}[0] final fun newBuilder(): com.apollographql.apollo.api/ApolloRequest.Builder<#A> // com.apollographql.apollo.api/ApolloRequest.newBuilder|newBuilder(){}[0] @@ -356,6 +358,8 @@ final class <#A: com.apollographql.apollo.api/Operation.Data> com.apollographql. final fun (): kotlin/Boolean? // com.apollographql.apollo.api/ApolloRequest.Builder.sendApqExtensions.|(){}[0] final var sendDocument // com.apollographql.apollo.api/ApolloRequest.Builder.sendDocument|{}sendDocument[0] final fun (): kotlin/Boolean? // com.apollographql.apollo.api/ApolloRequest.Builder.sendDocument.|(){}[0] + final var sendEnhancedClientAwareness // com.apollographql.apollo.api/ApolloRequest.Builder.sendEnhancedClientAwareness|{}sendEnhancedClientAwareness[0] + final fun (): kotlin/Boolean // com.apollographql.apollo.api/ApolloRequest.Builder.sendEnhancedClientAwareness.|(){}[0] final fun addExecutionContext(com.apollographql.apollo.api/ExecutionContext): com.apollographql.apollo.api/ApolloRequest.Builder<#A1> // com.apollographql.apollo.api/ApolloRequest.Builder.addExecutionContext|addExecutionContext(com.apollographql.apollo.api.ExecutionContext){}[0] final fun addHttpHeader(kotlin/String, kotlin/String): com.apollographql.apollo.api/ApolloRequest.Builder<#A1> // com.apollographql.apollo.api/ApolloRequest.Builder.addHttpHeader|addHttpHeader(kotlin.String;kotlin.String){}[0] @@ -372,6 +376,7 @@ final class <#A: com.apollographql.apollo.api/Operation.Data> com.apollographql. final fun retryOnError(kotlin/Boolean?): com.apollographql.apollo.api/ApolloRequest.Builder<#A1> // com.apollographql.apollo.api/ApolloRequest.Builder.retryOnError|retryOnError(kotlin.Boolean?){}[0] final fun sendApqExtensions(kotlin/Boolean?): com.apollographql.apollo.api/ApolloRequest.Builder<#A1> // com.apollographql.apollo.api/ApolloRequest.Builder.sendApqExtensions|sendApqExtensions(kotlin.Boolean?){}[0] final fun sendDocument(kotlin/Boolean?): com.apollographql.apollo.api/ApolloRequest.Builder<#A1> // com.apollographql.apollo.api/ApolloRequest.Builder.sendDocument|sendDocument(kotlin.Boolean?){}[0] + final fun sendEnhancedClientAwareness(kotlin/Boolean): com.apollographql.apollo.api/ApolloRequest.Builder<#A1> // com.apollographql.apollo.api/ApolloRequest.Builder.sendEnhancedClientAwareness|sendEnhancedClientAwareness(kotlin.Boolean){}[0] } } diff --git a/libraries/apollo-runtime/api/android/apollo-runtime.api b/libraries/apollo-runtime/api/android/apollo-runtime.api index e022cfd8ffd..1eb9c3330bb 100644 --- a/libraries/apollo-runtime/api/android/apollo-runtime.api +++ b/libraries/apollo-runtime/api/android/apollo-runtime.api @@ -108,6 +108,7 @@ public final class com/apollographql/apollo/ApolloClient$Builder : com/apollogra public final fun getRetryOnErrorInterceptor ()Lcom/apollographql/apollo/interceptor/ApolloInterceptor; public fun getSendApqExtensions ()Ljava/lang/Boolean; public fun getSendDocument ()Ljava/lang/Boolean; + public final fun getSendEnhancedClientAwareness ()Z public final fun getSubscriptionNetworkTransport ()Lcom/apollographql/apollo/network/NetworkTransport; public final fun getWebSocketEngine ()Lcom/apollographql/apollo/network/ws/WebSocketEngine; public final fun getWebSocketIdleTimeoutMillis ()Ljava/lang/Long; @@ -140,6 +141,7 @@ public final class com/apollographql/apollo/ApolloClient$Builder : com/apollogra public synthetic fun sendApqExtensions (Ljava/lang/Boolean;)Ljava/lang/Object; public fun sendDocument (Ljava/lang/Boolean;)Lcom/apollographql/apollo/ApolloClient$Builder; public synthetic fun sendDocument (Ljava/lang/Boolean;)Ljava/lang/Object; + public final fun sendEnhancedClientAwareness (Z)Lcom/apollographql/apollo/ApolloClient$Builder; public final fun serverUrl (Ljava/lang/String;)Lcom/apollographql/apollo/ApolloClient$Builder; public final fun subscriptionNetworkTransport (Lcom/apollographql/apollo/network/NetworkTransport;)Lcom/apollographql/apollo/ApolloClient$Builder; public final fun webSocketEngine (Lcom/apollographql/apollo/network/ws/WebSocketEngine;)Lcom/apollographql/apollo/ApolloClient$Builder; diff --git a/libraries/apollo-runtime/api/apollo-runtime.klib.api b/libraries/apollo-runtime/api/apollo-runtime.klib.api index a3a688e4296..29a86706313 100644 --- a/libraries/apollo-runtime/api/apollo-runtime.klib.api +++ b/libraries/apollo-runtime/api/apollo-runtime.klib.api @@ -660,6 +660,8 @@ final class com.apollographql.apollo/ApolloClient : com.apollographql.apollo.api final fun (): kotlin/Boolean? // com.apollographql.apollo/ApolloClient.Builder.sendApqExtensions.|(){}[0] final var sendDocument // com.apollographql.apollo/ApolloClient.Builder.sendDocument|{}sendDocument[0] final fun (): kotlin/Boolean? // com.apollographql.apollo/ApolloClient.Builder.sendDocument.|(){}[0] + final var sendEnhancedClientAwareness // com.apollographql.apollo/ApolloClient.Builder.sendEnhancedClientAwareness|{}sendEnhancedClientAwareness[0] + final fun (): kotlin/Boolean // com.apollographql.apollo/ApolloClient.Builder.sendEnhancedClientAwareness.|(){}[0] final var subscriptionNetworkTransport // com.apollographql.apollo/ApolloClient.Builder.subscriptionNetworkTransport|{}subscriptionNetworkTransport[0] final fun (): com.apollographql.apollo.network/NetworkTransport? // com.apollographql.apollo/ApolloClient.Builder.subscriptionNetworkTransport.|(){}[0] final var webSocketEngine // com.apollographql.apollo/ApolloClient.Builder.webSocketEngine|{}webSocketEngine[0] @@ -708,6 +710,7 @@ final class com.apollographql.apollo/ApolloClient : com.apollographql.apollo.api final fun retryOnErrorInterceptor(com.apollographql.apollo.interceptor/ApolloInterceptor?): com.apollographql.apollo/ApolloClient.Builder // com.apollographql.apollo/ApolloClient.Builder.retryOnErrorInterceptor|retryOnErrorInterceptor(com.apollographql.apollo.interceptor.ApolloInterceptor?){}[0] final fun sendApqExtensions(kotlin/Boolean?): com.apollographql.apollo/ApolloClient.Builder // com.apollographql.apollo/ApolloClient.Builder.sendApqExtensions|sendApqExtensions(kotlin.Boolean?){}[0] final fun sendDocument(kotlin/Boolean?): com.apollographql.apollo/ApolloClient.Builder // com.apollographql.apollo/ApolloClient.Builder.sendDocument|sendDocument(kotlin.Boolean?){}[0] + final fun sendEnhancedClientAwareness(kotlin/Boolean): com.apollographql.apollo/ApolloClient.Builder // com.apollographql.apollo/ApolloClient.Builder.sendEnhancedClientAwareness|sendEnhancedClientAwareness(kotlin.Boolean){}[0] final fun serverUrl(kotlin/String): com.apollographql.apollo/ApolloClient.Builder // com.apollographql.apollo/ApolloClient.Builder.serverUrl|serverUrl(kotlin.String){}[0] final fun subscriptionNetworkTransport(com.apollographql.apollo.network/NetworkTransport?): com.apollographql.apollo/ApolloClient.Builder // com.apollographql.apollo/ApolloClient.Builder.subscriptionNetworkTransport|subscriptionNetworkTransport(com.apollographql.apollo.network.NetworkTransport?){}[0] final fun webSocketEngine(com.apollographql.apollo.network.ws/WebSocketEngine?): com.apollographql.apollo/ApolloClient.Builder // com.apollographql.apollo/ApolloClient.Builder.webSocketEngine|webSocketEngine(com.apollographql.apollo.network.ws.WebSocketEngine?){}[0] diff --git a/libraries/apollo-runtime/api/jvm/apollo-runtime.api b/libraries/apollo-runtime/api/jvm/apollo-runtime.api index d1a2b49d652..ae89653f943 100644 --- a/libraries/apollo-runtime/api/jvm/apollo-runtime.api +++ b/libraries/apollo-runtime/api/jvm/apollo-runtime.api @@ -108,6 +108,7 @@ public final class com/apollographql/apollo/ApolloClient$Builder : com/apollogra public final fun getRetryOnErrorInterceptor ()Lcom/apollographql/apollo/interceptor/ApolloInterceptor; public fun getSendApqExtensions ()Ljava/lang/Boolean; public fun getSendDocument ()Ljava/lang/Boolean; + public final fun getSendEnhancedClientAwareness ()Z public final fun getSubscriptionNetworkTransport ()Lcom/apollographql/apollo/network/NetworkTransport; public final fun getWebSocketEngine ()Lcom/apollographql/apollo/network/ws/WebSocketEngine; public final fun getWebSocketIdleTimeoutMillis ()Ljava/lang/Long; @@ -140,6 +141,7 @@ public final class com/apollographql/apollo/ApolloClient$Builder : com/apollogra public synthetic fun sendApqExtensions (Ljava/lang/Boolean;)Ljava/lang/Object; public fun sendDocument (Ljava/lang/Boolean;)Lcom/apollographql/apollo/ApolloClient$Builder; public synthetic fun sendDocument (Ljava/lang/Boolean;)Ljava/lang/Object; + public final fun sendEnhancedClientAwareness (Z)Lcom/apollographql/apollo/ApolloClient$Builder; public final fun serverUrl (Ljava/lang/String;)Lcom/apollographql/apollo/ApolloClient$Builder; public final fun subscriptionNetworkTransport (Lcom/apollographql/apollo/network/NetworkTransport;)Lcom/apollographql/apollo/ApolloClient$Builder; public final fun webSocketEngine (Lcom/apollographql/apollo/network/ws/WebSocketEngine;)Lcom/apollographql/apollo/ApolloClient$Builder; From 7776056a9a627e246a8943026c47d67f7a4592ad Mon Sep 17 00:00:00 2001 From: Calvin Cestari <146856+calvincestari@users.noreply.github.com> Date: Thu, 5 Jun 2025 18:47:32 -0700 Subject: [PATCH 10/17] Adds request composer test --- .../src/commonTest/kotlin/test/HttpRequestComposerTest.kt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/integration-tests/src/commonTest/kotlin/test/HttpRequestComposerTest.kt b/tests/integration-tests/src/commonTest/kotlin/test/HttpRequestComposerTest.kt index bd831a595a1..872aaf5e20e 100644 --- a/tests/integration-tests/src/commonTest/kotlin/test/HttpRequestComposerTest.kt +++ b/tests/integration-tests/src/commonTest/kotlin/test/HttpRequestComposerTest.kt @@ -35,6 +35,13 @@ class HttpRequestComposerTest { checkTestFixture(bodyText, "allPlanets.json") } + @Test + fun requestBuilderSetsEnhancedClientAwarenessExtensionsTrueByDefault() { + val apolloRequest = ApolloRequest.Builder(AllPlanetsQuery()).build() + + assertEquals(true, apolloRequest.sendEnhancedClientAwareness) + } + @Test fun requestHeadersAreForwardedToTheServer() = runTest(before = { setUp() }, after = { tearDown() }) { val apolloClient = ApolloClient.Builder().serverUrl(mockServer.url()).build() From 641b3d03f793e4f9299638814a042d358510c19f Mon Sep 17 00:00:00 2001 From: Calvin Cestari <146856+calvincestari@users.noreply.github.com> Date: Thu, 5 Jun 2025 18:47:41 -0700 Subject: [PATCH 11/17] Adds body extensions tests --- .../kotlin/test/BodyExtensionsTest.kt | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/tests/integration-tests/src/commonTest/kotlin/test/BodyExtensionsTest.kt b/tests/integration-tests/src/commonTest/kotlin/test/BodyExtensionsTest.kt index 8d5b10bda71..18ed696e0a5 100644 --- a/tests/integration-tests/src/commonTest/kotlin/test/BodyExtensionsTest.kt +++ b/tests/integration-tests/src/commonTest/kotlin/test/BodyExtensionsTest.kt @@ -71,4 +71,60 @@ class BodyExtensionsTest { apolloClient.close() mockServer.close() } + + @Suppress("UNCHECKED_CAST") + @Test + fun enhancedClientAwarenessExtensionsIncludedByDefault() = runTest { + val mockServer = MockServer() + + val apolloClient = ApolloClient.Builder() + .networkTransport( + HttpNetworkTransport.Builder() + .httpRequestComposer(DefaultHttpRequestComposer(mockServer.url())) + .build() + ) + .build() + + mockServer.enqueueError(statusCode = 500) + apolloClient.query(LaunchDetailsQuery("42")).execute() + + val request = mockServer.awaitRequest() + + @Suppress("UNCHECKED_CAST") + val asMap = Buffer().write(request.body).jsonReader().readAny() as Map + val expected: Map = mapOf("name" to "apollo-kotlin", "version" to com.apollographql.apollo.api.apolloApiVersion) + + assertEquals(expected, (asMap["extensions"] as Map).get("clientLibrary")) + + apolloClient.close() + mockServer.close() + } + + @Suppress("UNCHECKED_CAST") + @Test + fun enhancedClientAwarenessExtensionsExcludedWhenDisabled() = runTest { + val mockServer = MockServer() + + val apolloClient = ApolloClient.Builder() + .sendEnhancedClientAwareness(false) + .networkTransport( + HttpNetworkTransport.Builder() + .httpRequestComposer(DefaultHttpRequestComposer(mockServer.url())) + .build() + ) + .build() + + mockServer.enqueueError(statusCode = 500) + apolloClient.query(LaunchDetailsQuery("42")).execute() + + val request = mockServer.awaitRequest() + + @Suppress("UNCHECKED_CAST") + val asMap = Buffer().write(request.body).jsonReader().readAny() as Map + + assertEquals(null, (asMap["extensions"] as Map).get("clientLibrary")) + + apolloClient.close() + mockServer.close() + } } From 968506ef8b456d3339fb9a7ec695f93648e1dc11 Mon Sep 17 00:00:00 2001 From: Calvin Cestari <146856+calvincestari@users.noreply.github.com> Date: Fri, 6 Jun 2025 11:09:53 -0700 Subject: [PATCH 12/17] Remove unnecessary test --- .../src/commonTest/kotlin/test/HttpRequestComposerTest.kt | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tests/integration-tests/src/commonTest/kotlin/test/HttpRequestComposerTest.kt b/tests/integration-tests/src/commonTest/kotlin/test/HttpRequestComposerTest.kt index 872aaf5e20e..bd831a595a1 100644 --- a/tests/integration-tests/src/commonTest/kotlin/test/HttpRequestComposerTest.kt +++ b/tests/integration-tests/src/commonTest/kotlin/test/HttpRequestComposerTest.kt @@ -35,13 +35,6 @@ class HttpRequestComposerTest { checkTestFixture(bodyText, "allPlanets.json") } - @Test - fun requestBuilderSetsEnhancedClientAwarenessExtensionsTrueByDefault() { - val apolloRequest = ApolloRequest.Builder(AllPlanetsQuery()).build() - - assertEquals(true, apolloRequest.sendEnhancedClientAwareness) - } - @Test fun requestHeadersAreForwardedToTheServer() = runTest(before = { setUp() }, after = { tearDown() }) { val apolloClient = ApolloClient.Builder().serverUrl(mockServer.url()).build() From 19d1ec86ca62790ba47b5eeba9cb124d912b08f3 Mon Sep 17 00:00:00 2001 From: Calvin Cestari <146856+calvincestari@users.noreply.github.com> Date: Fri, 6 Jun 2025 12:48:46 -0700 Subject: [PATCH 13/17] Refactor into single object and fix version --- .../apollo/api/http/DefaultHttpRequestComposer.kt | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo/api/http/DefaultHttpRequestComposer.kt b/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo/api/http/DefaultHttpRequestComposer.kt index 7b898cefe6b..0e33361bfa4 100644 --- a/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo/api/http/DefaultHttpRequestComposer.kt +++ b/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo/api/http/DefaultHttpRequestComposer.kt @@ -220,22 +220,19 @@ class DefaultHttpRequestComposer( } val extensions = buildJsonString { - if (autoPersistQueries) { - writeObject { + writeObject { + if (autoPersistQueries) { name("persistedQuery") writeObject { name("version").value(1) name("sha256Hash").value(operation.id()) } } - } - - if (sendEnhancedClientAwareness) { - writeObject { + if (sendEnhancedClientAwareness) { name("clientLibrary") writeObject { name("name").value("apollo-kotlin") - name("version").value(0) + name("version").value(com.apollographql.apollo.api.apolloApiVersion) } } } From 8e60dc704ccc72d8f636429d29a7634254d01685 Mon Sep 17 00:00:00 2001 From: Calvin Cestari <146856+calvincestari@users.noreply.github.com> Date: Fri, 6 Jun 2025 13:38:29 -0700 Subject: [PATCH 14/17] Correctly set flag value --- .../apollographql/apollo/api/http/DefaultHttpRequestComposer.kt | 2 +- .../commonMain/kotlin/com/apollographql/apollo/ApolloClient.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo/api/http/DefaultHttpRequestComposer.kt b/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo/api/http/DefaultHttpRequestComposer.kt index 0e33361bfa4..9170e69bc59 100644 --- a/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo/api/http/DefaultHttpRequestComposer.kt +++ b/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo/api/http/DefaultHttpRequestComposer.kt @@ -341,7 +341,7 @@ class DefaultHttpRequestComposer( ): Map { val operation = apolloRequest.operation val sendApqExtensions = apolloRequest.sendApqExtensions ?: false - val sendEnhancedClientAwarenessExtensions = true + val sendEnhancedClientAwarenessExtensions = apolloRequest.sendEnhancedClientAwareness val sendDocument = apolloRequest.sendDocument ?: true val customScalarAdapters = apolloRequest.executionContext[CustomScalarAdapters] ?: CustomScalarAdapters.Empty diff --git a/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo/ApolloClient.kt b/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo/ApolloClient.kt index e25ca593241..3ae5aaef692 100644 --- a/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo/ApolloClient.kt +++ b/libraries/apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo/ApolloClient.kt @@ -289,8 +289,8 @@ private constructor( retryOnError(retryOnError ?: apolloClient.retryOnError?.invoke(apolloRequest)) failFastIfOffline(failFastIfOffline ?: apolloClient.failFastIfOffline) - ignoreUnknownKeys(ignoreUnknownKeys ?: apolloClient.ignoreUnknownKeys) + sendEnhancedClientAwareness(apolloClient.sendEnhancedClientAwareness) }.build() val allInterceptors = buildList { From ffdbff1e5a6b03f09e801064b287edbaf41f971b Mon Sep 17 00:00:00 2001 From: Calvin Cestari <146856+calvincestari@users.noreply.github.com> Date: Fri, 6 Jun 2025 13:38:41 -0700 Subject: [PATCH 15/17] Fix null test --- .../src/commonTest/kotlin/test/BodyExtensionsTest.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/integration-tests/src/commonTest/kotlin/test/BodyExtensionsTest.kt b/tests/integration-tests/src/commonTest/kotlin/test/BodyExtensionsTest.kt index 18ed696e0a5..880ed07d1f6 100644 --- a/tests/integration-tests/src/commonTest/kotlin/test/BodyExtensionsTest.kt +++ b/tests/integration-tests/src/commonTest/kotlin/test/BodyExtensionsTest.kt @@ -20,6 +20,7 @@ import com.apollographql.apollo.testing.internal.runTest import okio.Buffer import kotlin.test.Test import kotlin.test.assertEquals +import kotlin.test.assertNull class WithExtensionsHttpRequestComposer(private val serverUrl: String) : HttpRequestComposer { override fun compose(apolloRequest: ApolloRequest): HttpRequest { @@ -121,8 +122,8 @@ class BodyExtensionsTest { @Suppress("UNCHECKED_CAST") val asMap = Buffer().write(request.body).jsonReader().readAny() as Map - - assertEquals(null, (asMap["extensions"] as Map).get("clientLibrary")) + + assertNull((asMap["extensions"] as? Map)?.get("clientLibrary")) apolloClient.close() mockServer.close() From 611b4591da1918ddb20370ae0b5d27caa1b25c35 Mon Sep 17 00:00:00 2001 From: Martin Bonnin Date: Sat, 7 Jun 2025 01:00:55 +0200 Subject: [PATCH 16/17] update tests --- .../src/test/graphql/com/example/measurements | 11 +++++++---- .../src/commonTest/kotlin/test/HttpGetTest.kt | 5 +++-- .../commonTest/kotlin/test/LoggingInterceptorTest.kt | 4 ++-- .../src/jvmTest/kotlin/test/JvmFileUploadTest.kt | 2 +- tests/integration-tests/testFixtures/allPlanets.json | 2 +- .../expectedOperationsPartBodyMultiple.json | 2 +- .../expectedOperationsPartBodyNested.json | 2 +- .../expectedOperationsPartBodySingle.json | 2 +- .../testFixtures/expectedOperationsPartBodyTwice.json | 2 +- 9 files changed, 18 insertions(+), 14 deletions(-) diff --git a/libraries/apollo-compiler/src/test/graphql/com/example/measurements b/libraries/apollo-compiler/src/test/graphql/com/example/measurements index 0a4f536cd96..6f3fb517538 100644 --- a/libraries/apollo-compiler/src/test/graphql/com/example/measurements +++ b/libraries/apollo-compiler/src/test/graphql/com/example/measurements @@ -2,16 +2,17 @@ // If you updated the codegen and test fixtures, you should commit this file too. Test: Total LOC: -aggregate-all 195528 -aggregate-kotlin-responseBased 61630 -aggregate-kotlin-operationBased 39804 +aggregate-all 201251 +aggregate-kotlin-responseBased 63247 +aggregate-kotlin-operationBased 41359 aggregate-kotlin-compat 0 -aggregate-java-operationBased 94094 +aggregate-java-operationBased 96645 java-operationBased-fragments_with_defer_and_include_directives 5754 kotlin-operationBased-fragments_with_defer_and_include_directives 3416 java-operationBased-data_builders 3013 kotlin-responseBased-data_builders 2626 +java-operationBased-typepolicy 2551 java-operationBased-mutation_create_review 2419 kotlin-responseBased-fragment_with_inline_fragment 2407 java-operationBased-fragment_with_inline_fragment 2237 @@ -24,8 +25,10 @@ kotlin-responseBased-mutation_create_review java-operationBased-mutation_create_review_semantic_naming 1629 java-operationBased-unique_type_name 1627 java-operationBased-inline_fragment_intersection 1623 +kotlin-responseBased-typepolicy 1617 kotlin-responseBased-nested_named_fragments 1610 java-operationBased-root_query_fragment_with_nested_fragments 1569 +kotlin-operationBased-typepolicy 1555 java-operationBased-named_fragment_delegate 1457 java-operationBased-simple_fragment 1438 java-operationBased-named_fragment_with_variables 1398 diff --git a/tests/integration-tests/src/commonTest/kotlin/test/HttpGetTest.kt b/tests/integration-tests/src/commonTest/kotlin/test/HttpGetTest.kt index 0f99193ae95..1817cdc1622 100644 --- a/tests/integration-tests/src/commonTest/kotlin/test/HttpGetTest.kt +++ b/tests/integration-tests/src/commonTest/kotlin/test/HttpGetTest.kt @@ -1,6 +1,7 @@ package test import com.apollographql.apollo.ApolloClient +import com.apollographql.apollo.api.apolloApiVersion import com.apollographql.apollo.api.http.HttpMethod import com.apollographql.apollo.integration.normalizer.HeroAndFriendsNamesQuery import com.apollographql.apollo.integration.normalizer.SearchHeroQuery @@ -38,7 +39,7 @@ class HttpGetTest { .execute() assertEquals(response.data?.hero?.name, "R2-D2") assertEquals( - "/?operationName=HeroAndFriendsNames&variables=%7B%22episode%22%3A%22JEDI%22%7D&query=query%20HeroAndFriendsNames%28%24episode%3A%20Episode%29%20%7B%20hero%28episode%3A%20%24episode%29%20%7B%20name%20friends%20%7B%20name%20%7D%20%7D%20%7D", + "/?operationName=HeroAndFriendsNames&variables=%7B%22episode%22%3A%22JEDI%22%7D&query=query%20HeroAndFriendsNames%28%24episode%3A%20Episode%29%20%7B%20hero%28episode%3A%20%24episode%29%20%7B%20name%20friends%20%7B%20name%20%7D%20%7D%20%7D&extensions=%7B%22clientLibrary%22%3A%7B%22name%22%3A%22apollo-kotlin%22%2C%22version%22%3A%22${apolloApiVersion}%22%7D%7D", mockServer.awaitRequest().path ) } @@ -50,7 +51,7 @@ class HttpGetTest { .httpMethod(HttpMethod.Get) .execute() assertEquals( - "/?operationName=SearchHero&variables=%7B%22text%22%3A%22%21%23%24%26%27%28%29%2A%2B%2C%2F%3A%3B%3D%3F%40%5B%5D%7B%7D%25%20%22%7D&query=query%20SearchHero%28%24text%3A%20String%29%20%7B%20search%28text%3A%20%24text%29%20%7B%20__typename%20...%20on%20Character%20%7B%20__typename%20name%20...%20on%20Human%20%7B%20homePlanet%20%7D%20...%20on%20Droid%20%7B%20primaryFunction%20%7D%20%7D%20%7D%20%7D", + "/?operationName=SearchHero&variables=%7B%22text%22%3A%22%21%23%24%26%27%28%29%2A%2B%2C%2F%3A%3B%3D%3F%40%5B%5D%7B%7D%25%20%22%7D&query=query%20SearchHero%28%24text%3A%20String%29%20%7B%20search%28text%3A%20%24text%29%20%7B%20__typename%20...%20on%20Character%20%7B%20__typename%20name%20...%20on%20Human%20%7B%20homePlanet%20%7D%20...%20on%20Droid%20%7B%20primaryFunction%20%7D%20%7D%20%7D%20%7D&extensions=%7B%22clientLibrary%22%3A%7B%22name%22%3A%22apollo-kotlin%22%2C%22version%22%3A%22${apolloApiVersion}%22%7D%7D", mockServer.awaitRequest().path ) } diff --git a/tests/integration-tests/src/commonTest/kotlin/test/LoggingInterceptorTest.kt b/tests/integration-tests/src/commonTest/kotlin/test/LoggingInterceptorTest.kt index f93a31e6b37..5221623290c 100644 --- a/tests/integration-tests/src/commonTest/kotlin/test/LoggingInterceptorTest.kt +++ b/tests/integration-tests/src/commonTest/kotlin/test/LoggingInterceptorTest.kt @@ -142,7 +142,7 @@ class LoggingInterceptorTest { Post http://0.0.0.0/ accept: multipart/mixed;deferspec=20220824, application/graphql-response+json, application/json [end of headers] - {"operationName":"HeroName","variables":{},"query":"query HeroName { hero { name } }"} + {"operationName":"HeroName","variables":{},"query":"query HeroName { hero { name } }","extensions":{"clientlibrary":{"name":"apollo-kotlin","version":"5.0.0-snapshot"}}} HTTP: 200 Content-Type: text/plain @@ -183,7 +183,7 @@ class LoggingInterceptorTest { Post http://0.0.0.0/ accept: multipart/mixed;deferspec=20220824, application/graphql-response+json, application/json [end of headers] - {"operationName":"HeroName","variables":{},"query":"query HeroName { hero { name } }"} + {"operationName":"HeroName","variables":{},"query":"query HeroName { hero { name } }","extensions":{"clientlibrary":{"name":"apollo-kotlin","version":"5.0.0-snapshot"}}} HTTP: 200 Content-Type: text/plain diff --git a/tests/integration-tests/src/jvmTest/kotlin/test/JvmFileUploadTest.kt b/tests/integration-tests/src/jvmTest/kotlin/test/JvmFileUploadTest.kt index e9d2552966e..e5357bc27d3 100644 --- a/tests/integration-tests/src/jvmTest/kotlin/test/JvmFileUploadTest.kt +++ b/tests/integration-tests/src/jvmTest/kotlin/test/JvmFileUploadTest.kt @@ -53,7 +53,7 @@ class JvmFileUploadTest { val request = mockServer.awaitRequest() val parts = request.parts() - val expectedBodyLength = 1009 + val expectedBodyLength = 1092 assertEquals(expectedBodyLength, request.body.size) assertEquals(expectedBodyLength.toString(), request.headers["Content-Length"]) assertEquals(4, parts.size) diff --git a/tests/integration-tests/testFixtures/allPlanets.json b/tests/integration-tests/testFixtures/allPlanets.json index 306fea73a37..7e104220d8b 100644 --- a/tests/integration-tests/testFixtures/allPlanets.json +++ b/tests/integration-tests/testFixtures/allPlanets.json @@ -1 +1 @@ -{"operationName":"AllPlanets","variables":{},"query":"query AllPlanets { allPlanets(first: 300) { planets { __typename ...PlanetFragment filmConnection { totalCount films { __typename title ...FilmFragment } } } } } fragment PlanetFragment on Planet { name climates surfaceWater } fragment FilmFragment on Film { title producers }"} \ No newline at end of file +{"operationName":"AllPlanets","variables":{},"query":"query AllPlanets { allPlanets(first: 300) { planets { __typename ...PlanetFragment filmConnection { totalCount films { __typename title ...FilmFragment } } } } } fragment PlanetFragment on Planet { name climates surfaceWater } fragment FilmFragment on Film { title producers }","extensions":{"clientLibrary":{"name":"apollo-kotlin","version":"5.0.0-SNAPSHOT"}}} \ No newline at end of file diff --git a/tests/integration-tests/testFixtures/expectedOperationsPartBodyMultiple.json b/tests/integration-tests/testFixtures/expectedOperationsPartBodyMultiple.json index 19c3baa3802..a1169a66e79 100644 --- a/tests/integration-tests/testFixtures/expectedOperationsPartBodyMultiple.json +++ b/tests/integration-tests/testFixtures/expectedOperationsPartBodyMultiple.json @@ -1 +1 @@ -{"operationName":"MultipleUpload","variables":{"files":[null,null]},"query":"mutation MultipleUpload($files: [Upload!]!) { multipleUpload(files: $files) { id path filename mimetype } }"} \ No newline at end of file +{"operationName":"MultipleUpload","variables":{"files":[null,null]},"query":"mutation MultipleUpload($files: [Upload!]!) { multipleUpload(files: $files) { id path filename mimetype } }","extensions":{"clientLibrary":{"name":"apollo-kotlin","version":"5.0.0-SNAPSHOT"}}} \ No newline at end of file diff --git a/tests/integration-tests/testFixtures/expectedOperationsPartBodyNested.json b/tests/integration-tests/testFixtures/expectedOperationsPartBodyNested.json index 7fbb1b15711..0d433c63fa7 100644 --- a/tests/integration-tests/testFixtures/expectedOperationsPartBodyNested.json +++ b/tests/integration-tests/testFixtures/expectedOperationsPartBodyNested.json @@ -1 +1 @@ -{"operationName":"NestedUpload","variables":{"topFile":null,"topFileList":[null,null],"nested":{"recursiveNested":[{"file":null,"fileList":[null,null]},{"file":null,"fileList":[null,null]}],"file":null,"fileList":[null,null]}},"query":"mutation NestedUpload($topFile: Upload, $topFileList: [Upload], $nested: NestedObject) { nestedUpload(topFile: $topFile, topFileList: $topFileList, nested: $nested) }"} \ No newline at end of file +{"operationName":"NestedUpload","variables":{"topFile":null,"topFileList":[null,null],"nested":{"recursiveNested":[{"file":null,"fileList":[null,null]},{"file":null,"fileList":[null,null]}],"file":null,"fileList":[null,null]}},"query":"mutation NestedUpload($topFile: Upload, $topFileList: [Upload], $nested: NestedObject) { nestedUpload(topFile: $topFile, topFileList: $topFileList, nested: $nested) }","extensions":{"clientLibrary":{"name":"apollo-kotlin","version":"5.0.0-SNAPSHOT"}}} \ No newline at end of file diff --git a/tests/integration-tests/testFixtures/expectedOperationsPartBodySingle.json b/tests/integration-tests/testFixtures/expectedOperationsPartBodySingle.json index 095fd3c9540..5c9ecf0caf5 100644 --- a/tests/integration-tests/testFixtures/expectedOperationsPartBodySingle.json +++ b/tests/integration-tests/testFixtures/expectedOperationsPartBodySingle.json @@ -1 +1 @@ -{"operationName":"SingleUpload","variables":{"file":null},"query":"mutation SingleUpload($file: Upload!) { singleUpload(file: $file) { id path filename mimetype } }"} \ No newline at end of file +{"operationName":"SingleUpload","variables":{"file":null},"query":"mutation SingleUpload($file: Upload!) { singleUpload(file: $file) { id path filename mimetype } }","extensions":{"clientLibrary":{"name":"apollo-kotlin","version":"5.0.0-SNAPSHOT"}}} \ No newline at end of file diff --git a/tests/integration-tests/testFixtures/expectedOperationsPartBodyTwice.json b/tests/integration-tests/testFixtures/expectedOperationsPartBodyTwice.json index d49e33e7459..9a3cee5902f 100644 --- a/tests/integration-tests/testFixtures/expectedOperationsPartBodyTwice.json +++ b/tests/integration-tests/testFixtures/expectedOperationsPartBodyTwice.json @@ -1 +1 @@ -{"operationName":"SingleUploadTwice","variables":{"file1":null,"file2":null},"query":"mutation SingleUploadTwice($file1: Upload!, $file2: Upload!) { file1: singleUpload(file: $file1) { id path filename mimetype } file2: singleUpload(file: $file2) { id path filename mimetype } }"} \ No newline at end of file +{"operationName":"SingleUploadTwice","variables":{"file1":null,"file2":null},"query":"mutation SingleUploadTwice($file1: Upload!, $file2: Upload!) { file1: singleUpload(file: $file1) { id path filename mimetype } file2: singleUpload(file: $file2) { id path filename mimetype } }","extensions":{"clientLibrary":{"name":"apollo-kotlin","version":"5.0.0-SNAPSHOT"}}} \ No newline at end of file From 88ca4ccd2715ac03f86ad6dc8b158f9867f44b7a Mon Sep 17 00:00:00 2001 From: BoD Date: Tue, 10 Jun 2025 10:16:11 +0200 Subject: [PATCH 17/17] Update fixtures when making a release --- scripts/release.main.kts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/scripts/release.main.kts b/scripts/release.main.kts index 762a8d16fb8..8a8c99998d6 100755 --- a/scripts/release.main.kts +++ b/scripts/release.main.kts @@ -72,6 +72,7 @@ println("Tag pushed.") val bumpVersionBranchName = "release-$versionToRelease-bump-snapshot" runCommand("git", "checkout", "-b", bumpVersionBranchName) setCurrentVersion(nextSnapshot) +setVersionInFixtures(nextSnapshot) runCommand("git", "commit", "-a", "-m", "version is now $nextSnapshot") runCommand("git", "push", "origin", bumpVersionBranchName) runCommand("gh", "pr", "create", "--base", startBranch, "--fill") @@ -243,6 +244,18 @@ fun setVersionInIntelliJPlugin(version: String) { } } +fun setVersionInFixtures(nextSnapshot: String) { + for (file in File("tests/integration-tests/testFixtures").walk()) { + if (file.isDirectory || !file.name.endsWith(".json")) continue + val content = file.readText() + .replace(Regex("""\{"name":"apollo-kotlin","version":"(.+)"\}""")) { + """{"name":"apollo-kotlin","version":"$nextSnapshot"}""" + } + file.writeText(content) + } +} + + fun mergeAndWait(branchName: String) { runCommand("gh", "pr", "merge", branchName, "--squash", "--auto", "--delete-branch") println("Waiting for the PR to be merged...")