Apollo Android Versions Save

:robot: Β A strongly-typed, caching GraphQL client for the JVM, Android, and Kotlin multiplatform.

v3.8.2

11 months ago

A maintenance release with bugfixes, mostly around WebSockets and subscriptions as well as a LocalTime adapter and options to work with operation manifests.

Huge THANK YOU to @baconz, @AlexHartford, @Oleur for the love they put in WebSocket contributions as well as @Jephuff for their first contribution πŸ’™ .

πŸ‘·β€ All changes

  • add Service.operationManifestFormat (#4981)
  • WebSockets: Fix fan out in websocket network transport (#4972)
  • Test: Throw inside flow in MapTestNetworkTransport (#4982)
  • Doc: Add Optional.Absent in documentation (#4979)
  • Doc: clarify that operationBased codegen is the recommendation (#4966)
  • AST: use existing as the base for copying enum values (#4943)
  • Cache: Fix deleting records in the SqlNormalizedCache with cascade-true (#4938)
  • Compiler: Fix deprecated input field usage false positive (#4935)
  • Doc: Clarify KDoc of watch() (#4914)
  • WebSockets: allow changing the serverUrl of WebSocketNetworkTransport (#4885)
  • WebSockets: accept connectionPayload lambda instead of static auth (#4855)
  • Add LocalTime adapter for Java and Kotlin (#4829)
  • Doc: Add a section about the operationBased codegen (3.x) (#4940)

v4.0.0-alpha.1

1 year ago

This release is the first alpha of the next major version of Apollo Kotlin: 4.0.0.

This version is under development, but we want to give you a preview of what's coming, and get your early feedback. Please see the roadmap for more details about the release plan.

While version 3 changed a lot of APIs compared to version 2, version 4 should be mostly compatible with version 3. Version 4 will even keep the same package name in order to keep the number of changes low.

The error handling has changed but besides that, the version should be mostly compatible. Please consult the migration guide for all the details.

We would love to hear your feedback on this release. Please report any issues, questions, ideas, or comments on the issue tracker.

πŸ› οΈ Android Studio / IntelliJ plugin

See this page for installation instructions and more information.

This plugin for Android Studio and IntelliJ helps you work with Apollo Kotlin. It provides the following features:

  • Automatic code generation
  • Integration with the GraphQL IntelliJ Plugin
  • Navigation to GraphQL definitions
  • Helpers to migrate your project to the latest version

⚑️ ApolloResponse.exception for error handling

Error handling is an important aspect of a client library and we found it could benefit from some changes.

In particular we are moving away from throwing exceptions:

  • This improves dealing with Flows as they will no longer terminate on errors
  • It helps grouping all error handling (network, GraphQL, caching) in the same area of your code

To that effect, there is now an ApolloResponse.exception : ApolloException property, which will be present when a network error or cache miss have occurred, or when GraphQL errors are present:

val data = response.data
when {
  data != null -> {
    println("The server returned data: $data")
  }
  else -> {
    // An error happened, check response.exception for more details or just display a generic error 
    when (response.exception) {
      is ApolloGraphQLException -> // do something with exception.errors
      is ApolloHttpException -> // do something with exception.statusCode
      is ApolloNetworkException -> TODO()
      is ApolloParseException -> TODO()
      else -> // generic error
    }
  }
}

To ease the migration to v4, the v3 behavior can be restored by calling ApolloClient.Builder.useV3ExceptionHandling(true).

Feedback about this change is welcome on issue 4711.

β˜•οΈ apollo-runtime-java for better Java support

As v3 has a Kotlin and Coroutines first API, using it from Java is sometimes impractical or not idiomatic. That is why in v4 we are introducing a new Java runtime, written in Java, which provides a Java friendly API. It is callback based and doesn't depend on a third-party library like Rx.

To use it in your project, instead of the usual runtime (com.apollographql.apollo3:apollo-runtime), use the following dependency in your build.gradle[.kts] file:

implementation("com.apollographql.apollo3:apollo-runtime-java")

Then you can use the ApolloClient class from Java:

ApolloClient apolloClient = new ApolloClient.Builder()
  .serverUrl("https://...")
  .build();

apolloClient
  .query(MyQuery.builder().build())
  .enqueue(new ApolloCallback<MyQuery.Data>() {
      @Override public void onResponse(@NotNull ApolloResponse<MyQuery.Data> response) {
        System.out.prinitln(response.getData());
      }
  });

A few examples can be found in the tests.

πŸ”ƒ Multi-module: automatic detection of used types

In multi-module projects, by default, all the types of an upstream module are generated because there is no way to know in advance what types are going to be used by downstream modules. For large projects this can lead to a lot of unused code and an increased build time.

To avoid this, in v3 you could manually specify which types to generate by using alwaysGenerateTypesMatching. In v4 this can now be computed automatically by detecting which types are used by the downstream modules.

To enable this, add the "opposite" link of dependencies with isADependencyOf().

// schema/build.gradle.kts
apollo {
  service("service") {
    packageName.set("schema")

    // Enable generation of metadata for use by downstream modules 
    generateApolloMetadata.set(true)

    // More options...

    // Get used types from the downstream module
    isADependencyOf(project(":feature1"))

    // You can have several downstream modules
    isADependencyOf(project(":feature2"))
  }
}
// feature1/build.gradle.kts
apollo {
  service("service") {
    packageName.set("feature1")
    
    // Get the generated schema types (and fragments) from the upstream schema module 
    dependsOn(project(":schema")) 
  }
}

v3.8.1

1 year ago

This patch release contains 2 bug fixes.

πŸ‘·β€ All changes

  • Add ignoreApolloClientHttpHeaders (#4838)
  • Download introspection: handle GraphQL errors (#4861)

v3.8.0

1 year ago

This release adds two new artifacts that contain Jetpack compose extensions amongst other fixes.

πŸ’™οΈ External contributors

Many thanks to @slinstacart and @hbmartin for their contributions to this release!

✨ [New] Jetpack compose extension (#4802)

You can now use the apollo-compose-support artifact:

// build.gradle.kts
dependencies {
  implementation("com.apollographql.apollo3:apollo-compose-support")
}

This artifact contains the toState() and watchAsState() extensions:

/**
 * A stateful composable that retrieves your data
 */
@OptIn(ApolloExperimental::class)
@Composable
fun LaunchDetails(launchId: String) {
    val response by apolloClient.query(LaunchDetailsQuery(launchId)).toState()
    val r = response
    when {
        r == null -> Loading() // no response yet
        r.exception != null -> ErrorMessage("Oh no... A network error happened: ${r.exception!!.message}")
        r.hasErrors() -> ErrorMessage("Oh no... A GraphQL error happened ${r.errors[0].message}.")
        else -> LaunchDetails(r.data!!, navigateToLogin)
    }
}

/**
 * A stateless composable that displays your data
 */
@Composable
private fun LaunchDetails(
        data: LaunchDetailsQuery.Data,
) {
  // Your UI code goes here
}

If you are working with paginated data, you can also add apollo-compose-paging-support to your dependencies:

// build.gradle.kts
dependencies {
  implementation("com.apollographql.apollo3:apollo-compose-paging-support")
}

This artifact contains a helper function to create androidx.pagin.Pager instances (androix documentation):

@OptIn(ApolloExperimental::class)
@Composable
fun LaunchList(onLaunchClick: (launchId: String) -> Unit) {
  val lazyPagingItems = rememberAndCollectPager<LaunchListQuery.Data, LaunchListQuery.Launch>(
          config = PagingConfig(pageSize = 10),
          appendCall = { response, loadSize ->
            if (response?.data?.launches?.hasMore == false) {
              // No more pages
              null
            } else {
              // Compute the next call from the current response
              apolloClient.query(
                      LaunchListQuery(
                              cursor = Optional.present(response?.data?.launches?.cursor),
                              pageSize = Optional.present(loadSize)
                      )
              )
            }
          },
          getItems = { response ->
            // Compute the items to be added to the page from the current response
            if (response.hasErrors()) {
              Result.failure(ApolloException(response.errors!![0].message))
            } else {
              Result.success(response.data!!.launches.launches.filterNotNull())
            }
          },
  )
  
  // Use your paging items:
  if (lazyPagingItems.loadState.refresh is LoadState.Loading) {
    Loading()
  } else {
    LazyColumn {
      items(lazyPagingItems) { launch ->
        // Your UI code goes here
      }
      item {
        when (val append = lazyPagingItems.loadState.append) {
          is LoadState.Error -> // Add error indicator here 
          LoadState.Loading -> // Add loading indicator here
        }
      }
    }
  }
}

As always, feedback is very welcome. Let us know what you think of the feature by either opening an issue on our GitHub repo , joining the community or stopping by our channel in the KotlinLang Slack(get your invite here).

✨ [New] Gradle plugin: run codegen after gradle sync

If you import a new project or run a Gradle sync, your GraphQL models are now automatically generated so that the IDE can find the symbols and your files do not show red underlines. This takes into account Gradle up-to-date checks and it should be pretty fast. If you want to opt-out, you can do so with generateSourcesDuringGradleSync.set(false):

apollo {
  // Enable automatic generation of models during Gradle sync (default)
  generateSourcesDuringGradleSync.set(true)

  // Or disable automatic generation of models to save on your Gradle sync times
  generateSourcesDuringGradleSync.set(false)

  service("api") {
    // Your  GraphQL configuration
  }
}

πŸ‘·β€ All changes

  • Allow to add HTTP headers on top of ApolloClient ones (#4754)
  • Kotlin 1.8 (#4776)
  • Move cache creation outside the main thread (#4781)
  • Cache: ignore hardcoded @include(if: false) directives (#4795)
  • Add % to reserved characters to encode in URL (#4804)
  • First drop of experimental Compose support libraries (#4783)
  • Consider variable default values with @skip/@include/@defer (#4785)
  • Gradle plugin: run codegen after gradle sync (#4796)
  • Allow custom SqlDriver (#4806)
  • Multipart subscriptions (#4768, #4807, #4738)
  • GQLNode.print for type extensions (#4814)

v3.7.5

1 year ago

This release contains a bunch of fixes and minor improvements.

Many thanks to @adubovkin and @ndwhelan for contributing to the project, and to all the people who sent feedback! πŸ’œ

πŸ› Bug fixes

  • Fix CacheFirst + emitCacheMisses(true) (#4708)
  • Fix content-length for the String constructor in MockServer (#4683)
  • Fix same shape validation (#4641)
  • Add a @JsName annotation to Operation.name() (#4643)
  • Remove unreachable lenient mode from JSON writer/reader (#4656)
  • Remove deprecation on connectToAndroidSourceSet because alternative have issues too (#4674)
  • Fail fast if trying to set browser WebSocket headers (#4676)
  • Make sure the fallback type is always last (#4692)
  • Fix normalizing data when using @include or @skip with default values (#4700)
  • Java codegen: fix h nameclash in hashCode (#4715)

πŸ” Deprecation warnings (#4610)

As we're starting to work on version 4.0 which will drop support for the "compat" codegen and a few other options dating from version 2, we've added in this release some deprecation warnings that will warn when they're used. If you haven't done already, now is a good time to migrate!

πŸ‘·β€ Other changes

  • Data builders: support for @skip and @include (#4645)
  • SchemaDownloader: Update to download deprecated input fields (#4678)
  • Include deprecated arguments and directives in introspection (#4702)
  • Update JS dependencies (#4634)

v3.7.4

1 year ago

This release contains a handful of bug fixes and improvements.

πŸ‘·β€ All changes

  • Kotlin codegen: automatically escape 'companion' fields (#4630)
  • Runtime: fix a case where APQ + cache could be misconfigured and throw an exception (#4628)
  • Update KTOR to 2.2.2 (#4627)
  • Allow having an empty last part in multipart (#4598)
  • Add data builders for unknown interface and union types (#4613)
  • Http cache: don't access the disk from the main thread in error case (#4606)

v3.7.3

1 year ago

This release contains a handful of bug fixes and improvements, and also discontinues the legacy JS artifacts.

Many thanks to @StefanChmielewski and @chao2zhang for contributing to the project! 🧑

βš™οΈ Removed JS legacy artifacts (#4591)

Historically, Kotlin Multiplatform has had 2 formats of JS artifacts: Legacy and IR, and Apollo Kotlin has been publishing both. However, the Legacy format is about to be deprecated with Kotlin 1.8 and moreover we've seen issues when using the Legacy artifact in the browser. That is why starting with this release, only the IR artifacts will be published. Please reach out if this causes any issue in your project.

πŸ‘·β€ All changes

  • Add GraphQLWsProtocol.Factory.webSocketPayloadComposer (#4589)
  • Escape "Companion" in enum value names (#4558)
  • Un-break Gradle configuration cache in multi module cases (#4564)
  • Move computing the alwaysGenerateTypesMatching to execution time (#4578)
  • Log deprecation warning instead of printing (#4561)
  • Escape spaces when url encoding, for Apple (#4567)
  • Fix providing linker flags to the Kotlin compiler with KGP 1.8 (#4573)
  • Use service {} in all messages/docs (#4572)
  • Print all duplicate types at once (#4571)
  • Fix JavaPoet formatting (#4584)
  • Don't publish legacy js artifacts (#4591)

v3.7.2

1 year ago

This patch release brings a few fixes.

Many thanks to @davidshepherd7, @chao2zhang, @agrosner, @MyDogTom, @doucheng, @sam43 and @vincentjames501, for helping improve the library! πŸ™

πŸ”Žβ€ Explicit service declaration

Apollo Kotlin can be configured to work with multiple services and have the package name, schema files location, and other options specified for each of them. When using a single service however it is possible to omit the service block and set the options directly in the apollo block - in that case, a default service named service is automatically defined.

While this saves a few lines, it relies on Gradle afterEvaluate {} block that makes the execution of the plugin less predictable and more subject to race conditions with other plugins (see here for an example).

What's more, as we move more logic to build time, the name of the service is going to be used more and more in generated code. Since explicit is better than implicit, mandating that service name sounds a good thing to do and a warning is now printed if you do not define your service name.

To remove the warning, embed the options into a service block:

apollo {
+ service("service") {
    packageName.set("com.example")
    // ...
+ }
}

πŸ‘·β€ All changes

  • Improve "duplicate type" message by using the full path of the module (#4527)
  • Fix using apollo2 and apollo3 Gradle plugins at the same time (#4528)
  • Add a warning when using the default service (#4532)
  • Fix Java codegen in synthetic fields when using optionals (#4533)
  • Make canBeBatched and httpHeaders orthogonal (#4534)
  • Fix item wrongly removed from http cache when error in subscriptions (#4537)
  • Do not throw on graphql-ws errors and instead return the errors in ApolloResponse (#4540)
  • graphql-ws: send pong while waiting for connection_ack (#4555)

v3.7.1

1 year ago

A patch release with a few fixes.

πŸ‘·β€ All changes

  • πŸ‘·Data Builders: make DefaultFakeResolver open and stateless (#4468)
  • Kotlin 1.7.21 (#4511)
  • Introduce HttpFetchPolicyContext (#4509)
  • Fix usedCoordinates on interfaces (#4506)

Many thanks to @Holoceo, @juliagarrigos, @davidshepherd7 and @eduardb for the feedbacks πŸ’™

v2.5.14

1 year ago

A patch release to fix an issue where the ApolloCall could end up in a bad state. Many thanks to @WilliamsDHI for diving into this πŸ’™!

πŸ‘·β€ All changes

  • update terminate and responseCallback methods to return Optional.absent() in IDLE/TERMINATED state (#4383)