diff --git a/.github/workflows/benchmarks.yml b/.github/workflows/benchmarks.yml
index dd9faf13b90..7bf8a0fc56a 100644
--- a/.github/workflows/benchmarks.yml
+++ b/.github/workflows/benchmarks.yml
@@ -5,25 +5,27 @@ on:
# branches: [ '*' ]
schedule:
- cron: '0 3 * * *'
+ workflow_dispatch:
+
env:
- GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}
+ DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
jobs:
benchmarks:
runs-on: macos-14
if: github.repository == 'apollographql/apollo-kotlin'
steps:
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1
- - uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 #v4.0.0
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7
+ - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 #v4.2.1
with:
distribution: 'temurin'
java-version: 17
- - uses: gradle/gradle-build-action@42452daeb5b454a76f686a8e4de8234afd7b1f44 #v2.12.0
+ - uses: gradle/actions/setup-gradle@dbbdc275be76ac10734476cc723d82dfe7ec6eda #v3.4.2
with:
gradle-home-cache-cleanup: true
- run: |
# Build the benchmark apks
- ./gradlew -p benchmark :app:assembleRelease :microbenchmark:assembleIncubatingReleaseAndroidTest :microbenchmark:assembleStableReleaseAndroidTest
+ ./gradlew -p benchmark :app:assembleRelease :microbenchmark:assembleReleaseAndroidTest
# Step can be removed if/when gcloud is added to the macos image - See https://github.com/actions/virtual-environments/issues/4639
- name: Setup gcloud
uses: google-github-actions/setup-gcloud@98ddc00a17442e89a24bbf282954a3b65ce6d200 #v2.1.0
diff --git a/.github/workflows/bump-kotlin-shadow.yml b/.github/workflows/bump-kotlin-shadow.yml
new file mode 100644
index 00000000000..0dfa6d1c87b
--- /dev/null
+++ b/.github/workflows/bump-kotlin-shadow.yml
@@ -0,0 +1,20 @@
+name: Bump kotlin shadow
+
+on:
+ schedule:
+ - cron: '0 2 * * *'
+ workflow_dispatch:
+
+jobs:
+ push-kotlin-nightlies-branch:
+ runs-on: macos-14
+ steps:
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7
+ - name: Bump Kotlin in libraries.toml
+ run: ./scripts/bump-kotlin-in-libraries-toml.main.kts
+ - name: Push changes to kotlin-nightlies branch
+ run: |
+ git checkout -b kotlin-nightlies
+ git add .
+ git commit -m "Bump Kotlin version"
+ git push --force origin kotlin-nightlies
diff --git a/.github/workflows/defer-with-router-tests.yml b/.github/workflows/defer-with-router-tests.yml
index 1074bc779ae..ae816371c8f 100644
--- a/.github/workflows/defer-with-router-tests.yml
+++ b/.github/workflows/defer-with-router-tests.yml
@@ -4,7 +4,7 @@ on:
schedule:
- cron: '0 3 * * *'
env:
- GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}
+ DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
jobs:
defer-with-router-tests:
@@ -12,7 +12,7 @@ jobs:
if: github.repository == 'apollographql/apollo-kotlin'
steps:
- name: Checkout project
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1
+ uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7
- name: Install and run subgraph
working-directory: tests/defer/router/subgraphs/computers
@@ -29,13 +29,13 @@ jobs:
./router --supergraph tests/defer/router/simple-supergraph.graphqls &
- name: Setup Java
- uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 #v4.0.0
+ uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 #v4.2.1
with:
distribution: 'temurin'
java-version: 17
- name: Setup Gradle
- uses: gradle/gradle-build-action@42452daeb5b454a76f686a8e4de8234afd7b1f44 #v2.12.0
+ uses: gradle/actions/setup-gradle@dbbdc275be76ac10734476cc723d82dfe7ec6eda #v3.4.2
- name: Run Apollo Kotlin @defer tests
env:
diff --git a/.github/workflows/docs-publish.yml b/.github/workflows/docs-publish.yml
index f0df1982fd4..0a81d4a7794 100644
--- a/.github/workflows/docs-publish.yml
+++ b/.github/workflows/docs-publish.yml
@@ -13,7 +13,7 @@ on:
jobs:
publish:
- uses: apollographql/docs/.github/workflows/publish.yml@main
+ uses: apollographql/docs/.github/workflows/publish.yml@main # pga-ignore
if: github.repository == 'apollographql/apollo-kotlin'
secrets:
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
diff --git a/.github/workflows/platform-api-tests.yml b/.github/workflows/platform-api-tests.yml
index a4403df6587..f1048b70872 100644
--- a/.github/workflows/platform-api-tests.yml
+++ b/.github/workflows/platform-api-tests.yml
@@ -8,7 +8,7 @@ on:
workflow_dispatch:
env:
- GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}
+ DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
jobs:
platform-api-tests:
@@ -16,16 +16,16 @@ jobs:
if: github.repository == 'apollographql/apollo-kotlin'
steps:
- name: Checkout project
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1
+ uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7
- name: Setup Java
- uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 #v4.0.0
+ uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 #v4.2.1
with:
distribution: 'temurin'
java-version: 17
- name: Setup Gradle
- uses: gradle/gradle-build-action@42452daeb5b454a76f686a8e4de8234afd7b1f44 #v2.12.0
+ uses: gradle/actions/setup-gradle@dbbdc275be76ac10734476cc723d82dfe7ec6eda #v3.4.2
- name: Run tests against the Apollo Platform API
env:
diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml
index c8b31b03b44..c811d49bd50 100644
--- a/.github/workflows/pr.yml
+++ b/.github/workflows/pr.yml
@@ -5,12 +5,14 @@ on:
paths-ignore:
- 'docs/**'
- '*.md'
+ workflow_dispatch:
+
env:
- GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}
+ DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
# Cancel any current or previous job from the same PR
concurrency:
- group: ${{ github.head_ref }}
+ group: ${{ format('{0}-', github.head_ref) }}
cancel-in-progress: true
jobs:
@@ -18,12 +20,12 @@ jobs:
if: "!startsWith(github.head_ref, 'release-')"
runs-on: macos-14
steps:
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1
- - uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 #v4.0.0
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7
+ - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 #v4.2.1
with:
distribution: 'temurin'
java-version: 17
- - uses: gradle/gradle-build-action@42452daeb5b454a76f686a8e4de8234afd7b1f44 #v2.12.0
+ - uses: gradle/actions/setup-gradle@dbbdc275be76ac10734476cc723d82dfe7ec6eda #v3.4.2
with:
gradle-home-cache-cleanup: true
- name: Build with Gradle
@@ -32,7 +34,7 @@ jobs:
- name: Collect Diagnostics
if: always()
run: ./scripts/collect-diagnostics.main.kts
- - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 #v4.3.0
+ - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 #v4.3.3
if: always()
with:
name: tests-gradle.zip
@@ -42,12 +44,12 @@ jobs:
if: "!startsWith(github.head_ref, 'release-')"
runs-on: macos-14
steps:
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1
- - uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 #v4.0.0
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7
+ - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 #v4.2.1
with:
distribution: 'temurin'
java-version: 17
- - uses: gradle/gradle-build-action@42452daeb5b454a76f686a8e4de8234afd7b1f44 #v2.12.0
+ - uses: gradle/actions/setup-gradle@dbbdc275be76ac10734476cc723d82dfe7ec6eda #v3.4.2
with:
gradle-home-cache-cleanup: true
- name: Build with Gradle
@@ -56,7 +58,7 @@ jobs:
- name: Collect Diagnostics
if: always()
run: ./scripts/collect-diagnostics.main.kts
- - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 #v4.3.0
+ - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 #v4.3.3
if: always()
with:
name: tests-no-gradle.zip
@@ -66,12 +68,12 @@ jobs:
if: "!startsWith(github.head_ref, 'release-')"
runs-on: macos-14
steps:
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1
- - uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 #v4.0.0
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7
+ - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 #v4.2.1
with:
distribution: 'temurin'
java-version: 17
- - uses: gradle/gradle-build-action@42452daeb5b454a76f686a8e4de8234afd7b1f44 #v2.12.0
+ - uses: gradle/actions/setup-gradle@dbbdc275be76ac10734476cc723d82dfe7ec6eda #v3.4.2
with:
gradle-home-cache-cleanup: true
- name: Build with Gradle
@@ -80,7 +82,7 @@ jobs:
- name: Collect Diagnostics
if: always()
run: ./scripts/collect-diagnostics.main.kts
- - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 #v4.3.0
+ - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 #v4.3.3
if: always()
with:
name: tests-integration.zip
@@ -102,11 +104,11 @@ jobs:
# Check out current repository
- name: Fetch Sources
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1
+ uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7
# Setup Java 11 environment for the next steps
- name: Setup Java
- uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 #v4.0.0
+ uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 #v4.2.1
with:
distribution: 'temurin'
java-version: 17
@@ -136,14 +138,14 @@ jobs:
# Collect Tests Result of failed tests
- name: Collect Tests Result
if: ${{ failure() }}
- uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 #v4.3.0
+ uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 #v4.3.3
with:
name: tests-result
path: ${{ github.workspace }}/intellij-plugin/build/reports/tests
# Cache Plugin Verifier IDEs
- name: Setup Plugin Verifier IDEs Cache
- uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 #v4.0.0
+ uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2
with:
path: ${{ steps.properties.outputs.pluginVerifierHomeDir }}/ides
key: plugin-verifier-${{ hashFiles('intellij-plugin/build/listProductsReleases.txt') }}
@@ -155,7 +157,7 @@ jobs:
# Collect Plugin Verifier Result
- name: Collect Plugin Verifier Result
if: ${{ always() }}
- uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 #v4.3.0
+ uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 #v4.3.3
with:
name: pluginVerifier-result
path: ${{ github.workspace }}/intellij-plugin/build/reports/pluginVerifier
@@ -173,7 +175,7 @@ jobs:
# Store already-built plugin as an artifact for downloading
- name: Upload artifact
- uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 #v4.3.0
+ uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 #v4.3.3
with:
name: ${{ steps.artifact.outputs.filename }}
path: ./intellij-plugin/build/distributions/content/*/*
diff --git a/.github/workflows/publish-ij-plugin-snapshot.yml b/.github/workflows/publish-ij-plugin-snapshot.yml
index 7e9486d1172..7678fb1a24d 100644
--- a/.github/workflows/publish-ij-plugin-snapshot.yml
+++ b/.github/workflows/publish-ij-plugin-snapshot.yml
@@ -5,16 +5,16 @@ on:
- cron: '0 0 * * 0'
workflow_dispatch:
env:
- GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}
+ DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
jobs:
publish-intellij-plugin:
name: Publish IntelliJ plugin
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7
- - uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 #v4.0.0
+ - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 #v4.2.1
with:
distribution: 'temurin'
java-version: 17
diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml
index 161b8755404..107a1eb9a18 100644
--- a/.github/workflows/push.yml
+++ b/.github/workflows/push.yml
@@ -7,19 +7,19 @@ on:
- 'docs/**'
- '*.md'
env:
- GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}
+ DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
jobs:
deploy:
runs-on: macos-14
if: github.repository == 'apollographql/apollo-kotlin'
steps:
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1
- - uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 #v4.0.0
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7
+ - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 #v4.2.1
with:
distribution: 'temurin'
java-version: 17
- - uses: gradle/gradle-build-action@42452daeb5b454a76f686a8e4de8234afd7b1f44 #v2.12.0
+ - uses: gradle/actions/setup-gradle@dbbdc275be76ac10734476cc723d82dfe7ec6eda #v3.4.2
with:
gradle-home-cache-cleanup: true
- name: Build with Gradle
@@ -35,13 +35,13 @@ jobs:
- name: Collect Diagnostics
if: always()
run: ./scripts/collect-diagnostics.main.kts
- - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 #v4.3.0
+ - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 #v4.3.3
if: always()
with:
name: push.zip
path: diagnostics.zip
- name: Deploy Kdoc to github pages
- uses: JamesIves/github-pages-deploy-action@65b5dfd4f5bcd3a7403bbc2959c144256167464e #v4.5.0
+ uses: JamesIves/github-pages-deploy-action@5c6e9e9f3672ce8fd37b9856193d2a537941e66c #v4.6.1
with:
branch: gh-pages # The branch the action should deploy to.
folder: libraries/apollo-kdoc/build/dokka/html # The folder the action should deploy.
diff --git a/.github/workflows/tag.yml b/.github/workflows/tag.yml
index 5714097963b..9674ae5a978 100644
--- a/.github/workflows/tag.yml
+++ b/.github/workflows/tag.yml
@@ -5,7 +5,7 @@ on:
tags:
- '*'
env:
- GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}
+ DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
jobs:
publish-libraries:
@@ -13,12 +13,12 @@ jobs:
runs-on: macos-14
if: github.repository == 'apollographql/apollo-kotlin'
steps:
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1
- - uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 #v4.0.0
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7
+ - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 #v4.2.1
with:
distribution: 'temurin'
java-version: 17
- - uses: gradle/gradle-build-action@42452daeb5b454a76f686a8e4de8234afd7b1f44 #v2.12.0
+ - uses: gradle/actions/setup-gradle@dbbdc275be76ac10734476cc723d82dfe7ec6eda #v3.4.2
with:
gradle-home-cache-cleanup: true
#--no-configuration-cache for https://youtrack.jetbrains.com/issue/KT-65879
@@ -36,8 +36,8 @@ jobs:
name: Publish IntelliJ plugin
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1
- - uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 #v4.0.0
+ - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7
+ - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 #v4.2.1
with:
distribution: 'temurin'
java-version: 17
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
index a5f2722fe66..d69494f0a95 100644
--- a/.idea/codeStyles/Project.xml
+++ b/.idea/codeStyles/Project.xml
@@ -25,6 +25,10 @@
+
+
+
+
@@ -58,7 +62,7 @@
-
+
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7a6c559fca7..27ae15562d4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,129 @@
Change Log
==========
+# Version 4.0.0-beta.7
+
+_2024-06-05_
+
+## K2
+
+#5931: This version is built with K2. You will need Kotlin 1.9+ on the JVM to build it and Kotlin 2.0 for other platforms.
+
+## ApolloCompilerPluginProvider
+
+#5865: `ApolloCompilerPluginProvider` is introduced to allow passing arguments to compiler plugins. See the [compiler plugins documentation](https://go.apollo.dev/ak-compiler-plugins) for more details.
+
+## ๐ทโ All changes
+* [testing] Use com.apollographql.mockserver.MockServer (#5939)
+* [testing] Simplify our implementation of runTest (#5935)
+* [testing] Prepare apollo-testing-support to new MockServer (#5934)
+* [runtime] Remove multidex library (#5930)
+* [all] Bump languageVersion/apiVersion to Kotlin 2.0 (#5931)
+* [codegen] fix mapping of the builtin Float type (#5928)
+* [IJ Plugin] Add inspection to warn about the presence of a GraphQL config file (#5908)
+* [codegen] Add a null-check to java enum safeValueOf (#5904)
+* [gradle-plugin] Remove eager configuration (#5923)
+* [gradle-plugin] sort input files (#5919)
+* [IJ Plugin] Suppress GraphQLDuplicateDirective for certain directives (#5910)
+* [adapters] Add KtorHttpUrlAdapter (#5915)
+* [IJ Plugin] Add a "new UI" compatible icon (#5906)
+* [IJ Plugin] Operation and fragment definition rename (#5912)
+* [IJ Plugin] Add @link directives to extra.graphqls during v3->v4 migration (#5909)
+* [IJ Plugin] Remove GraphQL IJ plugin issue workaround (#5907)
+* [cache] Pagination: use "field key" instead of "field name" (#5898)
+* [IJ Plugin] Improve the presentation of GraphQL elements when navigating to them (#5900)
+* [IJ Plugin] Include subfolders when contributing GraphQL config (#5871)
+* [runtime] Remove existing interceptors from ApolloClient.Builder before adding new ones (#5858)
+* [codegen] Add ApolloCompilerPluginProvider (#5865)
+* [runtime] Clear current ApolloStore related interceptors when calling `.store()` on builder (#5857)
+* [cache] Call through to loadRecords from the MemoryCache to the SQL one (#5848)
+* [runtime] deprecate operationIdGenerator (#5850)
+
+# Version 3.8.4
+
+_2024-04-29_
+
+Version 3.8.4 is a maintenance release with one bug fix and 2 performance improvements. New developments happen in the 4.x versions.
+
+* [java-runtime] Fix `ApolloClient.Builder.okHttpClient()` returns null instead of this (#5860)
+* [normalized-cache] Use a single transaction when using MemoryCache chaining (#5861)
+* [normalized-cache] Call through to loadRecords from the MemoryCache to the SQL one (#5863)
+
+# Version 4.0.0-beta.6
+
+_2024-04-23_
+
+## SQL cache performance improvements
+
+If you're using a chained memory + SQL cache, #5840 makes sure cache writes are wrapped in a transaction, making them much faster.
+
+## Apollo Compiler Plugins
+
+`Plugin` is renamed to `ApolloCompilerPlugin`. There is a new `documentTransform` API as well as other fixes. More details in the [compiler plugins documentation](https://www.apollographql.com/docs/kotlin/v4/advanced/compiler-plugins).
+
+## Experimental WebSockets
+
+A new `.websocket` package is available that makes it easier to retry WebSockets and handle errors. More details and migration guide in the [experimental websockets documentation](https://www.apollographql.com/docs/kotlin/v4/advanced/experimental-websockets).
+
+## ApolloIdlingResource is deprecated
+
+We recommend using reactive patterns to test your UI instead. See [this article about ways to do so](https://medium.com/androiddevelopers/alternatives-to-idling-resources-in-compose-tests-8ae71f9fc473).
+
+## Removed androidx.startup dependency
+
+androidx.startup was introduced in beta.5 but is problematic for unit tests and other cases. beta.6 removes that dependency. More details in the [network connectivity documentation](https://www.apollographql.com/docs/kotlin/v4/advanced/network-connectivity).
+
+## WasmJS support for apollo-adapter
+
+You can see Wasm in action at https://wasm.confetti-app.dev/
+
+## Threading changes
+
+In a effort to minimize the number of thread switches, the whole request is now run in the same dispatcher. See [Threading.md](https://github.com/apollographql/apollo-kotlin/blob/39d76630277476004bbaed0e3a897feb5a959084/design-docs/Threading.md) for more details.
+
+## Contributors ๐
+
+Many thanks to @joreilly, @ychescale9 and @japhib for their contributions to this release ๐!
+
+## ๐ทโ All changes
+* [normalized-cache]: use a single SQL transaction when using MemoryCache chaining (#5840)
+* [compiler] expose apollo-ast as an api dependency (#5838)
+* [compiler] Rename `Plugin` to `ApolloCompilerPlugin` and add error message for bad configurations (#5821)
+* [IJ Plugin] Fix pulling file from device not working on AS Koala (#5822)
+* [compiler] Add `@ApolloEnumConstructor` and make enum as sealed class Unknown constructor opt-in (#5813)
+* [runtime] Move ApolloParseException to ApolloNetworkException (#5816)
+* [normalized-cache] Let isFromCache be about the ApolloResponse (#5805)
+* [compiler] Add DocumentTransform API (#5809)
+* [idling-resource] Deprecate ApolloIdlingResource (#5817, #5764)
+* [runtime] Share the default OkHttpBuilder (#5811)
+* [runtime] [BREAKING] change `isOnline` to a suspend fun
+* [adapters] Support Kotlin/Wasm for apollo-adapters (#5803)
+* [all] Bump Kotlin to 2.0.0-RC1 (#5802)
+* [Codegen] Add CompiledArgumentDefinition (#5797, #5837)
+* [runtime] Merge experimental WebSocketNetworkTransport in apollo-runtime (#5790)
+* [normalized-cache] Cache pagination: add FieldNameGenerator and EmbeddedFieldsProvider (#5772)
+* [runtime] Support configuring `ApolloClient` with lazily initialized `Call.Factory`. (#5784)
+* [runtime] fix ApolloClient.Builder.okHttpClient() returns null instead of this (#5778)
+* [normalized-cache] Fix variable coercion in lists. Absent variables are coerced to null (#5773)
+* [IJ Plugin] Fix an NPE (#5770)
+* [runtime] Simplify ApolloCall (#5765)
+* [runtime] remove `androidx.startup` dependency (#5761, #5720)
+* [compiler] Bump kotlin_labs definitions to v0.3 (#5762)
+* [Pagination] Support nodes in Connection types (#5754)
+* [compiler] Directive validation is now enforced by default (#5758)
+* [cache] Make ApolloStore.publish() suspend (#5755)
+* [runtime] Change the dispatcher earlier in the chain (#4319)
+* [IJ Plugin] Add an advanced setting to include generated code references in GraphQL "Go To Declaration" (#5743)
+* [IJ Plugin] Fix presentation of Kotlin elements when navigating to them from GraphQL (#5739)
+* [IJ Plugin] Consider all Gradle projects recursively (#5734)
+* [runtime] Deprecate ApolloClient.Builder.addInterceptors() (#5733)
+* [all] use jdk-release (#5731)
+* [http-cache] Ignore IOException when calling ApolloHttpCache.remove (#5729)
+* [IJ plugin] Bump platformVersion and pluginSinceBuild from 232 to 233 (#5726)
+* [runtime] add ApolloClient.failFastIfOffline (#5725)
+* [all] Introduce "filesystem" sourceSet and use okio 3.9.0 (#5719)
+* [runtime] Do not use Ktor in Js HttpEngine, use fetch directly instead (#5702)
+
# Version 3.8.3
_2024-03-20_
diff --git a/README.md b/README.md
index c420e2b0bf6..67504272766 100644
--- a/README.md
+++ b/README.md
@@ -15,17 +15,17 @@
| :----- |
| What do you like best about Apollo Kotlin? What needs to be improved? Please tell us by taking a [one-minute survey](https://docs.google.com/forms/d/e/1FAIpQLSczNDXfJne3ZUOXjk9Ursm9JYvhTh1_nFTDfdq3XBAFWCzplQ/viewform?usp=pp_url&entry.1170701325=Apollo+Kotlin&entry.204965213=Readme). Your responses will help us understand Apollo Kotlin usage and allow us to serve you better. |
-Apollo Kotlin (formerly known as Apollo Android) is a GraphQL client that generates Kotlin and Java models from GraphQL queries.
+Apollo Kotlin (formerly Apollo Android) is a GraphQL client that generates Kotlin and Java models from GraphQL operations.
-Apollo Kotlin executes queries and mutations against a GraphQL server and returns results as query-specific Kotlin types. This means you don't have to deal with parsing JSON, or passing around `Map`s and making clients cast values to the right type manually. You also don't have to write model types yourself, because these are generated from the GraphQL definitions your UI uses.
+Apollo Kotlin executes operations against a GraphQL server and returns results as operation-specific Kotlin types. This means you don't have to deal with parsing JSON, or passing around `Map`s and making clients cast values to the right type manually. You also don't have to write model types yourself, because these are generated from the GraphQL definitions your app uses.
-Because generated types are query-specific, you can only access data that you actually specify as part of a query. If you don't ask for a particular field in a query, you can't access the corresponding property on the returned data structure.
+Because generated types are operation-specific, you can only access data that you actually specify as part of an operation. If you don't ask for a particular field in an operation, you can't access the corresponding property on the returned data structure.
-This library is designed primarily with Android in mind, but you can use it in any Java/Kotlin app, including multiplatform.
+This library is designed primarily with Android in mind, but you can use it in any Kotlin (including multiplatform) and Java app.
## Features
-* Java and Kotlin Multiplatform code generation
+* Kotlin Multiplatform and Java code generation
* Queries, Mutations and Subscriptions
* Reflection-free parsing
* Normalized cache
@@ -34,10 +34,10 @@ This library is designed primarily with Android in mind, but you can use it in a
* Auto Persisted Queries
* Query batching
* File uploads
-* Espresso IdlingResource
* Fake models for tests
* AppSync and graphql-ws websockets
* GraphQL AST parser
+* Plugin for Android Studio and IntelliJ
## Multiplatform
@@ -45,14 +45,14 @@ Apollo Kotlin is a [Kotlin Multiplatform](https://kotlinlang.org/docs/multiplatf
Here's the current matrix of supported features per platform:
-| | `jvm` | `Appleยน` | `js` | `linuxX64`
-| --- | :---: | :---: |:----:| :---: |
-| `apollo-api` (models)|โ |โ | โ |โ |
-| `apollo-runtime` (network, query batching, apq, ...) |โ |โ | โ |๐ซ|
-| `apollo-normalized-cache` |โ |โ | โ |๐ซ|
-| `apollo-adapters` |โ |โ | โ |๐ซ|
-| `apollo-normalized-cache-sqlite` |โ |โ | ๐ซ |๐ซ|
-| `apollo-http-cache` |โ |๐ซ| ๐ซ |๐ซ|
+| | `jvm` | `Appleยน` | `js` | `wasmJs` | `linuxX64` |
+|------------------------------------------------------|:-----:|:--------:|:----:|:--------:|:----------:|
+| `apollo-api` (models) | โ | โ | โ | โ | โ |
+| `apollo-runtime` (network, query batching, apq, ...) | โ | โ | โ | โ | ๐ซ |
+| `apollo-normalized-cache` | โ | โ | โ | โ | ๐ซ |
+| `apollo-adapters` | โ | โ | โ | โ | ๐ซ |
+| `apollo-normalized-cache-sqlite` | โ | โ | ๐ซ | ๐ซ | ๐ซ |
+| `apollo-http-cache` | โ | ๐ซ | ๐ซ | ๐ซ | ๐ซ |
ยน: Apple currently includes:
@@ -80,7 +80,7 @@ Check [the project website](https://www.apollographql.com/docs/android/) for in
## Getting started
-If you are new to GraphQL, check out [the tutorial](https://www.apollographql.com/docs/android/tutorial/00-introduction/) that will guide you through building an Android app using Apollo, Kotlin and coroutines.
+If you are new to GraphQL, check out [the tutorial](https://www.apollographql.com/docs/android/tutorial/00-introduction/) that will guide you through building an Android app using Apollo.
If you'd like to add Apollo Kotlin to an existing project, follow these steps:
@@ -88,7 +88,7 @@ Add the plugin to your `build.gradle.kts`:
```kotlin
plugins {
- id("com.apollographql.apollo3") version "4.0.0-beta.5"
+ id("com.apollographql.apollo3") version "4.0.0-beta.7"
}
```
@@ -96,7 +96,7 @@ Add the runtime dependency:
```kotlin
dependencies {
- implementation("com.apollographql.apollo3:apollo-runtime:4.0.0-beta.5")
+ implementation("com.apollographql.apollo3:apollo-runtime:4.0.0-beta.7")
}
```
@@ -121,7 +121,7 @@ By default, Apollo Kotlin requires a schema in your module's `src/main/graphql`
cp ${schema} ${module}/src/main/graphql/
```
-Write a query in a `${module}/src/main/graphql/GetRepository.graphql` file:
+Write a query in a `${module}/src/main/graphql/HeroQuery.graphql` file:
```graphql
query HeroQuery($id: String!) {
@@ -164,9 +164,8 @@ Some platforms have specific runtime requirements:
At build time, it requires:
* Gradle 8.0+
-* Kotlin 1.8+ for JVM projects
-* Kotlin 1.9+ for native projects
-* Kotlin 2.0+ for JS projects
+* Kotlin 1.9+ for JVM projects
+* Kotlin 2.0+ for native, JS, and Wasm projects
## Proguard / R8 configuration
@@ -174,7 +173,7 @@ As the code generated by Apollo Kotlin doesn't use any reflection, it can safely
## Android Studio / IntelliJ plugin
-An experimental [plugin for Android Studio and IntelliJ](https://plugins.jetbrains.com/plugin/20645-apollo-graphql) is available to help you work with Apollo Kotlin, providing automatic code generation, integration with the [GraphQL IntelliJ Plugin](https://plugins.jetbrains.com/plugin/8097-js-graphql), navigation to GraphQL definitions, migration helpers, and more.
+A [plugin for Android Studio and IntelliJ](https://plugins.jetbrains.com/plugin/20645-apollo-graphql) is available to help you work with Apollo Kotlin, providing automatic code generation, integration with the [GraphQL IntelliJ Plugin](https://plugins.jetbrains.com/plugin/8097-js-graphql), navigation to GraphQL definitions, migration helpers, and more.
Installation instructions and more information can be found [here](https://github.com/apollographql/apollo-kotlin/tree/main/intellij-plugin).
@@ -188,7 +187,7 @@ Releases are hosted on [Maven Central](https://repo1.maven.org/maven2/com/apollo
```kotlin
plugins {
- id("com.apollographql.apollo3") version "4.0.0-beta.5"
+ id("com.apollographql.apollo3") version "4.0.0-beta.7"
}
repositories {
@@ -196,13 +195,13 @@ repositories {
}
dependencies {
- implementation("com.apollographql.apollo3:apollo-runtime:4.0.0-beta.5")
+ implementation("com.apollographql.apollo3:apollo-runtime:4.0.0-beta.7")
- // optional: if you want to use the normalized cache
- implementation("com.apollographql.apollo3:apollo-normalized-cache-sqlite:4.0.0-beta.5")
- // optional: if you just want the generated models and parsers and write your own HTTP code/cache code, you can remove apollo-runtime
+ // Optional: if you want to use the normalized cache
+ implementation("com.apollographql.apollo3:apollo-normalized-cache-sqlite:4.0.0-beta.7")
+ // Optional: if you just want the generated models and parsers and write your own HTTP code/cache code, you can remove apollo-runtime
// and use apollo-api instead
- implementation("com.apollographql.apollo3:apollo-api:4.0.0-beta.5")
+ implementation("com.apollographql.apollo3:apollo-api:4.0.0-beta.7")
}
```
@@ -233,7 +232,7 @@ pluginManagement {
}
```
-And then use the `4.0.0-beta.6-SNAPSHOT` version for the plugin and libraries.
+And then use the `4.0.0-beta.8-SNAPSHOT` version for the plugin and libraries.
These snapshots are updated on each push to `main`.
diff --git a/ROADMAP.md b/ROADMAP.md
index 295b4abb298..e9d64518c1a 100644
--- a/ROADMAP.md
+++ b/ROADMAP.md
@@ -1,6 +1,6 @@
# ๐ฎ Apollo Kotlin Roadmap
-**Last updated: 2024-04-19**
+**Last updated: 2024-05-16**
For up to date release notes, refer to the project [Changelog](https://github.com/apollographql/apollo-kotlin/blob/main/CHANGELOG.md).
diff --git a/benchmark/app/build.gradle.kts b/benchmark/app/build.gradle.kts
index 79841d12156..9a90b319aed 100644
--- a/benchmark/app/build.gradle.kts
+++ b/benchmark/app/build.gradle.kts
@@ -5,6 +5,7 @@ plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
id("com.apollographql.apollo3")
+ alias(libs.plugins.kotlin.compose)
}
android {
@@ -43,10 +44,6 @@ android {
buildFeatures {
compose = true
}
-
- composeOptions {
- kotlinCompilerExtensionVersion = libs.versions.compose.compiler.get()
- }
}
dependencies {
diff --git a/benchmark/microbenchmark/build.gradle.kts b/benchmark/microbenchmark/build.gradle.kts
index 2e07e60b4af..9c22229e35e 100644
--- a/benchmark/microbenchmark/build.gradle.kts
+++ b/benchmark/microbenchmark/build.gradle.kts
@@ -21,40 +21,25 @@ configure {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
-
- flavorDimensions += "stability"
- productFlavors {
- create("incubating") {
- dimension = "stability"
- testApplicationId = "com.apollographql.apollo3.benchmark.incubating"
- }
- create("stable") {
- dimension = "stability"
- testApplicationId = "com.apollographql.apollo3.benchmark.stable"
- }
- }
}
dependencies {
- implementation("com.apollographql.apollo3:apollo-runtime")
-
- listOf(
- "com.apollographql.apollo3:apollo-normalized-cache-api",
- "com.apollographql.apollo3:apollo-normalized-cache-sqlite",
- "com.apollographql.apollo3:apollo-normalized-cache"
- ).forEach {
- add("androidTestStableImplementation", it)
- add("androidTestIncubatingImplementation", "$it-incubating")
- }
+ implementation(libs.apollo.runtime)
implementation(libs.moshi)
ksp(libs.moshix.ksp)
androidTestImplementation(libs.benchmark.junit4)
androidTestImplementation(libs.androidx.test.core)
- androidTestImplementation("com.apollographql.apollo3:apollo-mockserver")
- androidTestImplementation("com.apollographql.apollo3:apollo-testing-support")
+ androidTestImplementation(libs.apollo.mockserver)
+ androidTestImplementation(libs.apollo.testingsupport)
+
+ // Stable cache
+ androidTestImplementation(libs.apollo.normalizedcache.sqlite)
+
+ // Incubating cache
+ androidTestImplementation(libs.apollo.normalizedcache.sqlite.incubating.snapshot)
}
java {
diff --git a/benchmark/microbenchmark/src/androidTestIncubating/kotlin/com/apollographql/apollo3/benchmark/ApolloStoreIncubatingTests.kt b/benchmark/microbenchmark/src/androidTest/java/com/apollographql/apollo3/benchmark/ApolloStoreIncubatingTests.kt
similarity index 88%
rename from benchmark/microbenchmark/src/androidTestIncubating/kotlin/com/apollographql/apollo3/benchmark/ApolloStoreIncubatingTests.kt
rename to benchmark/microbenchmark/src/androidTest/java/com/apollographql/apollo3/benchmark/ApolloStoreIncubatingTests.kt
index ef5301c931a..16f7d1bffd6 100644
--- a/benchmark/microbenchmark/src/androidTestIncubating/kotlin/com/apollographql/apollo3/benchmark/ApolloStoreIncubatingTests.kt
+++ b/benchmark/microbenchmark/src/androidTest/java/com/apollographql/apollo3/benchmark/ApolloStoreIncubatingTests.kt
@@ -8,10 +8,10 @@ import com.apollographql.apollo3.benchmark.Utils.dbName
import com.apollographql.apollo3.benchmark.Utils.operationBasedQuery
import com.apollographql.apollo3.benchmark.Utils.resource
import com.apollographql.apollo3.benchmark.test.R
-import com.apollographql.apollo3.cache.normalized.ApolloStore
-import com.apollographql.apollo3.cache.normalized.api.MemoryCacheFactory
-import com.apollographql.apollo3.cache.normalized.api.NormalizedCacheFactory
-import com.apollographql.apollo3.cache.normalized.sql.SqlNormalizedCacheFactory
+import com.apollographql.cache.normalized.ApolloStore
+import com.apollographql.cache.normalized.api.MemoryCacheFactory
+import com.apollographql.cache.normalized.api.NormalizedCacheFactory
+import com.apollographql.cache.normalized.sql.SqlNormalizedCacheFactory
import org.junit.Assert
import org.junit.Rule
import org.junit.Test
diff --git a/benchmark/microbenchmark/src/androidTestStable/kotlin/com/apollographql/apollo3/benchmark/ApolloStoreTests.kt b/benchmark/microbenchmark/src/androidTest/java/com/apollographql/apollo3/benchmark/ApolloStoreTests.kt
similarity index 97%
rename from benchmark/microbenchmark/src/androidTestStable/kotlin/com/apollographql/apollo3/benchmark/ApolloStoreTests.kt
rename to benchmark/microbenchmark/src/androidTest/java/com/apollographql/apollo3/benchmark/ApolloStoreTests.kt
index 20b1f79f4c2..5743fb08ffd 100644
--- a/benchmark/microbenchmark/src/androidTestStable/kotlin/com/apollographql/apollo3/benchmark/ApolloStoreTests.kt
+++ b/benchmark/microbenchmark/src/androidTest/java/com/apollographql/apollo3/benchmark/ApolloStoreTests.kt
@@ -50,7 +50,7 @@ class ApolloStoreTests {
threadPool.submit {
// Let each thread execute a few writes/reads
repeat(WORK_LOAD) {
- apolloStore.writeOperation(query, data)
+ apolloStore.writeOperationSync(query, data)
val data2 = apolloStore.readOperation(query)
Assert.assertEquals(data, data2)
}
diff --git a/benchmark/microbenchmark/src/androidTestIncubating/kotlin/com/apollographql/apollo3/benchmark/CacheIncubatingIntegrationTests.kt b/benchmark/microbenchmark/src/androidTest/java/com/apollographql/apollo3/benchmark/CacheIncubatingIntegrationTests.kt
similarity index 82%
rename from benchmark/microbenchmark/src/androidTestIncubating/kotlin/com/apollographql/apollo3/benchmark/CacheIncubatingIntegrationTests.kt
rename to benchmark/microbenchmark/src/androidTest/java/com/apollographql/apollo3/benchmark/CacheIncubatingIntegrationTests.kt
index f3f5bb40391..4b259c5d878 100644
--- a/benchmark/microbenchmark/src/androidTestIncubating/kotlin/com/apollographql/apollo3/benchmark/CacheIncubatingIntegrationTests.kt
+++ b/benchmark/microbenchmark/src/androidTest/java/com/apollographql/apollo3/benchmark/CacheIncubatingIntegrationTests.kt
@@ -9,17 +9,17 @@ import com.apollographql.apollo3.benchmark.Utils.dbName
import com.apollographql.apollo3.benchmark.Utils.operationBasedQuery
import com.apollographql.apollo3.benchmark.Utils.resource
import com.apollographql.apollo3.benchmark.test.R
-import com.apollographql.apollo3.cache.normalized.ApolloStore
-import com.apollographql.apollo3.cache.normalized.FetchPolicy
-import com.apollographql.apollo3.cache.normalized.api.MemoryCacheFactory
-import com.apollographql.apollo3.cache.normalized.api.NormalizedCacheFactory
-import com.apollographql.apollo3.cache.normalized.fetchPolicy
-import com.apollographql.apollo3.cache.normalized.sql.SqlNormalizedCacheFactory
-import com.apollographql.apollo3.cache.normalized.store
-import com.apollographql.apollo3.mockserver.MockRequestBase
-import com.apollographql.apollo3.mockserver.MockResponse
-import com.apollographql.apollo3.mockserver.MockServer
-import com.apollographql.apollo3.mockserver.MockServerHandler
+import com.apollographql.cache.normalized.ApolloStore
+import com.apollographql.cache.normalized.FetchPolicy
+import com.apollographql.cache.normalized.api.MemoryCacheFactory
+import com.apollographql.cache.normalized.api.NormalizedCacheFactory
+import com.apollographql.cache.normalized.fetchPolicy
+import com.apollographql.cache.normalized.sql.SqlNormalizedCacheFactory
+import com.apollographql.cache.normalized.store
+import com.apollographql.mockserver.MockRequestBase
+import com.apollographql.mockserver.MockResponse
+import com.apollographql.mockserver.MockServer
+import com.apollographql.mockserver.MockServerHandler
import com.apollographql.apollo3.testing.MapTestNetworkTransport
import com.apollographql.apollo3.testing.registerTestResponse
import kotlinx.coroutines.joinAll
diff --git a/benchmark/microbenchmark/src/androidTestIncubating/kotlin/com/apollographql/apollo3/benchmark/CacheIncubatingTests.kt b/benchmark/microbenchmark/src/androidTest/java/com/apollographql/apollo3/benchmark/CacheIncubatingTests.kt
similarity index 80%
rename from benchmark/microbenchmark/src/androidTestIncubating/kotlin/com/apollographql/apollo3/benchmark/CacheIncubatingTests.kt
rename to benchmark/microbenchmark/src/androidTest/java/com/apollographql/apollo3/benchmark/CacheIncubatingTests.kt
index c0c606b3599..c4ea6d1c08d 100644
--- a/benchmark/microbenchmark/src/androidTestIncubating/kotlin/com/apollographql/apollo3/benchmark/CacheIncubatingTests.kt
+++ b/benchmark/microbenchmark/src/androidTest/java/com/apollographql/apollo3/benchmark/CacheIncubatingTests.kt
@@ -2,10 +2,7 @@ package com.apollographql.apollo3.benchmark
import androidx.benchmark.junit4.BenchmarkRule
import androidx.benchmark.junit4.measureRepeated
-import androidx.test.platform.app.InstrumentationRegistry
import com.apollographql.apollo3.api.CustomScalarAdapters
-import com.apollographql.apollo3.api.Executable
-import com.apollographql.apollo3.api.Operation
import com.apollographql.apollo3.api.Query
import com.apollographql.apollo3.api.json.jsonReader
import com.apollographql.apollo3.api.parseJsonResponse
@@ -16,26 +13,20 @@ import com.apollographql.apollo3.benchmark.Utils.registerCacheSize
import com.apollographql.apollo3.benchmark.Utils.resource
import com.apollographql.apollo3.benchmark.Utils.responseBasedQuery
import com.apollographql.apollo3.benchmark.test.R
-import com.apollographql.apollo3.cache.normalized.api.CacheHeaders
-import com.apollographql.apollo3.cache.normalized.api.CacheKeyGenerator
-import com.apollographql.apollo3.cache.normalized.api.CacheResolver
-import com.apollographql.apollo3.cache.normalized.api.DefaultRecordMerger
-import com.apollographql.apollo3.cache.normalized.api.FieldPolicyCacheResolver
-import com.apollographql.apollo3.cache.normalized.api.MemoryCacheFactory
-import com.apollographql.apollo3.cache.normalized.api.ReadOnlyNormalizedCache
-import com.apollographql.apollo3.cache.normalized.api.Record
-import com.apollographql.apollo3.cache.normalized.api.TypePolicyCacheKeyGenerator
-import com.apollographql.apollo3.cache.normalized.api.normalize
-import com.apollographql.apollo3.cache.normalized.api.readDataFromCache
-import com.apollographql.apollo3.cache.normalized.sql.SqlNormalizedCacheFactory
+import com.apollographql.cache.normalized.api.CacheHeaders
+import com.apollographql.cache.normalized.api.DefaultRecordMerger
+import com.apollographql.cache.normalized.api.FieldPolicyCacheResolver
+import com.apollographql.cache.normalized.api.MemoryCacheFactory
+import com.apollographql.cache.normalized.api.TypePolicyCacheKeyGenerator
+import com.apollographql.cache.normalized.api.normalize
+import com.apollographql.cache.normalized.api.readDataFromCache
+import com.apollographql.cache.normalized.sql.SqlNormalizedCacheFactory
import kotlinx.coroutines.runBlocking
import org.junit.Assert
import org.junit.Rule
import org.junit.Test
-import java.lang.reflect.Method
import java.util.concurrent.Executors
-@Suppress("UNCHECKED_CAST")
class CacheIncubatingTests {
@get:Rule
val benchmarkRule = BenchmarkRule()
@@ -158,4 +149,4 @@ class CacheIncubatingTests {
private const val CONCURRENCY = 15
private const val WORK_LOAD = 15
}
-}
\ No newline at end of file
+}
diff --git a/benchmark/microbenchmark/src/androidTestStable/kotlin/com/apollographql/apollo3/benchmark/CacheIntegrationTests.kt b/benchmark/microbenchmark/src/androidTest/java/com/apollographql/apollo3/benchmark/CacheIntegrationTests.kt
similarity index 94%
rename from benchmark/microbenchmark/src/androidTestStable/kotlin/com/apollographql/apollo3/benchmark/CacheIntegrationTests.kt
rename to benchmark/microbenchmark/src/androidTest/java/com/apollographql/apollo3/benchmark/CacheIntegrationTests.kt
index a088efaed44..4a14ae376fd 100644
--- a/benchmark/microbenchmark/src/androidTestStable/kotlin/com/apollographql/apollo3/benchmark/CacheIntegrationTests.kt
+++ b/benchmark/microbenchmark/src/androidTest/java/com/apollographql/apollo3/benchmark/CacheIntegrationTests.kt
@@ -16,10 +16,10 @@ import com.apollographql.apollo3.cache.normalized.api.NormalizedCacheFactory
import com.apollographql.apollo3.cache.normalized.fetchPolicy
import com.apollographql.apollo3.cache.normalized.sql.SqlNormalizedCacheFactory
import com.apollographql.apollo3.cache.normalized.store
-import com.apollographql.apollo3.mockserver.MockRequestBase
-import com.apollographql.apollo3.mockserver.MockResponse
-import com.apollographql.apollo3.mockserver.MockServer
-import com.apollographql.apollo3.mockserver.MockServerHandler
+import com.apollographql.mockserver.MockRequestBase
+import com.apollographql.mockserver.MockResponse
+import com.apollographql.mockserver.MockServer
+import com.apollographql.mockserver.MockServerHandler
import com.apollographql.apollo3.testing.MapTestNetworkTransport
import com.apollographql.apollo3.testing.registerTestResponse
import kotlinx.coroutines.joinAll
diff --git a/benchmark/microbenchmark/src/androidTestStable/kotlin/com/apollographql/apollo3/benchmark/CacheTests.kt b/benchmark/microbenchmark/src/androidTest/java/com/apollographql/apollo3/benchmark/CacheTests.kt
similarity index 100%
rename from benchmark/microbenchmark/src/androidTestStable/kotlin/com/apollographql/apollo3/benchmark/CacheTests.kt
rename to benchmark/microbenchmark/src/androidTest/java/com/apollographql/apollo3/benchmark/CacheTests.kt
diff --git a/benchmark/microbenchmark/src/androidTestStable/kotlin/com/apollographql/apollo3/benchmark/JsonTests.kt b/benchmark/microbenchmark/src/androidTest/java/com/apollographql/apollo3/benchmark/JsonTests.kt
similarity index 100%
rename from benchmark/microbenchmark/src/androidTestStable/kotlin/com/apollographql/apollo3/benchmark/JsonTests.kt
rename to benchmark/microbenchmark/src/androidTest/java/com/apollographql/apollo3/benchmark/JsonTests.kt
diff --git a/benchmark/settings.gradle.kts b/benchmark/settings.gradle.kts
index 948ad2898a5..3d1b8b0d7d2 100644
--- a/benchmark/settings.gradle.kts
+++ b/benchmark/settings.gradle.kts
@@ -2,8 +2,8 @@ pluginManagement {
includeBuild("build-logic")
}
plugins {
- id("com.gradle.develocity") version "3.17.2" // sync with libraries.toml
- id("com.gradle.common-custom-user-data-gradle-plugin") version "2.0.1"
+ id("com.gradle.develocity") version "3.17.5" // sync with libraries.toml
+ id("com.gradle.common-custom-user-data-gradle-plugin") version "2.0.2"
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
}
@@ -23,9 +23,9 @@ apply(from = "../gradle/ge.gradle")
listOf(pluginManagement.repositories, dependencyResolutionManagement.repositories).forEach {
it.apply {
maven {
- url = uri("../build/localMaven")
+ url = uri("https://s01.oss.sonatype.org/content/repositories/snapshots/")
}
}
}
-includeBuild("../")
\ No newline at end of file
+includeBuild("../")
diff --git a/build-logic/build.gradle.kts b/build-logic/build.gradle.kts
index 97e86200629..8ad9afaa2af 100644
--- a/build-logic/build.gradle.kts
+++ b/build-logic/build.gradle.kts
@@ -22,6 +22,7 @@ dependencies {
implementation(libs.kotlinx.benchmark)
implementation(libs.dokkatoo)
+ implementation(libs.apollo.execution.gradle.plugin)
// We add all the plugins to the classpath here so that they are loaded with proper conflict resolution
// See https://github.com/gradle/gradle/issues/4741
diff --git a/build-logic/settings.gradle.kts b/build-logic/settings.gradle.kts
index c7ce3ed431e..b443e588d2d 100644
--- a/build-logic/settings.gradle.kts
+++ b/build-logic/settings.gradle.kts
@@ -1,6 +1,6 @@
plugins {
- id("com.gradle.develocity") version "3.17.2" // sync with libraries.toml
- id("com.gradle.common-custom-user-data-gradle-plugin") version "2.0.1"
+ id("com.gradle.develocity") version "3.17.5" // sync with libraries.toml
+ id("com.gradle.common-custom-user-data-gradle-plugin") version "2.0.2"
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
}
diff --git a/build-logic/src/main/kotlin/Android.kt b/build-logic/src/main/kotlin/Android.kt
index d48af7eee16..46f60a73b13 100644
--- a/build-logic/src/main/kotlin/Android.kt
+++ b/build-logic/src/main/kotlin/Android.kt
@@ -41,6 +41,4 @@ fun Project.configureAndroid(
}
}
}
-
- dependencies.add("implementation", getCatalogLib("androidx.multidex"))
}
diff --git a/build-logic/src/main/kotlin/CompilerOptions.kt b/build-logic/src/main/kotlin/CompilerOptions.kt
index 084c347423d..9a49436adf2 100644
--- a/build-logic/src/main/kotlin/CompilerOptions.kt
+++ b/build-logic/src/main/kotlin/CompilerOptions.kt
@@ -16,14 +16,22 @@ import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.dsl.KotlinNativeCompilerOptions
import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension
-import org.jetbrains.kotlin.gradle.dsl.KotlinVersion
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask
/**
* @param target the JVM version we want to be compatible with (bytecode + bootstrap classpath)
*/
-fun KotlinCommonCompilerOptions.configure(target: Int) {
+fun KotlinCommonCompilerOptions.configure(target: Int, kotlinCompilerOptions: KotlinCompilerOptions, isAndroid: Boolean) {
+ val actualTarget = when {
+ isAndroid -> {
+ // https://blog.blundellapps.co.uk/setting-jdk-level-in-android-gradle-builds/
+ // D8 can dex Java17 bytecode
+ 17
+ }
+ else -> target
+ }
+
freeCompilerArgs.add("-Xexpect-actual-classes")
/**
@@ -34,14 +42,17 @@ fun KotlinCommonCompilerOptions.configure(target: Int) {
freeCompilerArgs.add("-opt-in=com.apollographql.apollo3.annotations.ApolloExperimental")
freeCompilerArgs.add("-opt-in=com.apollographql.apollo3.annotations.ApolloInternal")
- apiVersion.set(KotlinVersion.KOTLIN_1_9)
- languageVersion.set(KotlinVersion.KOTLIN_1_9)
+ apiVersion.set(kotlinCompilerOptions.version)
+ languageVersion.set(kotlinCompilerOptions.version)
when (this) {
is KotlinJvmCompilerOptions -> {
freeCompilerArgs.add("-Xjvm-default=all")
- freeCompilerArgs.add("-Xjdk-release=${target.toJvmTarget().target}")
- jvmTarget.set(target.toJvmTarget())
+ if (!isAndroid) {
+ // See https://cs.android.com/android-studio/platform/tools/base/+/mirror-goog-studio-main:build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/JavaCompileUtils.kt;l=410?q=Using%20%27--release%27%20option%20for%20JavaCompile%20is%20not%20supported%20because%20it%20prevents%20the%20Android%20Gradle%20plugin
+ freeCompilerArgs.add("-Xjdk-release=${actualTarget.toJvmTarget().target}")
+ }
+ jvmTarget.set(actualTarget.toJvmTarget())
}
is KotlinNativeCompilerOptions -> {
@@ -94,21 +105,12 @@ val Project.androidExtensionOrNull: BaseExtension?
return (extensions.findByName("android") as? BaseExtension)
}
-fun Project.configureJavaAndKotlinCompilers(jvmTarget: Int?) {
+fun Project.configureJavaAndKotlinCompilers(jvmTarget: Int?, kotlinCompilerOptions: KotlinCompilerOptions) {
@Suppress("NAME_SHADOWING")
val jvmTarget = jvmTarget?: 8
kotlinExtensionOrNull?.forEachCompilerOptions { isAndroid ->
- val target = when {
- isAndroid -> {
- // https://blog.blundellapps.co.uk/setting-jdk-level-in-android-gradle-builds/
- // D8 can dex Java17 bytecode
- 17
- }
- else -> jvmTarget
- }
-
- configure(target)
+ configure(jvmTarget, kotlinCompilerOptions, isAndroid)
}
project.tasks.withType(JavaCompile::class.java).configureEach {
// For JVM only modules, this dictates the "org.gradle.jvm.version" Gradle attribute
diff --git a/build-logic/src/main/kotlin/Mpp.kt b/build-logic/src/main/kotlin/Mpp.kt
index 5a6cb070878..cabe19d194b 100644
--- a/build-logic/src/main/kotlin/Mpp.kt
+++ b/build-logic/src/main/kotlin/Mpp.kt
@@ -120,29 +120,29 @@ fun Project.configureMpp(
* Current Graph is something like so:
*
* ```mermaid
- * graph TB
- * commonMain --> concurrentMain
- * commonMain --> linuxMain
- * commonMain --> jsMain
- * concurrentMain --> jvmMain
- * concurrentMain --> appleMain
- * appleMain --> macosX64
- * appleMain --> macosArm64
- * appleMain --> iosArm64
- * appleMain --> iosX64
- * appleMain --> iosSimulatorArm64
- * appleMain --> watchosArm32
- * appleMain --> watchosArm64
- * appleMain --> watchosSimulatorArm64
- * appleMain --> tvosArm64
- * appleMain --> tvosX64
- * appleMain --> tvosSimulatorArm64
- *
- * classDef kotlinPurple fill:#A97BFF,stroke:#333,stroke-width:2px,color:#333
- * classDef javaOrange fill:#b07289,stroke:#333,stroke-width:2px,color:#333
- * classDef gray fill:#AAA,stroke:#333,stroke-width:2px,color:#333
- * class jvmJavaCodeGen,macOsArm64Test,jvmTest,jsTest kotlinPurple
- * class commonTest javaOrange
+ * graph
+ * common --> fileSystem
+ * fileSystem --> concurrent
+ * fileSystem --> jsCommon
+ * concurrent --> native
+ * concurrent --> jvmCommon
+ * jsCommon --> js
+ * jsCommon --> wasmJs
+ * jvmCommon --> jvm
+ * jvmCommon --> android
+ * native --> linux
+ * native --> apple
+ * apple --> macosX64
+ * apple --> macosArm64
+ * apple --> iosArm64
+ * apple --> iosX64
+ * apple --> iosSimulatorArm64
+ * apple --> watchosArm32
+ * apple --> watchosArm64
+ * apple --> watchosSimulatorArm64
+ * apple --> tvosArm64
+ * apple --> tvosX64
+ * apple --> tvosSimulatorArm64
* ```
*/
@OptIn(ExperimentalKotlinGradlePluginApi::class)
diff --git a/build-logic/src/main/kotlin/Testing.kt b/build-logic/src/main/kotlin/Testing.kt
index bdae5755861..cc60ac2d4c2 100644
--- a/build-logic/src/main/kotlin/Testing.kt
+++ b/build-logic/src/main/kotlin/Testing.kt
@@ -1,4 +1,4 @@
-import com.gradle.enterprise.gradleplugin.testretry.retry
+import com.gradle.develocity.agent.gradle.test.DevelocityTestConfiguration
import org.gradle.api.Project
import org.gradle.api.tasks.PathSensitivity
import org.gradle.api.tasks.testing.AbstractTestTask
@@ -14,10 +14,10 @@ fun Project.configureTesting() {
forwardEnv("testFilter")
forwardEnv("codegenModels")
}
-
+
pluginManager.withPlugin("org.jetbrains.kotlin.jvm") {
tasks.withType(Test::class.java) {
- retry {
+ extensions.getByType(DevelocityTestConfiguration::class.java).testRetry {
if (isCIBuild()) {
maxRetries.set(3)
failOnPassedAfterRetry.set(true)
@@ -54,6 +54,7 @@ private fun Project.addTestDependencies() {
}
}
}
+
is KotlinJvmProjectExtension -> {
dependencies.add("testImplementation", getCatalogLib("kotlin.test"))
}
diff --git a/build-logic/src/main/kotlin/api.kt b/build-logic/src/main/kotlin/api.kt
index ab02a117159..0ef1a972959 100644
--- a/build-logic/src/main/kotlin/api.kt
+++ b/build-logic/src/main/kotlin/api.kt
@@ -1,15 +1,19 @@
-
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.tasks.TaskProvider
import org.gradle.jvm.tasks.Jar
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
+import org.jetbrains.kotlin.gradle.dsl.KotlinVersion
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin
import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinNpmInstallTask
class AndroidOptions(
- val withCompose: Boolean
+ val withCompose: Boolean,
+)
+
+class KotlinCompilerOptions(
+ val version: KotlinVersion = KotlinVersion.KOTLIN_2_0,
)
fun Project.apolloLibrary(
@@ -21,7 +25,8 @@ fun Project.apolloLibrary(
withJvm: Boolean = true,
withWasm: Boolean = true,
androidOptions: AndroidOptions? = null,
- publish: Boolean = true
+ publish: Boolean = true,
+ kotlinCompilerOptions: KotlinCompilerOptions = KotlinCompilerOptions(),
) {
group = property("GROUP")!!
version = property("VERSION_NAME")!!
@@ -30,7 +35,7 @@ fun Project.apolloLibrary(
configureAndroid(namespace, androidOptions)
}
commonSetup()
- configureJavaAndKotlinCompilers(jvmTarget)
+ configureJavaAndKotlinCompilers(jvmTarget, kotlinCompilerOptions)
addOptIn(
"com.apollographql.apollo3.annotations.ApolloExperimental",
@@ -74,9 +79,10 @@ fun Project.apolloTest(
withJvm: Boolean = true,
appleTargets: Set = setOf(hostTarget),
browserTest: Boolean = false,
+ kotlinCompilerOptions: KotlinCompilerOptions = KotlinCompilerOptions(),
) {
commonSetup()
- configureJavaAndKotlinCompilers(null)
+ configureJavaAndKotlinCompilers(null, kotlinCompilerOptions)
addOptIn(
"com.apollographql.apollo3.annotations.ApolloExperimental",
"com.apollographql.apollo3.annotations.ApolloInternal",
diff --git a/build.gradle.kts b/build.gradle.kts
index 625f9d2f9bb..27128de78fe 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,4 +1,5 @@
import JapiCmp.configureJapiCmp
+import kotlinx.validation.ExperimentalBCVApi
import org.jetbrains.kotlin.gradle.targets.native.tasks.KotlinNativeHostTest
plugins {
@@ -85,9 +86,6 @@ tasks.register("ciTestsNoGradle") {
* Update the database schemas in CI
*/
dependsOn(":apollo-normalized-cache-sqlite:generateCommonMainJsonDatabaseSchema")
- dependsOn(":apollo-normalized-cache-sqlite-incubating:generateCommonMainJsonDatabaseSchema")
- dependsOn(":apollo-normalized-cache-sqlite-incubating:generateCommonMainBlobDatabaseSchema")
- dependsOn(":apollo-normalized-cache-sqlite-incubating:generateCommonMainBlob2DatabaseSchema")
doLast {
if (isCIBuild()) {
@@ -122,6 +120,9 @@ rootProject.configureNode()
rootProject.configureJapiCmp()
configure {
+ @OptIn(ExperimentalBCVApi::class)
+ klib.enabled = true
+
ignoredPackages.addAll(
listOf(
/**
@@ -168,4 +169,4 @@ tasks.register("rmbuild") {
}
}
-apolloRoot(ciBuild)
\ No newline at end of file
+apolloRoot(ciBuild)
diff --git a/design-docs/Glossary.md b/design-docs/Glossary.md
index fcc41654bf2..860d3a2a9b9 100644
--- a/design-docs/Glossary.md
+++ b/design-docs/Glossary.md
@@ -1,9 +1,6 @@
-# Codegen Glossary
-
-## Glossary
-
-A small Glossary of the terms used during codegen. The [GraphQL Spec](https://spec.graphql.org/draft/) does a nice job of defining the common terms like `Field`, `SelectionSet`, etc... so I'm not adding these terms here. But it misses some concepts that we bumped into during codegen and that I'm trying to clarify here.
+# Glossary
+The [GraphQL Spec](https://spec.graphql.org/draft/) does a nice job of defining common terms like `Field`, `SelectionSet`, etc. but here are a few other concepts that the library deals with, and their definition.
### Response shape
@@ -105,3 +102,26 @@ Example:
### Polymorphic field
A field that can take several shapes
+
+### Record
+
+A shallow map of a response object. Nested objects in the map values are replaced by a cache reference to another Record.
+
+### Cache key
+
+A unique identifier for a Record.
+By default it is the path formed by all the field keys from the root of the query to the field referencing the Record.
+To avoid duplication the Cache key can also be computed from the Record contents, usually using its key fields.
+
+### Field key
+
+A key that uniquely identifies a field within a Record. By default composed of the field name and the arguments passed to it.
+
+### Key fields
+
+Fields that are used to compute a Cache key for an object.
+
+### Pagination arguments
+
+Field arguments that control pagination, e.g. `first`, `after`, etc. They should be omitted when computing a field key so different pages can be merged into the same field.
+
diff --git a/design-docs/Normalized cache overview.md b/design-docs/Normalized cache overview.md
index 7ba4fb34712..6bd1b52e692 100644
--- a/design-docs/Normalized cache overview.md
+++ b/design-docs/Normalized cache overview.md
@@ -93,7 +93,7 @@ An example:
-
Key
+
Cache key
Record
@@ -217,7 +217,7 @@ An instance is created when building the `ApolloClient` and held by the `ApolloC
## Record merging
-When a `Record` is stored in the cache, it is _merged_ with the existing one at the same key (if any):
+When a `Record` is stored in the cache, it is _merged_ with the existing one at the same cache key (if any):
- existing fields are replaced with the new value
- new fields are added
diff --git a/design-docs/Normalized cache pagination.md b/design-docs/Normalized cache pagination.md
index 6fa93fadffc..3311d071ebd 100644
--- a/design-docs/Normalized cache pagination.md
+++ b/design-docs/Normalized cache pagination.md
@@ -210,7 +210,7 @@ If your schema uses a different pagination style, you can still use the paginati
#### Pagination arguments
-The `@fieldPolicy` directive has a `paginationArgs` argument that can be used to specify the arguments that should be omitted from the cache key.
+The `@fieldPolicy` directive has a `paginationArgs` argument that can be used to specify the arguments that should be omitted from the field key.
Going back to the example above with `usersPage`:
@@ -220,6 +220,9 @@ extend type Query
@fieldPolicy(forField: "usersPage" paginationArgs: "page")
```
+> [!NOTE]
+> This can also be done programmatically by configuring the `ApolloStore` with a `FieldKeyGenerator` implementation.
+
With that in place, after fetching the first page, the cache will look like this:
| Cache Key | Record |
@@ -228,7 +231,7 @@ With that in place, after fetching the first page, the cache will look like this
| user:1 | id: 1, name: John Smith |
| user:2 | id: 2, name: Jane Doe |
-Notice how the cache key no longer includes the `page` argument, which means watching `UsersPage(page = 1)` (or any page) is enough to observe the whole list.
+The field key no longer includes the `page` argument, which means watching `UsersPage(page = 1)` or any page will observe the same list.
Here's what happens when fetching the second page:
@@ -240,13 +243,13 @@ Here's what happens when fetching the second page:
| user:3 | id: 3, name: Peter Parker |
| user:4 | id: 4, name: Bruce Wayne |
-We can see that the field containing the first page was overwritten by the second page.
+The field containing the first page was overwritten by the second page.
-This is because the cache key is now the same for all pages.
+This is because the field key is now the same for all pages and the default merging strategy is to overwrite existing fields with the new value.
#### Record merging
-To fix this we need to supply the store with a piece of code that can merge new pages with the existing list.
+To fix this we need to supply the store with a piece of code that can merge the lists in a sensible way.
This is done by passing a `RecordMerger` to the `ApolloStore` constructor:
```kotlin
@@ -266,11 +269,11 @@ val apolloStore = ApolloStore(
normalizedCacheFactory = cacheFactory,
cacheKeyGenerator = TypePolicyCacheKeyGenerator,
apolloResolver = FieldPolicyApolloResolver,
- recordMerger = FieldRecordMerger(MyFieldMerger)
+ recordMerger = FieldRecordMerger(MyFieldMerger), // Configure the store with the custom merger
)
```
-With this, the cache will look like this after fetching the second page:
+With this, the cache will be as expected after fetching the second page:
| Cache Key | Record |
|------------|-------------------------------------------------------------------------------|
@@ -280,13 +283,13 @@ With this, the cache will look like this after fetching the second page:
| user:3 | id: 3, name: Peter Parker |
| user:4 | id: 4, name: Bruce Wayne |
-The `RecordMerger` shown above is simplistic: it can only append new pages to the end of the existing list.
-
-A more sophisticated implementation could look at the contents of the incoming page and decide where to append / insert the items into the existing list.
+The `RecordMerger` shown above is simplistic: it will always append new items to the end of the existing list.
+In a real app, we need to look at the contents of the incoming page and decide if and where to append / insert the items.
-To do that it is often necessary to have access to the arguments used to fetch a record inside the `RecordMerger`, to decide where to insert the new items.
+To do that it is usually necessary to have access to the arguments that were used to fetch the existing/incoming lists (e.g. the page number), to decide what to do with the new items.
+For instance if the existing list is for page 1 and the incoming one is for page 2, we should append.
-Fields in records can actually have arbitrary metadata associated with them, in addition to their values. We'll use this to implement more sophisticated merging.
+Fields in records can have arbitrary metadata attached to them, in addition to their value. We'll use this to implement a more capable merging strategy.
#### Metadata
@@ -307,10 +310,10 @@ This is done by passing a `MetadataGenerator` to the `ApolloStore` constructor:
```kotlin
class ConnectionMetadataGenerator : MetadataGenerator {
@Suppress("UNCHECKED_CAST")
- override fun metadataForObject(obj: Any?, context: MetadataGeneratorContext): Map {
+ override fun metadataForObject(obj: ApolloJsonElement, context: MetadataGeneratorContext): Map {
if (context.field.type.rawType().name == "UserConnection") {
- obj as Map
- val edges = obj["edges"] as List