Repository: apollographql/apollo-kotlin
Pull request #4830 (2023-04-03 16:41:07)

Update subscription docs to include multipart subscriptions

netlify[bot]: ### <span aria-hidden="true">👷</span> Deploy Preview for *apollo-android-docs* processing.


|  Name | Link |
|:-:|------------------------|
|<span aria-hidden="true">🔨</span> Latest commit | f8b842979b18b469535d56424e2c78ef2394d265 |
|<span aria-hidden="true">🔍</span> Latest deploy log | https://app.netlify.com/sites/apollo-android-docs/deploys/642b01a523573d00086578f3 |

Patch:
diff --git a/docs/source/essentials/custom-scalars.mdx b/docs/source/essentials/custom-scalars.mdx
index ac4ceb96cc..15492e71f9 100644
--- a/docs/source/essentials/custom-scalars.mdx
+++ b/docs/source/essentials/custom-scalars.mdx
@@ -138,6 +138,8 @@ In addition, the `com.apollographql.apollo3:apollo-adapters` artifact provides t
 | `com.apollographql.apollo3.adapter.JavaLocalDateAdapter`        | For `java.time.LocalDate` ISO8601 dates                                                             |
 | `com.apollographql.apollo3.adapter.KotlinxLocalDateTimeAdapter` | For `kotlinx.datetime.LocalDateTime` ISO8601 dates                                                  |
 | `com.apollographql.apollo3.adapter.JavaLocalDateTimeAdapter`    | For `java.time.LocalDateTime` ISO8601 dates                                                         |
+| `com.apollographql.apollo3.adapter.KotlinxLocalTimeAdapter`     | For `kotlinx.datetime.LocalTime` ISO8601 dates                                                      |
+| `com.apollographql.apollo3.adapter.JavaLocalTimeAdapter`        | For `java.time.LocalTime` ISO8601 dates                                                         |
 | `com.apollographql.apollo3.adapter.JavaOffsetDateTimeAdapter`   | For `java.time.OffsetDateTime` ISO8601 dates                                                        |
 | `com.apollographql.apollo3.adapter.DateAdapter`                 | For `java.util.Date` ISO8601 dates                                                                  |
 | `com.apollographql.apollo3.adapter.BigDecimalAdapter`           | For a Multiplatform `com.apollographql.apollo3.adapter.BigDecimal` class holding big decimal values |
diff --git a/docs/source/essentials/subscriptions.mdx b/docs/source/essentials/subscriptions.mdx
index fddc4e8c01..9f856aed8c 100644
--- a/docs/source/essentials/subscriptions.mdx
+++ b/docs/source/essentials/subscriptions.mdx
@@ -2,12 +2,17 @@
 title: Subscriptions in Apollo Kotlin
 ---
 
-> By default, Apollo Kotlin uses the [`subscriptions-transport-ws`](https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md) protocol for subscriptions via the `SubscriptionWsProtocol` class. **This protocol is no longer actively maintained.** It remains the default for backward compatibility purposes.
->
-> A future version of Apollo Kotlin will change the default to the newer [`graphql-ws`](https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md) protocol and `GraphQLWsProtocol` class. If your server already uses `graphql-ws`, make sure to set your `WsProtocol` to [`GraphQLWsProtocol`](#customizing-your-websocket-protocol)
+Subscriptions are long-lived GraphQL read operations that can update their response over time, enabling clients to receive new data as it becomes available.
+
+The GraphQL spec does not specify a particular protocol to use for subscription operations. Apollo Kotlin supports the following protocols:
 
+- **WebSocket,** using one of the following subprotocols:
+  - [subscriptions-transport-ws](https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md) (⚠️ not actively maintained!)
+  - [graphql-ws](https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md)
+  - [appsync](https://docs.aws.amazon.com/appsync/latest/devguide/real-time-websocket-client.html) (also uses `graphql-ws` as [Sec-WebSocket-Protocol](https://datatracker.ietf.org/doc/html/rfc6455#section-1.2))
+* **HTTP,** using [chunked multipart responses](https://github.com/graphql/graphql-over-http/blob/main/rfcs/IncrementalDelivery.md)
 
-Subscriptions are long-lived GraphQL read operations that can update their response over time, enabling clients to receive updates as they occur. They're usually implemented as a connection to a GraphQL server over WebSocket (including in Apollo Kotlin).
+**You must use whichever transport is supported by your GraphQL endpoint.**
 
 You define a subscription in your app just like you define a query, except you use the `subscription` keyword. Here's an example subscription for getting the latest value of a number whenever that number is incremented:
 
@@ -19,18 +24,77 @@ subscription NumberIncremented {
 
 Unlike with queries and mutations, a subscription operation can include only _one_ field of the `Subscription` type. To subscribe to multiple fields, you create multiple subscription operations.
 
-## Setting the WebSocket URL
+## Configuring WebSocket subscriptions
+
+> By default, Apollo Kotlin uses the [`subscriptions-transport-ws`](https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md) protocol for subscriptions via the `SubscriptionWsProtocol` class. **This protocol is no longer actively maintained.** It remains the default for backward compatibility purposes.
+>
+> A future version of Apollo Kotlin will change the default to the newer [`graphql-ws`](https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md) protocol and `GraphQLWsProtocol` class. If your server already uses `graphql-ws`, make sure to [set your `WsProtocol` to `GraphQLWsProtocol`](#customizing-your-websocket-protocol).
 
-Because subscriptions usually use WebSocket instead of HTTP, you might have to customize the URL used:
+To use subscriptions over WebSocket, use `WebSocketNetworkTransport`:
 
 ```kotlin
 val apolloClient = ApolloClient.Builder()
-  .webSocketServerUrl("https://apollo-fullstack-tutorial.herokuapp.com/graphql")
-  .build()
+    .subscriptionNetworkTransport(
+        WebSocketNetworkTransport.Builder()
+            .serverUrl("https://apollo-fullstack-tutorial.herokuapp.com/graphql")
+            .build()
+    )
+    .build()
 ```
 
 > **Note:** Apollo Kotlin supports both `https://` (or `http://`) and `wss://` (or `ws://`) protocols. Internally, `wss://` is renamed to `https://` and which one you use does not matter.
 
+
+### Customizing your WebSocket protocol
+
+By default, Apollo Kotlin uses [subscriptions-transport-ws](https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md) for backward compatibility purposes, but it supports all of the following WebSocket subprotocols:
+
+- [subscriptions-transport-ws](https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md) (⚠️ not actively maintained!)
+- [graphql-ws](https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md)
+- [appsync](https://docs.aws.amazon.com/appsync/latest/devguide/real-time-websocket-client.html) (also uses `graphql-ws` as [Sec-WebSocket-Protocol](https://datatracker.ietf.org/doc/html/rfc6455#section-1.2))
+
+To customize your protocol, use the `WsProtocol` interface. Apollo Kotlin comes with built-in support for the subprotocols above:
+
+| Subprotocol | Class |
+|-------------|-------|
+| subscriptions-transport-ws | `SubscriptionWsProtocol` (default) |
+| graphql-ws | `GraphQLWsProtocol` |
+| appsync | `AppSyncWsProtocol` |
+
+For example, you can configure a `graphql-ws` transport like so:
+
+```kotlin
+val apolloClient = ApolloClient.Builder()
+    .subscriptionNetworkTransport(
+        WebSocketNetworkTransport.Builder()
+            .protocol(GraphQLWsProtocol.Factory()) // highlight-line
+            .serverUrl("https://apollo-fullstack-tutorial.herokuapp.com/graphql")
+            .build()
+    )
+    .build()
+```
+
+### Authentication
+
+Please refer to [this section](../advanced/authentication#authenticating-your-websockets) about authentication with WebSocket.
+
+
+## Configuring HTTP subscriptions
+
+To use HTTP for subscriptions, use `HttpNetworkTransport` like so:
+
+```kotlin
+val apolloClient = ApolloClient.Builder()
+    .subscriptionNetworkTransport(
+        HttpNetworkTransport.Builder()
+            .serverUrl("https://apollo-fullstack-tutorial.herokuapp.com/graphql")
+            .build()
+    )
+    .build()
+```
+
+This is the only configuration required. `HttpNetworkTransport` will use [chunked multipart responses](https://github.com/graphql/graphql-over-http/blob/main/rfcs/IncrementalDelivery.md) for subscription operations and standard POST or GET requests for queries and mutations.
+
 ## Listening to a subscription
 
 After you configure the `NetworkTransport`, use `ApolloClient.subscribe` to open the connection and listen for changes:
@@ -58,30 +122,3 @@ Like queries, subscriptions support partial responses with GraphQL errors, which
 Network errors terminate the `Flow`, and you need to retry to get new updates. Depending on the situation, retrying might open a new WebSocket or restart the subscription.
 
 See also [this section](../advanced/websocket-errors) about WebSocket errors handling.
-
-## Customizing your WebSocket protocol
-
-The GraphQL spec does not specify a particular protocol to use for subscription operations. By default, Apollo Kotlin uses [subscriptions-transport-ws](https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md) for backward compatibility purposes, but it supports all of the following:
-
-* [subscriptions-transport-ws](https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md) (⚠️ not actively maintained!)
-* [graphql-ws](https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md)
-* [appsync](https://docs.aws.amazon.com/appsync/latest/devguide/real-time-websocket-client.html) (also uses `graphql-ws` as [Sec-WebSocket-Protocol](https://datatracker.ietf.org/doc/html/rfc6455#section-1.2))
-
-To customize your protocol, use the `WsProtocol` interface. Apollo Kotlin comes with built-in support for the protocols above:
-
-* subscriptions-transport-ws: `SubscriptionWsProtocol` (default)
-* graphql-ws: `GraphQLWsProtocol`
-* appsync: `AppSyncWsProtocol`
-
-For example, you can configure a `graphql-ws` transport like so:
-
-```kotlin
-val apolloClient = ApolloClient.Builder()
-    .webSocketServerUrl("http://localhost:9090/graphql")
-    .wsProtocol(GraphQLWsProtocol.Factory())
-    .build()
-```
-
-## Authentication
-
-Please refer to [this section](../advanced/authentication#authenticating-your-websockets) about authentication with WebSocket.
diff --git a/gradle/libraries.toml b/gradle/libraries.toml
index ed7809711e..275b9d711b 100644
--- a/gradle/libraries.toml
+++ b/gradle/libraries.toml
@@ -20,13 +20,13 @@ javaPoet = "1.13.0"
 jetbrains-annotations = "23.0.0"
 junit = "4.13.2"
 kotlin-plugin-min = "1.6.0"
-kotlin-plugin = "1.8.20-RC2"
-kotlin-plugin-max = "1.8.20-RC2"
+kotlin-plugin = "1.8.20"
+kotlin-plugin-max = "1.8.20"
 kotlin-stdlib = "1.6.21"
 kotlinx-coroutines = "1.6.4"
 kotlinx-datetime = "0.4.0"
 kotlinx-serialization-runtime = "1.4.1"
-ksp = "1.8.20-RC-1.0.9"
+ksp = "1.8.20-1.0.10"
 ktor = "2.2.2"
 okhttp = "4.9.3"
 rx-android = "2.0.1"
diff --git a/libraries/apollo-adapters/README.md b/libraries/apollo-adapters/README.md
index 63ed566a47..251463099e 100644
--- a/libraries/apollo-adapters/README.md
+++ b/libraries/apollo-adapters/README.md
@@ -10,6 +10,8 @@ A few convenient adapters:
 | `com.apollographql.apollo3.adapter.JavaLocalDateAdapter`        | For `java.time.LocalDate` ISO8601 dates                                                             |
 | `com.apollographql.apollo3.adapter.KotlinxLocalDateTimeAdapter` | For `kotlinx.datetime.LocalDateTime` ISO8601 dates                                                  |
 | `com.apollographql.apollo3.adapter.JavaLocalDateTimeAdapter`    | For `java.time.LocalDateTime` ISO8601 dates                                                         |
+| `com.apollographql.apollo3.adapter.KotlinxLocalTimeAdapter`     | For `kotlinx.datetime.LocalTime` ISO8601 dates                                                      |
+| `com.apollographql.apollo3.adapter.JavaLocalTimeAdapter`        | For `java.time.LocalTime` ISO8601 dates                                                             |
 | `com.apollographql.apollo3.adapter.JavaOffsetDateTimeAdapter`   | For `java.time.OffsetDateTime` ISO8601 dates                                                        |
 | `com.apollographql.apollo3.adapter.DateAdapter`                 | For `java.util.Date` ISO8601 dates                                                                  |
 | `com.apollographql.apollo3.adapter.BigDecimalAdapter`           | For a Multiplatform `com.apollographql.apollo3.adapter.BigDecimal` class holding big decimal values |
diff --git a/libraries/apollo-adapters/api/apollo-adapters.api b/libraries/apollo-adapters/api/apollo-adapters.api
index 1326ce7181..897d551f07 100644
--- a/libraries/apollo-adapters/api/apollo-adapters.api
+++ b/libraries/apollo-adapters/api/apollo-adapters.api
@@ -42,6 +42,14 @@ public final class com/apollographql/apollo3/adapter/JavaLocalDateTimeAdapter :
 	public fun toJson (Lcom/apollographql/apollo3/api/json/JsonWriter;Lcom/apollographql/apollo3/api/CustomScalarAdapters;Ljava/time/LocalDateTime;)V
 }
 
+public final class com/apollographql/apollo3/adapter/JavaLocalTimeAdapter : com/apollographql/apollo3/api/Adapter {
+	public static final field INSTANCE Lcom/apollographql/apollo3/adapter/JavaLocalTimeAdapter;
+	public synthetic fun fromJson (Lcom/apollographql/apollo3/api/json/JsonReader;Lcom/apollographql/apollo3/api/CustomScalarAdapters;)Ljava/lang/Object;
+	public fun fromJson (Lcom/apollographql/apollo3/api/json/JsonReader;Lcom/apollographql/apollo3/api/CustomScalarAdapters;)Ljava/time/LocalTime;
+	public synthetic fun toJson (Lcom/apollographql/apollo3/api/json/JsonWriter;Lcom/apollographql/apollo3/api/CustomScalarAdapters;Ljava/lang/Object;)V
+	public fun toJson (Lcom/apollographql/apollo3/api/json/JsonWriter;Lcom/apollographql/apollo3/api/CustomScalarAdapters;Ljava/time/LocalTime;)V
+}
+
 public final class com/apollographql/apollo3/adapter/JavaOffsetDateTimeAdapter : com/apollographql/apollo3/api/Adapter {
 	public static final field INSTANCE Lcom/apollographql/apollo3/adapter/JavaOffsetDateTimeAdapter;
 	public synthetic fun fromJson (Lcom/apollographql/apollo3/api/json/JsonReader;Lcom/apollographql/apollo3/api/CustomScalarAdapters;)Ljava/lang/Object;
@@ -74,3 +82,11 @@ public final class com/apollographql/apollo3/adapter/KotlinxLocalDateTimeAdapter
 	public fun toJson (Lcom/apollographql/apollo3/api/json/JsonWriter;Lcom/apollographql/apollo3/api/CustomScalarAdapters;Lkotlinx/datetime/LocalDateTime;)V
 }
 
+public final class com/apollographql/apollo3/adapter/KotlinxLocalTimeAdapter : com/apollographql/apollo3/api/Adapter {
+	public static final field INSTANCE Lcom/apollographql/apollo3/adapter/KotlinxLocalTimeAdapter;
+	public synthetic fun fromJson (Lcom/apollographql/apollo3/api/json/JsonReader;Lcom/apollographql/apollo3/api/CustomScalarAdapters;)Ljava/lang/Object;
+	public fun fromJson (Lcom/apollographql/apollo3/api/json/JsonReader;Lcom/apollographql/apollo3/api/CustomScalarAdapters;)Lkotlinx/datetime/LocalTime;
+	public synthetic fun toJson (Lcom/apollographql/apollo3/api/json/JsonWriter;Lcom/apollographql/apollo3/api/CustomScalarAdapters;Ljava/lang/Object;)V
+	public fun toJson (Lcom/apollographql/apollo3/api/json/JsonWriter;Lcom/apollographql/apollo3/api/CustomScalarAdapters;Lkotlinx/datetime/LocalTime;)V
+}
+
diff --git a/libraries/apollo-adapters/src/commonMain/kotlin/com/apollographql/apollo3/adapter/KotlinxTimeAdapters.kt b/libraries/apollo-adapters/src/commonMain/kotlin/com/apollographql/apollo3/adapter/KotlinxTimeAdapters.kt
index 731d2dfbc4..41f75c5e45 100644
--- a/libraries/apollo-adapters/src/commonMain/kotlin/com/apollographql/apollo3/adapter/KotlinxTimeAdapters.kt
+++ b/libraries/apollo-adapters/src/commonMain/kotlin/com/apollographql/apollo3/adapter/KotlinxTimeAdapters.kt
@@ -7,6 +7,7 @@ import com.apollographql.apollo3.api.json.JsonWriter
 import kotlinx.datetime.Instant
 import kotlinx.datetime.LocalDate
 import kotlinx.datetime.LocalDateTime
+import kotlinx.datetime.LocalTime
 
 /**
  * An [Adapter] that converts an ISO 8601 String like "2010-06-01T22:19:44.475Z" to/from
@@ -55,3 +56,19 @@ object KotlinxLocalDateAdapter : Adapter<LocalDate> {
     writer.value(value.toString())
   }
 }
+
+/**
+ * An [Adapter] that converts an ISO 8601 String like "14:35:00" to/from
+ * a [kotlinx.datetime.LocalDate]
+ *
+ * It requires Android Gradle plugin 4.0 or newer and [core library desugaring](https://developer.android.com/studio/write/java8-support#library-desugaring).
+ */
+object KotlinxLocalTimeAdapter : Adapter<LocalTime> {
+  override fun fromJson(reader: JsonReader, customScalarAdapters: CustomScalarAdapters): LocalTime {
+    return LocalTime.parse(reader.nextString()!!)
+  }
+
+  override fun toJson(writer: JsonWriter, customScalarAdapters: CustomScalarAdapters, value: LocalTime) {
+    writer.value(value.toString())
+  }
+}
diff --git a/libraries/apollo-adapters/src/jvmMain/kotlin/com/apollographql/apollo3/adapter/JavaTimeAdapters.kt b/libraries/apollo-adapters/src/jvmMain/kotlin/com/apollographql/apollo3/adapter/JavaTimeAdapters.kt
index 476e317557..94531fdbb9 100644
--- a/libraries/apollo-adapters/src/jvmMain/kotlin/com/apollographql/apollo3/adapter/JavaTimeAdapters.kt
+++ b/libraries/apollo-adapters/src/jvmMain/kotlin/com/apollographql/apollo3/adapter/JavaTimeAdapters.kt
@@ -7,6 +7,7 @@ import com.apollographql.apollo3.api.json.JsonWriter
 import java.time.Instant
 import java.time.LocalDate
 import java.time.LocalDateTime
+import java.time.LocalTime
 import java.time.OffsetDateTime
 import java.time.format.DateTimeFormatter
 
@@ -85,3 +86,21 @@ object JavaOffsetDateTimeAdapter : Adapter<OffsetDateTime> {
     writer.value(value.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME))
   }
 }
+
+/**
+ * An [Adapter] that converts a time to/from [java.time.LocalTime]
+ *
+ * Examples:
+ * - "14:35:00"
+ *
+ * It requires Android Gradle plugin 4.0 or newer and [core library desugaring](https://developer.android.com/studio/write/java8-support#library-desugaring).
+ */
+object JavaLocalTimeAdapter : Adapter<LocalTime> {
+  override fun fromJson(reader: JsonReader, customScalarAdapters: CustomScalarAdapters): LocalTime {
+    return LocalTime.parse(reader.nextString())
+  }
+
+  override fun toJson(writer: JsonWriter, customScalarAdapters: CustomScalarAdapters, value: LocalTime) {
+    writer.value(value.toString())
+  }
+}
diff --git a/libraries/apollo-compose-paging-support/build.gradle.kts b/libraries/apollo-compose-paging-support/build.gradle.kts
index aa782cc2f9..08400a3c6b 100644
--- a/libraries/apollo-compose-paging-support/build.gradle.kts
+++ b/libraries/apollo-compose-paging-support/build.gradle.kts
@@ -40,7 +40,7 @@ tasks.withType(KotlinCompile::class.java).configureEach {
   kotlinOptions {
     freeCompilerArgs += listOf(
         "-P",
-        "plugin:androidx.compose.compiler.plugins.kotlin:suppressKotlinVersionCompatibilityCheck=1.8.20-RC2"
+        "plugin:androidx.compose.compiler.plugins.kotlin:suppressKotlinVersionCompatibilityCheck=1.8.20"
     )
   }
 }
diff --git a/libraries/apollo-compose-support/build.gradle.kts b/libraries/apollo-compose-support/build.gradle.kts
index 6b45dc5e78..e643c90956 100644
--- a/libraries/apollo-compose-support/build.gradle.kts
+++ b/libraries/apollo-compose-support/build.gradle.kts
@@ -35,7 +35,7 @@ tasks.withType(KotlinCompile::class.java).configureEach {
   kotlinOptions {
     freeCompilerArgs += listOf(
         "-P",
-        "plugin:androidx.compose.compiler.plugins.kotlin:suppressKotlinVersionCompatibilityCheck=1.8.20-RC2"
+        "plugin:androidx.compose.compiler.plugins.kotlin:suppressKotlinVersionCompatibilityCheck=1.8.20"
     )
   }
 }
diff --git a/scripts/release.main.kts b/scripts/release.main.kts
index d54938a9a9..6dbd3fcb9b 100755
--- a/scripts/release.main.kts
+++ b/scripts/release.main.kts
@@ -19,12 +19,15 @@ check(getCurrentVersion().endsWith("-SNAPSHOT")) {
 }
 
 check(args.size == 1) {
-  "tag.main.kts [version to tag]"
+  "release.main.kts [version to release]"
 }
 val versionToRelease = args[0]
 val nextSnapshot = getNextSnapshot(versionToRelease)
 
 val startBranch = runCommand("git", "symbolic-ref", "--short", "HEAD")
+check(startBranch == "main" || startBranch.startsWith("release-")) {
+  "You must be on the main branch or a release branch to make a release"
+}
 
 while (true) {
   println("Current version is '${getCurrentVersion()}'.")
@@ -46,7 +49,7 @@ setCurrentVersion(versionToRelease)
 setVersionInDocs(versionToRelease, nextSnapshot)
 runCommand("git", "commit", "-a", "-m", "release $versionToRelease")
 runCommand("git", "push", "origin", releaseBranchName)
-runCommand("gh", "pr", "create", "--fill")
+runCommand("gh", "pr", "create", "--base", startBranch, "--fill")
 
 println("Press enter to merge the release PR")
 readLine()
@@ -70,7 +73,7 @@ runCommand("git", "checkout", "-b", bumpVersionBranchName)
 setCurrentVersion(nextSnapshot)
 runCommand("git", "commit", "-a", "-m", "version is now $nextSnapshot")
 runCommand("git", "push", "origin", bumpVersionBranchName)
-runCommand("gh", "pr", "create", "--fill")
+runCommand("gh", "pr", "create", "--base", startBranch, "--fill")
 
 println("Press enter to merge the bump version PR")
 readLine()


Test patch:
diff --git a/libraries/apollo-adapters/src/jvmTest/kotlin/JavaTimeAdaptersTest.kt b/libraries/apollo-adapters/src/jvmTest/kotlin/JavaTimeAdaptersTest.kt
index c062f13c69..6cde061186 100644
--- a/libraries/apollo-adapters/src/jvmTest/kotlin/JavaTimeAdaptersTest.kt
+++ b/libraries/apollo-adapters/src/jvmTest/kotlin/JavaTimeAdaptersTest.kt
@@ -2,10 +2,12 @@ import com.apollographql.apollo3.adapter.DateAdapter
 import com.apollographql.apollo3.adapter.JavaInstantAdapter
 import com.apollographql.apollo3.adapter.JavaLocalDateAdapter
 import com.apollographql.apollo3.adapter.JavaLocalDateTimeAdapter
+import com.apollographql.apollo3.adapter.JavaLocalTimeAdapter
 import com.apollographql.apollo3.adapter.JavaOffsetDateTimeAdapter
 import com.apollographql.apollo3.adapter.KotlinxInstantAdapter
 import com.apollographql.apollo3.adapter.KotlinxLocalDateAdapter
 import com.apollographql.apollo3.adapter.KotlinxLocalDateTimeAdapter
+import com.apollographql.apollo3.adapter.KotlinxLocalTimeAdapter
 import com.apollographql.apollo3.api.Adapter
 import com.apollographql.apollo3.api.CustomScalarAdapters
 import com.apollographql.apollo3.api.json.BufferedSourceJsonReader
@@ -83,6 +85,15 @@ class JavaTimeAdaptersTest {
     assertEquals("2010-06-01", JavaLocalDateAdapter.toJson(localDate))
   }
 
+  @Test
+  fun localTime() {
+    val localTime = JavaLocalTimeAdapter.fromJson("14:35:20")
+    assertEquals(14, localTime.hour)
+    assertEquals(35, localTime.minute)
+    assertEquals(20, localTime.second)
+    assertEquals("14:35:20", JavaLocalTimeAdapter.toJson(localTime))
+  }
+
   @Test
   fun kotlinxInstant() {
     var instant = KotlinxInstantAdapter.fromJson("2010-06-01T22:19:44.475Z")
@@ -109,4 +120,13 @@ class JavaTimeAdaptersTest {
     assertEquals("2010-06-01", KotlinxLocalDateAdapter.toJson(localDate))
   }
 
+  @Test
+  fun kotlinxLocalTime() {
+    val localTime = KotlinxLocalTimeAdapter.fromJson("14:35:20")
+    assertEquals(14, localTime.hour)
+    assertEquals(35, localTime.minute)
+    assertEquals(20, localTime.second)
+    assertEquals("14:35:20", KotlinxLocalTimeAdapter.toJson(localTime))
+  }
+
 }