diff --git a/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/api/CacheResolver.kt b/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/api/CacheResolver.kt index 6a578b47..9032bdde 100644 --- a/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/api/CacheResolver.kt +++ b/normalized-cache/src/commonMain/kotlin/com/apollographql/cache/normalized/api/CacheResolver.kt @@ -1,6 +1,8 @@ package com.apollographql.cache.normalized.api import com.apollographql.apollo.api.CompiledField +import com.apollographql.apollo.api.CompiledListType +import com.apollographql.apollo.api.CompiledNotNullType import com.apollographql.apollo.api.Executable import com.apollographql.apollo.api.MutableExecutionOptions import com.apollographql.apollo.exception.CacheMissException @@ -230,12 +232,28 @@ class CacheControlCacheResolver( */ object FieldPolicyCacheResolver : CacheResolver { override fun resolveField(context: ResolverContext): Any? { - val keyArgsValues = context.field.argumentValues(context.variables) { it.definition.isKey }.values.map { it.toString() } - - if (keyArgsValues.isNotEmpty()) { - return CacheKey(context.field.type.rawType().name, keyArgsValues) + val keyArgsValues = context.field.argumentValues(context.variables) { it.definition.isKey }.values + if (keyArgsValues.isEmpty()) { + return DefaultCacheResolver.resolveField(context) } - - return DefaultCacheResolver.resolveField(context) + var type = context.field.type + if (type is CompiledNotNullType) { + type = type.ofType + } + if (type is CompiledListType) { + // Only support flat lists + if (type.ofType !is CompiledListType && !(type.ofType is CompiledNotNullType && (type.ofType as CompiledNotNullType).ofType is CompiledListType)) { + // Only support single key argument which is a flat list + if (keyArgsValues.size == 1) { + val keyArgsValue = keyArgsValues.first() as? List<*> + if (keyArgsValue != null && keyArgsValue.firstOrNull() !is List<*>) { + return keyArgsValue.map { + CacheKey(type.rawType().name, it.toString()) + } + } + } + } + } + return CacheKey(type.rawType().name, keyArgsValues.map { it.toString() }) } } diff --git a/tests/normalized-cache/src/commonMain/graphql/declarativecache/extra.graphqls b/tests/normalized-cache/src/commonMain/graphql/declarativecache/extra.graphqls index 231ec35c..39fb78a6 100644 --- a/tests/normalized-cache/src/commonMain/graphql/declarativecache/extra.graphqls +++ b/tests/normalized-cache/src/commonMain/graphql/declarativecache/extra.graphqls @@ -2,7 +2,10 @@ extend type Author @typePolicy(keyFields: "firstName lastName") extend type Book @typePolicy(keyFields: "isbn") -extend type Query @fieldPolicy(forField: "book", keyArgs: "isbn") @fieldPolicy(forField: "author", keyArgs: "firstName lastName") +extend type Query +@fieldPolicy(forField: "book", keyArgs: "isbn") +@fieldPolicy(forField: "author", keyArgs: "firstName lastName") +@fieldPolicy(forField: "books", keyArgs: "isbns") interface Node @typePolicy(keyFields: "id") { id: ID! diff --git a/tests/normalized-cache/src/commonTest/kotlin/declarativecache/DeclarativeCacheTest.kt b/tests/normalized-cache/src/commonTest/kotlin/declarativecache/DeclarativeCacheTest.kt index 97fd64f7..655f6acc 100644 --- a/tests/normalized-cache/src/commonTest/kotlin/declarativecache/DeclarativeCacheTest.kt +++ b/tests/normalized-cache/src/commonTest/kotlin/declarativecache/DeclarativeCacheTest.kt @@ -91,6 +91,20 @@ class DeclarativeCacheTest { assertEquals("Bordage", authorData2.author?.lastName) } + @Test + fun fieldPolicyWithLists() = runTest { + val cacheManager = CacheManager(MemoryCacheFactory()) + cacheManager.writeOperation(GetPromoBookQuery(), GetPromoBookQuery.Data(GetPromoBookQuery.PromoBook(title = "Promo", isbn = "42", __typename = "Book"))) + cacheManager.writeOperation(GetOtherBookQuery(), GetOtherBookQuery.Data(GetOtherBookQuery.OtherBook(isbn = "43", title = "Other Book", __typename = "Book"))) + + val booksQuery = GetBooksQuery(listOf("42", "43")) + val booksCacheResponse = cacheManager.readOperation(booksQuery) + val booksData = booksCacheResponse.data!! + assertEquals(2, booksData.books.size) + assertEquals(GetBooksQuery.Book("Promo", "42", "Book"), booksData.books[0]) + assertEquals(GetBooksQuery.Book("Other Book", "43", "Book"), booksData.books[1]) + } + @Test fun canResolveListProgrammatically() = runTest { val cacheResolver = object : CacheResolver {