Β A strongly-typed, caching GraphQL client for the JVM, Android, and Kotlin multiplatform.
MIT License
Bot releases are visible (Hide)
Version 3.8.3 is a maintenance release with two new convenience APIs and a Kotlin update. New developments happen in the 4.x versions.
Note: because Apollo Kotlin now depends on kotlin-stdlib version 1.9, you need the 1.8+ Kotlin compiler to compile your project.
ApolloClient.Builder(ApolloHttpCache)
(#5638) (#5640)buildPostBody
to write operation extensions (#5631).exception
(#5018)IOException
when calling ApolloHttpCache.remove
(#5730)PackageNameGenerator
and OperationOutputGenerator
are deprecated. See the documentation page about Apollo compiler plugins for more details.@semanticNonNull
or @catch
you should bump your @link
directives to use 0.3
. See the nullability documentation page for more details.https://go.apollo.dev/ij-plugin-snapshots
to get the latest weekly snapshots. (#5600)Many thanks to @ribafish, @molundb, @mboyd1993, @rohandhruva and @baconz for their help in this release π!
NetworkMonitor
(#5690)ApolloClient.retryOnError(Boolean)
(#5685)@catch
on fieldDefinitions, interfaces and objects (#5623)X-APOLLO-OPERATION-NAME
, X-APOLLO-OPERATION-ID
and the multipart boundary (#5533)generateAsInternal
code (#5526)4.0.0-beta.3
(#5452)Published by BoD 10 months ago
This release adds initial support for WebAssembly by adding the wasmJs
target.
Executing queries/mutations is working but this target is
experimental (Kotlin/Wasm is Alpha) and has multiple limitations:
Downloading a schema from introspection (./gradlew downloadServiceSchemaFromIntrospection
) got broken in the previous
release (#5449) and is now fixed.
Published by martinbonnin 11 months ago
Many thanks @chris-hatton and @sdfgsdfgd for contributing this version π
The normalized cache viewer can now display the contents of your in-memory cache. To do so, it relies on a
debug server that you need to run in your debug builds:
val apolloClient = ApolloClient.Builder()
.serverUrl("https://example.com/graphql")
.build()
if (BuildConfig.DEBUG) {
ApolloDebugServer.registerApolloClient(apolloClient)
}
You can read more about it in the "Apollo debug server" documentation page.
@catch
and @semanticNonNull
support@catch
makes it possible to model GraphQL errors as FieldResult
Kotlin classes giving you inline access to errors:
query GetUser {
user {
id
# map name to FieldResult<String?> instead of stopping the parsing
name @catch
avatarUrl
}
}
@semanticNonNull
is a better @nonnull
. @semanticNonNull
makes it possible to mark a field as null only on error. The matching Kotlin property is then generated as non-null:
# mark User.name as semantically non-null
extend type User @semanticNonNull(field: "name")
Both those directives are experimental and require opt-in of the nullability directives
You can read more about them in the "handle nullability" documentation page.
@oneOf
support@oneOf
introduces input polymorphism to GraphQL:
input PetInput @oneOf {
cat: CatInput
dog: DogInput
fish: FishInput
}
input CatInput { name: String!, numberOfLives: Int }
input DogInput { name: String!, wagsTail: Boolean }
input FishInput { name: String!, bodyLengthInMm: Int }
type Mutation {
addPet(pet: PetInput!): Pet
}
With @oneOf
, only one of cat
, dog
or fish
can be set.
@oneOf
support is automatically enabled if your schema has the @oneOf
directive definition.
You can read more about it in the @oneOf
RFC
[all] @oneOf
support (#5394, #5388)
[all] @catch
and @semanticNonNull
support (#5405)
[all] Take default values into account when computing field cache keys (#5384)
[all] Bump Kotlin to 2.0.0-Beta1 (#5373)
[IJ Plugin] Add 'Input class constructor issue' inspection (#5427)
[IJ plugin] Update v3->v4 migration following API tweaks (#5421)
[IJ Plugin] Report invalid oneOf
input object builder uses (#5416)
[IJ Plugin] Add inspection for @oneOf
input type constructor invocation (#5395)
[IJ plugin] Make the refresh button work with all normalized cache sources. (#5400)
[IJ Plugin] Cache viewer: take numbers into account in key sorting (#5396)
[IJ Plugin] Bump pluginUntilBuild to 233 (#5377)
[IJ Plugin] Telemetry: don't use a libraries changed listener (#5361)
[IJ Plugin] Cache viewer: add cache size to selector (#5357)
[IJ plugin] Use apollo-debug-server to retrieve normalized caches (#5348)
[IJ plugin] Cache viewer: "Pull from Device" modal dialog instead of action menu (#5333)
[IJ Plugin] Fix v3->v4 migration with ApolloCompositeException (#5330)
[runtime] remove some of the ApolloResponse.Builders (#5426)
[runtime] Add a few symbols as ERROR deprecation for the migration (#5422)
[runtime] Add executeV3 + toFlowV3 (#5417)
[runtime] Revive dataAssertNoErrors (#5419)
[runtime] Allow no data and no exception in case of GraphQL errors (#5408)
[runtime] Expose ExecutionContext to HttpEngine and add OkHttp helpers (#5383)
[runtime] Improve deprecation messages (#5411)
[runtime] Go back to just one Adapter class (#5403)
[runtime] Fix Optional.getOrElse (#5399)
[compiler] Remove kotlin-labs-0.1 directives (#5404)
[compiler] Throw a better exception than NullPointerException if a value is missing (#5402)
[compiler] ExecutableValidationResult is returned by validateAsExecutable() and cannot be @ApolloInternal (#5406)
[compiler] Rework the IrType hierarchy (#5392)
[compiler] remove CCN (#5387)
[compiler] Remove antlr (#5336)
[compiler] Tweak description javadoc, there is no need to use the same escaping as Kotlin (#5424)
[mockserver] Support setting port for Apollo MockServer (#5389)
[mockserver] Add WebSocket support to the MockServer (#5334)
[tools] Implement 2-step introspection (#5371)
[apollo-execution] Allow to pass arguments to the root types (#5352)
[apollo-ksp] Initial support for interfaces (#5351)
Published by BoD 12 months ago
We're continuing to progress towards the stable release of Apollo Kotlin v4 with this 2nd beta, which contains a few bug fixes and a new normalized cache viewer in the IDE plugin.
This is a great time to try out the new version and report any issues you might find!
The IDE plugin now has a graphical tool to inspect a normalized cache database. It lets you browse the records and see their contents.
This is useful to debug cache issues, or to understand how the normalized cache works.
The tool is available from View
| Tool Windows
| Apollo Normalized Cache
.
More information about the plugin can be found here.
Published by BoD about 1 year ago
The first beta of the next major version of Apollo Kotlin is here!
While there still may be a few API changes before the stable release, we are getting close and this is a great time to try out the new version and report any issues you might find!
Many thanks to @baconz and @hbmartin for their awesome contributions to this release!
The GraphQL community is working hard at making it easier to work with nullability in GraphQL.
In Apollo Kotlin, it is now possible to change the nullability of fields and list elements at the schema level using schema extensions. This is useful if you believe the schema made a field nullable for error reasons only and you don't want to handle those errors. In these cases, the whole query will return as an error.
Given the following SDL:
# schema.graphqls
type Query {
random: Int
list: [String]
required: Int!
}
You can extend it like so:
# extra.graphqls
extend type Query {
# make random non-nullable
random: Int!
# make list and list items non-nullable
list: [String!]!
# make required nullable
required: Int
# add a new field
new: Float
}
generateMethods
option to control which model methods are generated (#5212)By default all Kotlin models, operations, fragments, and input objects are generated as data classes. This means that the Kotlin compiler will
auto-generate toString
, equals
hashCode
, copy
and componentN
. If you don't think you need all of those
methods, and/or you are worried about the size of the generated code, you can now choose which methods to generate with the generateMethods
option:
apollo {
service("service") {
// Generates equals/hashCode
generateMethods.set(listOf("equalsHashCode"))
// Also generates toString, equals, and hashcode
generateMethods.set(listOf("equalsHashCode", "toString"))
// Only generates copy
generateMethods.set(listOf("copy"))
// Generates data classes (the default)
generateMethods.set(listOf("dataClass"))
}
}
Enum.values()
is no longer recommended when using Kotlin 1.9+ and the generated code now uses entries
instead (#5208)Optional<V>.getOrThrow()
when V is nullable (#5192)useV3ExceptionHandling
only throws when there are no errors populated (#5231)urlEncode
algorithm (#5234)keyFields
on non-existent fields (#5215)mergeExtensions
and toFullSchemaGQLDocument
(#5162)Optional<V>.getOrThrow()
when V is nullable (#5192)registerOperations {}
(#5196)generateMethods
options to control which methods are generated on "data" classes (#5212)A lot of additions to the IntelliJ plugin as well as a new GraphQL parser, a new Ktor multiplatform engine and more!
Apollo Kotlin wouldn't be where it is today without the awesome feedback, discussions and contributions from community members. Specifically in this release, we want to give a huge THANK YOU to: @Emplexx, @sonatard, @yt8492, @mayakoneval, @Meschreiber, @pcarrier and @ashare80
The IntelliJ plugin now detects unused fields in your queries and greys them out:
https://github.com/apollographql/apollo-kotlin/assets/372852/6a573a78-4a07-4294-8fa5-92a9ebb02e6c
The IntelliJ plugin can migrate most of your codebase to v4. To try it out, go to:
Tools
-> Apollo
-> Migrate to Apollo Kotlin 4
Because Kotlin is such a rich language and we can't account for all possible ways to configure your build, you might have to do some manual tweaks after the migration. But the plugin should handle most of the repetitive tasks of migrating.
If you configured introspection, you can now download your schema directly from IntelliJ
The IntelliJ plugin now has its own dedicated documentation page.
Consult it to find out everything you can do with the plugin as well as installation instructions.
Apollo AST, the GraphQL parser powering Apollo Kotlin is now a manually written recursive descent parser, compared to an automatically generated Antlr parser before.
Benchmarks show a x2 to x3 speed improvement and the parser also now supports all platforms Apollo Kotlin supports.
Client Controlled Nullability (CCN) is a GraphQL specification RFC aiming at making it easier to work with GraphQL in type safe languages like Kotlin and Swift.
To use CCN, use the !
and ?
CCN modifiers in your queries:
query GetUser {
user {
id
# name is required to display the user
name!
# phoneNumber is optional
phoneNumber?
}
}
The RFC is still in early stages and requires server support. The API and final shape of the RFC might still change. By adding support in Apollo Kotlin, we're hoping to unblock potential users and gather real life feedbacks helping the proposal move forward.
Apollo Kotlin now ships a apollo-engine-ktor
that you can use to replace the default HTTP and WebSocket engines of ApolloClient. To use it, add apollo-engine-ktor
to your dependencies:
dependencies {
implementation("com.apollographql.apollo3:apollo-engine-ktor")
}
And configure your client to use it:
val apolloClient = ApolloClient.Builder()
.serverUrl("https://example.com/graphql")
.httpEngine(KtorHttpEngine())
.webSocketEngine(KtorWebSocketEngine())
.build()
generateInputBuilders
(#5146)For Kotlin codegen, Apollo Kotlin relied on constructors with default arguments. While this works well in most cases, default arguments lack the ability to distinguish between null
and absent
meaning you have to wrap your values in Optional
before passing them to your constructor. If you had a lot of values, it could be cumbersome:
val input = SignupMemberInput(
dob = Utils.changeDateFormat(user.dobMMDDYYYY, "MM/dd/yyyy", "yyyy-MM-dd"),
firstName = Optional.Present(user.firstName),
lastName = user.lastName,
ssLast4 = Optional.Present(user.ssnLastFour),
email = user.email,
cellPhone = Optional.Present(user.phone),
password = user.password,
acceptedTos = true,
formIds = Optional.Present(formIds),
medium = Optional.Present(ConsentMediumEnum.android)
)
To generate Kotlin Builders, set generateInputBuilders
to true in your Gradle file:
apollo {
service("api") {
packageName.set("com.example")
generateInputBuilders.set(true)
}
}
With Builders, the same above code can be written in a more fluent way:
val input = SignupMemberInput.builder().apply {
dob(Utils.changeDateFormat(user.dobMMDDYYYY, "MM/dd/yyyy", "yyyy-MM-dd"))
firstName(user.firstName)
lastName(user.lastName)
ssLast4(user.ssnLastFour)
email(user.email)
cellPhone(user.phone)
password(user.password)
acceptedTos(true)
formIds(formIds)
medium(ConsentMediumEnum.ANDROID)
}.build()
Object
(#5156)useV3ExceptionHandling(true)
to ApolloClient.Builder()
. (#5135)A new alpha with updates to the IntelliJ/Android Studio plugin and better JS interop.
You can now navigate from Kotlin both GraphQL or Generated code:
https://github.com/apollographql/apollo-kotlin/assets/3974977/acd4bf34-db35-4442-a7af-b6151701620c
See blog the blog post and installation instructions for more information.
You can now connect the IJ/AS plugin to your GraphOS account. If your backend is configured to report field traces, the plugin will display a warning for expensive fields that may be slow to fetch.
You can configure it in your IJ/AS settings Languages & Frameworks
-> GraphQL
-> Apollo Kotlin
. See also #5048 for a video of the setup.
@jsExport
responseBased
codegen can now generate models annotated with @jsExport. This allows to fetch your response using faster JS-only APIs and cast them to the generated models. See the JS interoperability documentation for more information. Many thanks to @baconz for the deep dive π
Service.operationManifestFormat
(#4981)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 π .
Service.operationManifestFormat
(#4981)watch()
(#4914)Published by BoD over 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.
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:
ApolloResponse.exception
for error handlingError 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:
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 supportAs 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.
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"))
}
}
Published by BoD over 1 year ago
This patch release contains 2 bug fixes.
This release adds two new artifacts that contain Jetpack compose extensions amongst other fixes.
Many thanks to @slinstacart and @hbmartin for their contributions to this release!
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).
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
}
}
Published by BoD over 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! π
@JsName
annotation to Operation.name() (#4643)@include
or @skip
with default values (#4700)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!
@skip
and @include
(#4645)This release contains a handful of bug fixes and improvements.
Published by BoD almost 2 years 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! π§‘
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.
GraphQLWsProtocol.Factory.webSocketPayloadComposer
(#4589)alwaysGenerateTypesMatching
to execution time (#4578)service {}
in all messages/docs (#4572)Published by BoD almost 2 years ago
This patch release brings a few fixes.
Many thanks to @davidshepherd7, @chao2zhang, @agrosner, @MyDogTom, @doucheng, @sam43 and @vincentjames501, for helping improve the library! π
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")
// ...
+ }
}
canBeBatched
and httpHeaders
orthogonal (#4534)A patch release with a few fixes.
Many thanks to @Holoceo, @juliagarrigos, @davidshepherd7 and @eduardb for the feedbacks π
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 π!
This version adds multiple new low level features. These new features expose a lot of API surface, and they will probably stay experimental until 4.0. Feedback is always very welcome.
Compiler hooks allow you to tweak the generated models by exposing the underlying JavaPoet/KotlinPoet structures. You can use it for an example to:
__typename
(source)To do so, make sure to use the "external" version of the plugin:
plugins {
// Note: using the external plugin here to be able to reference KotlinPoet classes
id("com.apollographql.apollo3.external")
}
And then register your hook to the plugin:
apollo {
service("defaultnullvalues") {
packageName.set("hooks.defaultnullvalues")
compilerKotlinHooks.set(listOf(DefaultNullValuesHooks()))
}
}
By default, Apollo Kotlin models fragments with synthetic nullable fields. If you have a lot of fragments, checking these fields requires using if
statements. For an example, with a query like so:
{
animal {
species
... on WarmBlooded {
temperature
}
... on Pet {
name
}
... on Cat {
mustaches
}
}
}
you can access data like so:
if (animal.onWarmBlooded != null) {
// Cannot smart cast because of https://youtrack.jetbrains.com/issue/KT-8819/
println(animal.onWarmBlooded!!.temperature)
}
if (animal.onPet != null) {
println(animal.onPet!!.name)
}
if (animal.onCat != null) {
println(animal.onCat!!.mustaches)
}
Some of the combinations could be impossible. Maybe all the pets in your schema are warm blooded. Or maybe only cat is a warm blooded. To model this better and work around KT-8819, @chalermpong implemented a new codegen that adds a base sealed interface. Different implementations contain the same synthetic fragment fields as in the default codegen except that their nullability will be updated depending the branch:
when (animal) {
is WarmBloodedPetAnimal -> {
println(animal.onWarmBlooded!!.temperature)
println(animal.onPet!!.name)
}
is PetAnimal -> {
// Some pet that is not warm blooded, e.g. a Turtle maybe?
println(animal.onPet!!.name)
}
is OtherAnimal -> {
println(animal.species)
}
// Note how there is no branch for Cat because it's a WarmBloodedPetAnimal
// Also no branch for WarmBlooded animal because all pets in this (fictional) sample schema are WarmBlooded. This could be different in another schema
}
To try it out, add this to your Gradle scripts:
apollo {
codegenModels.set("experimental_operationBasedWithInterfaces")
}
Many many thanks to @chalermpong for diving into this π
By default, Apollo Kotlin only generates the types that are used in your queries. This is important because some schemas are really big and generating all the types would waste a lot of CPU cycles. In multi-modules scenarios, the codegen only knows about types that are used locally in that module. If two sibling modules use the same type and that type is not used upstream, that could lead to errors like this:
duplicate Type '$Foo' generated in modules: feature1, feature2
Use 'alwaysGenerateTypesMatching' in a parent module to generate the type only once
This version introduces new options to detect the used types automatically. It does so by doing a first pass at the GraphQL queries to determine the used type. Upstream modules can use the results of that computation without creating a circular dependency. To set up auto detection of used coordinates, configure your schema module to get the used coordinates from the feature module using the apolloUsedCoordinates
configuration:
// schema/build.gradle.kts
dependencies {
implementation("com.apollographql.apollo3:apollo-runtime")
// Get the used coordinates from your feature module
apolloUsedCoordinates(project(":feature"))
// If you have several, add several dependencies
apolloUsedCoordinates(project(":feature-2"))
}
apollo {
service("my-api") {
packageName.set("com.example.schema")
generateApolloMetadata.set(true)
}
}
And in each of your feature module, configure the apolloSchema
dependency:
// feature/build.gradle.kts
dependencies {
implementation("com.apollographql.apollo3:apollo-runtime")
// Depend on the codegen from the schema
apolloMetadata(project(":schema"))
// But also from the schema so as not to create a circular dependency
apolloSchema(project(":schema"))
}
apollo {
// The service names must match
service("my-api") {
packageName.set("com.example.feature")
}
}
registerJavaGeneratingTask
, fixes lint trying to scan generated sources (#4486)generateModelBuilder
to generateModelBuilders
and add test (#4476)JSWebSocketEngine
(#4445)A patch version to fix compatibility with Kotlin 1.7.20 and another fix when calling ApolloStore.dump()
with the SQL normalized cache.