Skip to content

Commit 31e9cff

Browse files
authored
Revisit docs 1/n: Get Started + Tutorial (#6089)
* remove apollo-adapters from these docs * move KDoc and Changelog up * add a list of modules * fix page name and section indentation * Add "add Android Studio plugin" * Nicer modules page * fix screenshot shadow * Revisit tutorial error handling * wording * wording * wording * wording
1 parent 39a2669 commit 31e9cff

File tree

34 files changed

+333
-91
lines changed

34 files changed

+333
-91
lines changed

docs/source/config.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"sidebar": {
88
"Get Started": "/",
99
"Migrating to v4": "/migration/4.0",
10+
"Modules": "/essentials/modules",
1011
"Evolution policy": "/essentials/evolution",
1112
"Kdoc": "https://apollographql.github.io/apollo-kotlin/kdoc/",
1213
"Changelog": "https://github.com/apollographql/apollo-kotlin/blob/main/CHANGELOG.md",

docs/source/essentials/modules.mdx

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
---
2+
title: Modules
3+
---
4+
5+
Apollo Kotlin is highly modular, making it easy to only include the features that you use and exclude the others, keeping your binary size and compile times small.
6+
7+
All the modules are documented in the [KDoc API reference](https://apollographql.github.io/apollo-kotlin/kdoc/)
8+
9+
## Main modules
10+
11+
### apollo-annotations
12+
13+
`apollo-annotations` is a very small module that contains `@ApolloExperimental` and other annotations mainly useful for handling API lifecycle.
14+
15+
It is an API dependency of most of the other modules.
16+
17+
### apollo-api
18+
19+
`apollo-api` contains the bare minimum symbols to compile the generated code and parse responses.
20+
21+
It does not contain any networking or caching code. For a more complete artifact, see `apollo-runtime`.
22+
23+
See ["Using the models without apollo-runtime"](https://www.apollographql.com/docs/kotlin/advanced/no-runtime) for how to use `apollo-api`.
24+
25+
### apollo-ast
26+
27+
`apollo-ast` contains code to parse GraphQL documents and manipulate their Abstract Syntax Tree.
28+
29+
See ["Apollo AST"](https://www.apollographql.com/docs/kotlin/advanced/apollo-ast) for how to use `apollo-ast`.
30+
31+
### apollo-compiler
32+
33+
`apollo-compiler` is the low level compiler API used by apollo-gradle-plugin.
34+
35+
`apollo-compiler` uses [JavaPoet](https://github.com/square/javapoet) and [KotlinPoet](https://github.com/square/kotlinpoet) to generate Java and Kotlin models from GraphQL operations.
36+
37+
`apollo-compiler` is usually consumed through Gradle or Maven plugins. It also contains `ApolloCompilerPlugin`.
38+
39+
See ["Apollo Compiler plugins"](https://www.apollographql.com/docs/kotlin/advanced/compiler-plugins) for how to develop compiler plugins.
40+
41+
### apollo-debug-server
42+
43+
`apollo-debug-server` is a server that serves your normalized cache to the IntelliJ/Android Studio plugin.
44+
45+
### apollo-gradle-plugin
46+
47+
`apollo-gradle-plugin` contains the Apollo Gradle plugin.
48+
49+
This module shadows and relocates its runtime dependencies to avoid classpath issues. This can make debugging harder in some cases.
50+
51+
See `apollo-gradle-plugin-external` for a version of `apollo-gradle-plugin` that does not shadow its dependencies.
52+
53+
See ["Gradle Plugin Configuration"](https://www.apollographql.com/docs/kotlin/advanced/plugin-configuration/) for how to use the Gradle plugin.
54+
55+
### apollo-gradle-plugin-external
56+
57+
`apollo-gradle-plugin-external` contains the Apollo Gradle plugin.
58+
59+
This module does not shadow its runtime dependencies, making it more prone to Gradle classpath issues.
60+
61+
See `apollo-gradle-plugin` for a version of `apollo-gradle-plugin-external` that shadow its dependencies.
62+
63+
See ["Gradle Plugin Configuration"](https://www.apollographql.com/docs/kotlin/advanced/plugin-configuration/) for how to use the Gradle plugin.
64+
65+
### apollo-http-cache
66+
67+
apollo-http-cache is a HTTP cache for your GraphQL operations. Compared to a regular HTTP cache, it also caches POST requests.
68+
69+
See ["HTTP cache"](https://www.apollographql.com/docs/kotlin/caching/http-cache) for how to use the HTTP cache
70+
71+
### apollo-normalized-cache
72+
73+
`apollo-normalized-cache contains` `ApolloStore` and `ApolloCacheInterceptor`. It bridges `ApolloClient` and `ApolloNormalizedCache`.
74+
75+
See ["Normalized Caches"](https://www.apollographql.com/docs/kotlin/caching/normalized-cache#in-memory-cache) for how to use the normalized cache.
76+
77+
### apollo-normalized-cache-api
78+
79+
`apollo-normalized-cache-api` is the low-level cache. It knows nothing about coroutines and/or `apollo-runtime` and contains a memory implementation of `NormalizedCache`.
80+
81+
Most of the time, use `apollo-normalized-cache` instead.
82+
83+
See ["Normalized Caches"](https://www.apollographql.com/docs/kotlin/caching/normalized-cache#in-memory-cache) for how to use the normalized cache.
84+
85+
### apollo-normalized-cache-sqlite
86+
87+
`apollo-normalized-cache-sqlite` contains an implementation of `NormalizedCache` that uses SQLite to persist the data across app restarts.
88+
89+
See ["Normalized Caches"](https://www.apollographql.com/docs/kotlin/caching/normalized-cache#in-memory-cache) for how to use the normalized cache.
90+
91+
### apollo-runtime
92+
93+
`apollo-runtime` contains `ApolloClient`, networking code to execute your queries and subscriptions. This is the main entry point.
94+
95+
See ["Get Started"](https://www.apollographql.com/docs/kotlin/) for how to instantiate and use an `ApolloClient`.
96+
97+
### apollo-testing-support
98+
99+
`apollo-testing-support` contains:
100+
101+
* `QueueTestNetworkTransport` and `MapTestNetworkTransport` for testing without a mock server.
102+
* a set of helper functions used for Apollo tests. They were never really intended to become public and will be removed in a future version. These symbols are marked as deprecated. If you are using them, copy paste them in your project.
103+
104+
See ["Mocking GraphQL responses"](https://www.apollographql.com/docs/kotlin/testing/mocking-graphql-responses) for how to use test network transports.
105+
106+
## Deprecated modules
107+
108+
These modules are deprecated and will be removed in a future version.
109+
110+
### apollo-adapters (DEPRECATED)
111+
112+
`apollo-adapters` contains adapters for common date and big decimal GraphQL scalars.
113+
114+
This module is deprecated and moved to the Apollo Galaxy. See the [Apollo Galaxy page](https://www.apollographql.com/docs/kotlin/advanced/galaxy) for more details.
115+
116+
### apollo-api-java (DEPRECATED)
117+
118+
`apollo-api-java` contains the symbols needed to compile the Java models.
119+
120+
This module is deprecated and moved to the Apollo Galaxy. See the [Apollo Galaxy page](https://www.apollographql.com/docs/kotlin/advanced/galaxy) for more details.
121+
122+
### apollo-engine-ktor (DEPRECATED)
123+
124+
`apollo-engine-ktor` is an implementation of `HttpEngine` and `WebSocketEngine` that uses Ktor.
125+
126+
This module is deprecated and moved to the Apollo Galaxy. See the [Apollo Galaxy page](https://www.apollographql.com/docs/kotlin/advanced/galaxy) for more details.
127+
128+
### apollo-idling-resource (DEPRECATED)
129+
130+
`apollo-idling-resource` contains an [Espresso `IdlingResource`](https://developer.android.com/training/testing/espresso/idling-resource) that monitors calls to your GraphQL API.
131+
132+
This module is deprecated as we recommend you should wait for your UI to change instead. See [this article about ways to do so](https://medium.com/androiddevelopers/alternatives-to-idling-resources-in-compose-tests-8ae71f9fc473).
133+
134+
### apollo-mockserver (DEPRECATED)
135+
136+
`apollo-mockserver` is a HTTP server for your tests. It supports multiplatform and websockets.
137+
138+
The API is minimal and performance is a non-goal. Do not use for production APIs.
139+
140+
This module is deprecated and moved to the Apollo Galaxy. See the [Apollo Galaxy page](https://www.apollographql.com/docs/kotlin/advanced/galaxy) for more details.
141+
142+
### apollo-runtime-java (DEPRECATED)
143+
144+
`apollo-runtime-java` is an implementation of `ApolloClient` that doesn't use coroutines and more generally is more friendly for Java callers.
145+
146+
This module is deprecated and moved to the Apollo Galaxy. See the [Apollo Galaxy page](https://www.apollographql.com/docs/kotlin/advanced/galaxy) for more details.
147+
148+
### apollo-rx2-support (DEPRECATED)
149+
150+
`apollo-rx2-support` provides thin wrappers around [`kotlinx-coroutines-rx2`](https://github.com/Kotlin/kotlinx.coroutines/tree/master/reactive/kotlinx-coroutines-rx2).
151+
152+
This module is deprecated and will be removed in a future version.
153+
154+
### apollo-rx3-support (DEPRECATED)
155+
156+
`apollo-rx3-support` provides thin wrappers around [`kotlinx-coroutines-rx3`](https://github.com/Kotlin/kotlinx.coroutines/tree/master/reactive/kotlinx-coroutines-rx3).
157+
158+
This module is deprecated and will be removed in a future version.
159+
160+
### apollo-rx2-support-java (DEPRECATED)
161+
162+
`apollo-rx2-support-java` provides adapter from `ApolloCall` to their RxJava3 equivalent.
163+
164+
This module is deprecated and moved to the Apollo Galaxy. See the [Apollo Galaxy page](https://www.apollographql.com/docs/kotlin/advanced/galaxy) for more details.
165+
166+
### apollo-rx3-support-java (DEPRECATED)
167+
168+
`apollo-rx3-support-java` provides adapter from `ApolloCall` to their RxJava3 equivalent.
169+
170+
This module is deprecated and moved to the Apollo Galaxy. See the [Apollo Galaxy page](https://www.apollographql.com/docs/kotlin/advanced/galaxy) for more details.
171+
172+
## Internal modules
173+
174+
These modules are published for technical reasons only. Most of their symbols are `@ApolloInternal` and they might be removed at any time. Avoid using them.
175+
176+
### apollo-mockserver (INTERNAL)
177+
178+
`apollo-mpp-utils` contains a few utilities for working with multiplatform projects.
179+
180+
As of June 2024, it only contains `currentTimeMillis`. In most cases, we should replace that with `kotlin.time.TimeMark` but it's still used in `HttpInfo` as absolute timestamps, and we can't remove it just yet.
181+
182+
This module is published for technical reasons only. Do not use directly.
183+
184+
### apollo-tooling (INTERNAL)
185+
186+
`apollo-tooling` contains APIs to work with GraphQL schemas and operations as well as the GraphOS API. It is used from the CLI and Gradle plugin
187+
188+
This module is published for technical reasons only. Do not use directly.

docs/source/index.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,10 @@ Here's the current matrix of supported features per platform:
113113
| | `jvm` | `Apple¹` | `js` | `wasmJs` | `linuxX64` |
114114
|------------------------------------------------------|:-----:|:--------:|:----:|:--------:|:----------:|
115115
| `apollo-api` (models) ||||||
116-
| `apollo-runtime` (network, query batching, apq, ...) ||||| 🚫 |
117-
| `apollo-normalized-cache` ||||| 🚫 |
118-
| `apollo-adapters` ||||| 🚫 |
119-
| `apollo-normalized-cache-sqlite` ||| 🚫 | 🚫 | 🚫 |
120-
| `apollo-http-cache` || 🚫 | 🚫 | 🚫 | 🚫 |
116+
| `apollo-runtime` (network, query batching, apq, ...) ||||| 🚫 |
117+
| `apollo-normalized-cache` ||||| 🚫 |
118+
| `apollo-normalized-cache-sqlite` ||| 🚫 | 🚫 | 🚫 |
119+
| `apollo-http-cache` || 🚫 | 🚫 | 🚫 | 🚫 |
121120

122121
¹: Apple currently includes:
123122

docs/source/tutorial/01-configure-project.mdx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,14 @@ You should see a list with static placeholder data:
3131

3232
Now let's add Apollo Kotlin to the project.
3333

34+
## Install the Android Studio Plugin (optional)
35+
36+
We recommend installing the [Android Studio Plugin](https://www.apollographql.com/docs/kotlin/testing/android-studio-plugin/) to benefit from autocomplete in your `.graphql`, live code generation and more.
37+
38+
Go to `Android Studio` -> `Setting...` -> `Plugins`. In the "Marketplace" tab, search for "Apollo" and install the Apollo Android Studio Plugin
39+
40+
<img src="images/add-ij-plugin.png" alt="A dialog showing how to install the Android Studio plugin" class="screenshot"/>
41+
3442
## Get the latest version of Apollo Kotlin
3543

3644
You can find the latest version of Apollo Kotlin from the [GitHub releases page](https://github.com/apollographql/apollo-kotlin/releases). It is also displayed at the top of the [apollo-kotlin repo](https://github.com/apollographql/apollo-kotlin/).

docs/source/tutorial/08-add-a-details-view.mdx

Lines changed: 40 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -118,19 +118,22 @@ fun LaunchDetails(launchId: String) {
118118
}
119119
```
120120

121-
## Handle protocol errors
121+
## Handle errors
122122

123-
As you execute your query, two types of errors can happen:
123+
As you execute your query, different types of errors can happen:
124124

125-
* Protocol errors: connectivity issues, HTTP errors, or JSON parsing errors. In this case, `response.exception` will contain an `ApolloException`, and `response.data` will be null.
126-
* Application errors. In this case, `response.errors` will contain the application errors and `response.data` might be `null`.
125+
* Fetch errors: connectivity issues, HTTP errors, JSON parsing errors, etc... In this case, `response.exception` contains an `ApolloException`. Both `response.data` and `response.errors` is null.
126+
* GraphQL [request errors](https://spec.graphql.org/draft/#request-error): in this case, `response.errors` contains the GraphQL errors. `response.data` is null.
127+
* GraphQL [field errors](https://spec.graphql.org/draft/#field-error): in this case, `response.errors` contains the GraphQL errors. `response.data` contains partial data.
128+
129+
Let's handle the first two for now: fetch errors and GraphQL request errors.
127130
128131
First let's create a `LaunchDetailsState` sealed interface that will hold the possible states of the UI:
129132

130133
```kotlin title="app/src/main/java/com/example/rocketreserver/LaunchDetails.kt"
131134
private sealed interface LaunchDetailsState {
132135
object Loading : LaunchDetailsState
133-
data class ProtocolError(val exception: ApolloException) : LaunchDetailsState
136+
data class Error(val message: String) : LaunchDetailsState
134137
data class Success(val data: LaunchDetailsQuery.Data) : LaunchDetailsState
135138
}
136139
```
@@ -144,11 +147,12 @@ fun LaunchDetails(launchId: String) {
144147
LaunchedEffect(Unit) {
145148
val response = apolloClient.query(LaunchDetailsQuery(launchId)).execute()
146149
state = when {
147-
response.exception != null -> {
148-
ProtocolError(response.exception!!)
150+
response.data != null -> {
151+
// Handle (potentially partial) data
152+
LaunchDetailsState.Success(response.data!!)
149153
}
150154
else -> {
151-
Success(response.data!!)
155+
LaunchDetailsState.Error("Oh no... An error happened.")
152156
}
153157
}
154158
}
@@ -158,63 +162,57 @@ fun LaunchDetails(launchId: String) {
158162
Now use the state to show the appropriate UI:
159163

160164
```kotlin title="app/src/main/java/com/example/rocketreserver/LaunchDetails.kt"
165+
161166
// Use the state
162167
when (val s = state) {
163168
Loading -> Loading()
164-
is ProtocolError -> ErrorMessage("Oh no... A protocol error happened: ${s.exception.message}")
169+
is Error -> ErrorMessage(s.message)
165170
is Success -> LaunchDetails(s.data)
166171
}
167172
}
168173
```
169174

170175
Enable airplane mode before clicking the details of a launch. You should see this:
171176

172-
<img src="images/error_protocol.png" alt="Oh no" class="screenshot" width="300"/>
177+
<img src="images/error_generic.png" alt="Oh no" class="screenshot" width="300"/>
173178

174-
This is good! But it's not enough. Even if the request executes correctly at the protocol level, it might also contain application errors that are specific to your server.
179+
This is good!
175180

176-
## Handle application errors
181+
This method handles fetch and GraphQL request errors but ignores GraphQL field errors.
177182

178-
To handle application errors, you can check `response.hasErrors()`. First, add a new state to the sealed interface:
183+
If a GraphQL field error happens, the corresponding Kotlin property is `null` and an error is present in `response.errors`: your response contains partial data!
179184

180-
```kotlin title="app/src/main/java/com/example/rocketreserver/LaunchDetails.kt"
181-
private sealed interface LaunchDetailsState {
182-
object Loading : LaunchDetailsState
183-
data class ProtocolError(val exception: ApolloException) : LaunchDetailsState
184-
data class ApplicationError(val errors: List<Error>) : LaunchDetailsState // highlight-line
185-
data class Success(val data: LaunchDetailsQuery.Data) : LaunchDetailsState
186-
}
187-
```
185+
Handling this partial data in your UI code can be complicated. You can handle them earlier by looking at `response.errors`.
186+
187+
## Handle partial data
188188

189-
Then, in the `when` block, check for `response.hasErrors()` and wrap the result in the new state:
189+
To handle GraphQL field errors globally and make sure the returned data is not partial, use `response.errors`:
190190

191191
```kotlin title="app/src/main/java/com/example/rocketreserver/LaunchDetails.kt"
192192
state = when {
193-
response.exception != null -> {
194-
ProtocolError(response.exception!!)
195-
}
196-
response.hasErrors() -> { // highlight-line
197-
ApplicationError(response.errors!!) // highlight-line
198-
} // highlight-line
199-
else -> {
200-
Success(response.data!!)
201-
}
193+
response.errors.orEmpty().isNotEmpty() -> {
194+
// GraphQL error
195+
LaunchDetailsState.Error(response.errors!!.first().message) // highlight-line
196+
}
197+
response.exception is ApolloNetworkException -> {
198+
// Network error
199+
LaunchDetailsState.Error("Please check your network connectivity.")
200+
}
201+
response.data != null -> {
202+
// data (never partial)
203+
LaunchDetailsState.Success(response.data!!)
204+
}
205+
else -> {
206+
// Another fetch error, maybe a cache miss?
207+
// Or potentially a non-compliant server returning data: null without an error
208+
LaunchDetailsState.Error("Oh no... An error happened.")
209+
}
202210
}
203211
```
204212

205-
You should also update the conditional expression to handle the `ApplicationError` case:
206-
```kotlin title="app/src/main/java/com/example/rocketreserver/LaunchDetails.kt"
207-
when (val s = state) {
208-
Loading -> Loading()
209-
is ApplicationError -> ErrorMessage(text = s.errors.first().message) // highlight-line
210-
is ProtocolError -> ErrorMessage("Oh no... A protocol error happened: ${s.exception.message}")
211-
is Success -> LaunchDetails(s.data)
212-
}
213-
```
214-
215213
`response.errors` contains details about any errors that occurred. Note that this code also null-checks `response.data!!`. In theory, a server should not set `response.data == null` and `response.hasErrors == false` at the same time, but the type system cannot guarantee this.
216214

217-
To trigger an error, replace `LaunchDetailsQuery(launchId)` with `LaunchDetailsQuery("invalidId")`. Disable airplane mode and select a launch. The server will send this response:
215+
To trigger a GraphQL field error, replace `LaunchDetailsQuery(launchId)` with `LaunchDetailsQuery("invalidId")`. Disable airplane mode and select a launch. The server will send this response:
218216

219217
```json title="(error)"
220218
{
137 KB
Loading
43.4 KB
Loading
-55.8 KB
Binary file not shown.

0 commit comments

Comments
 (0)