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 467fd6b928e..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 field name.
+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`:
@@ -221,7 +221,7 @@ extend type Query
```
> [!NOTE]
-> This can also be done programmatically by configuring the `ApolloStore` with a `FieldNameGenerator` implementation.
+> 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:
@@ -231,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 |
-The field name no longer includes the `page` argument, which means watching `UsersPage(page = 1)` or any page will observe the same 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:
@@ -245,7 +245,7 @@ Here's what happens when fetching the second page:
The field containing the first page was overwritten by the second page.
-This is because the field name is now the same for all pages and the default merging strategy is to overwrite existing fields with the new value.
+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
diff --git a/intellij-plugin/src/main/kotlin/com/apollographql/ijplugin/normalizedcache/NormalizedCache.kt b/intellij-plugin/src/main/kotlin/com/apollographql/ijplugin/normalizedcache/NormalizedCache.kt
index 6fc331af13c..d441b57ccfe 100644
--- a/intellij-plugin/src/main/kotlin/com/apollographql/ijplugin/normalizedcache/NormalizedCache.kt
+++ b/intellij-plugin/src/main/kotlin/com/apollographql/ijplugin/normalizedcache/NormalizedCache.kt
@@ -10,7 +10,7 @@ data class NormalizedCache(
)
data class Field(
- val name: String,
+ val key: String,
val value: FieldValue,
)
diff --git a/intellij-plugin/src/main/kotlin/com/apollographql/ijplugin/normalizedcache/provider/DatabaseNormalizedCacheProvider.kt b/intellij-plugin/src/main/kotlin/com/apollographql/ijplugin/normalizedcache/provider/DatabaseNormalizedCacheProvider.kt
index be2fd46bfd8..c7009b3ba8f 100644
--- a/intellij-plugin/src/main/kotlin/com/apollographql/ijplugin/normalizedcache/provider/DatabaseNormalizedCacheProvider.kt
+++ b/intellij-plugin/src/main/kotlin/com/apollographql/ijplugin/normalizedcache/provider/DatabaseNormalizedCacheProvider.kt
@@ -39,8 +39,8 @@ class DatabaseNormalizedCacheProvider : NormalizedCacheProvider {
apolloRecords.map { (key, apolloRecord) ->
NormalizedCache.Record(
key = key,
- fields = apolloRecord.map { (fieldName, fieldValue) ->
- Field(fieldName, fieldValue.toFieldValue())
+ fields = apolloRecord.map { (fieldKey, fieldValue) ->
+ Field(fieldKey, fieldValue.toFieldValue())
},
sizeInBytes = apolloRecord.sizeInBytes
)
diff --git a/intellij-plugin/src/main/kotlin/com/apollographql/ijplugin/normalizedcache/ui/FieldTreeTable.kt b/intellij-plugin/src/main/kotlin/com/apollographql/ijplugin/normalizedcache/ui/FieldTreeTable.kt
index ef423816bcf..8e6f06559bc 100644
--- a/intellij-plugin/src/main/kotlin/com/apollographql/ijplugin/normalizedcache/ui/FieldTreeTable.kt
+++ b/intellij-plugin/src/main/kotlin/com/apollographql/ijplugin/normalizedcache/ui/FieldTreeTable.kt
@@ -40,11 +40,14 @@ class FieldTreeTable(selectRecord: (String) -> Unit) : JBTreeTable(FieldTreeTabl
is NormalizedCache.FieldValue.StringValue -> append("\"${v.value}\"")
is NormalizedCache.FieldValue.NumberValue -> append(v.value.toString())
is NormalizedCache.FieldValue.BooleanValue -> append(v.value.toString())
- is NormalizedCache.FieldValue.ListValue -> append(when (val size = v.value.size) {
- 0 -> ApolloBundle.message("normalizedCacheViewer.fields.list.empty")
- 1 -> ApolloBundle.message("normalizedCacheViewer.fields.list.single")
- else -> ApolloBundle.message("normalizedCacheViewer.fields.list.multiple", size)
- }, SimpleTextAttributes.GRAY_ITALIC_ATTRIBUTES)
+ is NormalizedCache.FieldValue.ListValue -> append(
+ when (val size = v.value.size) {
+ 0 -> ApolloBundle.message("normalizedCacheViewer.fields.list.empty")
+ 1 -> ApolloBundle.message("normalizedCacheViewer.fields.list.single")
+ else -> ApolloBundle.message("normalizedCacheViewer.fields.list.multiple", size)
+ },
+ SimpleTextAttributes.GRAY_ITALIC_ATTRIBUTES
+ )
is NormalizedCache.FieldValue.CompositeValue -> append("{...}", SimpleTextAttributes.GRAY_ITALIC_ATTRIBUTES)
NormalizedCache.FieldValue.Null -> append("null")
diff --git a/intellij-plugin/src/main/kotlin/com/apollographql/ijplugin/normalizedcache/ui/FieldTreeTableModel.kt b/intellij-plugin/src/main/kotlin/com/apollographql/ijplugin/normalizedcache/ui/FieldTreeTableModel.kt
index fc2fafbf112..da8c84ac059 100644
--- a/intellij-plugin/src/main/kotlin/com/apollographql/ijplugin/normalizedcache/ui/FieldTreeTableModel.kt
+++ b/intellij-plugin/src/main/kotlin/com/apollographql/ijplugin/normalizedcache/ui/FieldTreeTableModel.kt
@@ -14,7 +14,8 @@ class FieldTreeTableModel : ListTreeTableModel(
override fun getColumnClass() = TreeTableModel::class.java
override fun valueOf(item: Unit) = Unit
},
- object : ColumnInfo(ApolloBundle.message("normalizedCacheViewer.fields.column.value")) {
+ object :
+ ColumnInfo(ApolloBundle.message("normalizedCacheViewer.fields.column.value")) {
override fun getColumnClass() = NormalizedCache.Field::class.java
override fun valueOf(item: NormalizedCacheFieldTreeNode) = item.field
},
@@ -42,7 +43,7 @@ class FieldTreeTableModel : ListTreeTableModel(
class NormalizedCacheFieldTreeNode(val field: NormalizedCache.Field) : DefaultMutableTreeNode() {
init {
- userObject = field.name
+ userObject = field.key
}
}
}
diff --git a/intellij-plugin/src/main/resources/messages/ApolloBundle.properties b/intellij-plugin/src/main/resources/messages/ApolloBundle.properties
index 200f65ad9f9..7164307d057 100644
--- a/intellij-plugin/src/main/resources/messages/ApolloBundle.properties
+++ b/intellij-plugin/src/main/resources/messages/ApolloBundle.properties
@@ -191,7 +191,7 @@ errorReport.actionText=Open GitHub Issue
toolwindow.stripe.NormalizedCacheViewer=Apollo Normalized Cache
normalizedCacheViewer.newTab=New Tab
normalizedCacheViewer.tabName.empty=Empty
-normalizedCacheViewer.fields.column.key=Key
+normalizedCacheViewer.fields.column.key=Field Key
normalizedCacheViewer.fields.column.value=Value
normalizedCacheViewer.toolbar.expandAll=Expand all keys
normalizedCacheViewer.toolbar.collapseAll=Collapse all keys
@@ -201,7 +201,7 @@ normalizedCacheViewer.toolbar.refresh=Refresh
normalizedCacheViewer.empty.message=Open or drag and drop a normalized cache .db file.
normalizedCacheViewer.empty.openFile=Open file...
normalizedCacheViewer.empty.pullFromDevice=Pull from device
-normalizedCacheViewer.records.table.key=Key
+normalizedCacheViewer.records.table.key=Cache Key
normalizedCacheViewer.records.table.size=Size
normalizedCacheViewer.fields.list.empty=[empty]
normalizedCacheViewer.fields.list.single=[1 item]
diff --git a/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo3/api/CompiledGraphQL.kt b/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo3/api/CompiledGraphQL.kt
index 32beed48bcb..7ea18f01188 100644
--- a/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo3/api/CompiledGraphQL.kt
+++ b/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo3/api/CompiledGraphQL.kt
@@ -68,7 +68,7 @@ class CompiledField internal constructor(
val value = argument.value.getOrThrow()
return if (value is CompiledVariable) {
- if (variables.valueMap.containsKey(value.name)) {
+ if (variables.valueMap.containsKey(value.name)) {
Optional.present(variables.valueMap[value.name])
} else {
// this argument has a variable value that is absent
@@ -100,7 +100,7 @@ class CompiledField internal constructor(
/**
* Returns a String containing the name of this field as well as encoded arguments. For an example:
* `hero({"episode": "Jedi"})`
- * This is mostly used internally to compute records.
+ * This is mostly used internally to compute field keys / cache keys.
*
* ## Note1:
* The argument defaultValues are not added to the name. If the schema changes from:
diff --git a/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo3/exception/Exceptions.kt b/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo3/exception/Exceptions.kt
index 43c5a907ef1..a733b6b03a5 100644
--- a/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo3/exception/Exceptions.kt
+++ b/libraries/apollo-api/src/commonMain/kotlin/com/apollographql/apollo3/exception/Exceptions.kt
@@ -17,12 +17,12 @@ sealed class ApolloException(message: String? = null, cause: Throwable? = null)
/**
* A generic exception used when there is no additional context besides the message.
*/
-class DefaultApolloException(message: String? = null, cause: Throwable? = null): ApolloException(message, cause)
+class DefaultApolloException(message: String? = null, cause: Throwable? = null) : ApolloException(message, cause)
/**
* No data was found
*/
-class NoDataException(cause: Throwable?): ApolloException("No data was found", cause)
+class NoDataException(cause: Throwable?) : ApolloException("No data was found", cause)
/**
* An I/O error happened: socket closed, DNS issue, TLS problem, file not found, etc...
@@ -118,7 +118,7 @@ class JsonDataException(message: String) : ApolloException(message)
*
* Due to the way the parsers work, it is not possible to distinguish between both cases.
*/
-class NullOrMissingField(message: String): ApolloException(message)
+class NullOrMissingField(message: String) : ApolloException(message)
/**
* The response could not be parsed because of an I/O exception.
@@ -132,8 +132,8 @@ class NullOrMissingField(message: String): ApolloException(message)
@Deprecated("ApolloParseException was only used for I/O exceptions and is now mapped to ApolloNetworkException.")
class ApolloParseException(message: String? = null, cause: Throwable? = null) : ApolloException(message = message, cause = cause)
-class ApolloGraphQLException(val error: Error): ApolloException("GraphQL error: '${error.message}'") {
- constructor(errors: List): this(errors.first())
+class ApolloGraphQLException(val error: Error) : ApolloException("GraphQL error: '${error.message}'") {
+ constructor(errors: List) : this(errors.first())
@Deprecated("Use error instead", level = DeprecationLevel.ERROR)
val errors: List = listOf(error)
@@ -143,10 +143,17 @@ class ApolloGraphQLException(val error: Error): ApolloException("GraphQL error:
* An object/field was missing in the cache
* If [fieldName] is null, it means a reference to an object could not be resolved
*/
-
class CacheMissException @ApolloInternal constructor(
+ /**
+ * The cache key to the missing object, or to the parent of the missing field if [fieldName] is not null.
+ */
val key: String,
+
+ /**
+ * The field key that was missing. If null, it means the object referenced by [key] was missing.
+ */
val fieldName: String? = null,
+
stale: Boolean = false,
) : ApolloException(message = message(key, fieldName, stale)) {
@@ -156,14 +163,14 @@ class CacheMissException @ApolloInternal constructor(
constructor(key: String, fieldName: String?) : this(key, fieldName, false)
companion object {
- internal fun message(key: String?, fieldName: String?, stale: Boolean): String {
- return if (fieldName == null) {
- "Object '$key' not found"
+ internal fun message(cacheKey: String?, fieldKey: String?, stale: Boolean): String {
+ return if (fieldKey == null) {
+ "Object '$cacheKey' not found"
} else {
if (stale) {
- "Field '$fieldName' on object '$key' is stale"
+ "Field '$fieldKey' on object '$cacheKey' is stale"
} else {
- "Object '$key' has no field named '$fieldName'"
+ "Object '$cacheKey' has no field named '$fieldKey'"
}
}
}
diff --git a/libraries/apollo-normalized-cache-api-incubating/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/api/CacheResolver.kt b/libraries/apollo-normalized-cache-api-incubating/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/api/CacheResolver.kt
index 2dbd08651fd..deddf3fa793 100644
--- a/libraries/apollo-normalized-cache-api-incubating/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/api/CacheResolver.kt
+++ b/libraries/apollo-normalized-cache-api-incubating/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/api/CacheResolver.kt
@@ -65,7 +65,7 @@ interface CacheResolver {
* @param variables the variables of the current operation
* @param parent the parent object as a map. It can contain the same values as [Record]. Especially, nested objects will be represented
* by [CacheKey]
- * @param parentId the id of the parent. Mainly used for debugging
+ * @param parentId the key of the parent. Mainly used for debugging
*
* @return a value that can go in a [Record]. No type checking is done. It is the responsibility of implementations to return the correct
* type
@@ -83,10 +83,10 @@ class ResolverContext(
val field: CompiledField,
val variables: Executable.Variables,
val parent: Map,
- val parentId: String,
+ val parentKey: String,
val parentType: String,
val cacheHeaders: CacheHeaders,
- val fieldNameGenerator: FieldNameGenerator,
+ val fieldKeyGenerator: FieldKeyGenerator,
)
/**
@@ -112,12 +112,12 @@ object DefaultCacheResolver : CacheResolver {
parent: Map,
parentId: String,
): Any? {
- val name = field.nameWithArguments(variables)
- if (!parent.containsKey(name)) {
- throw CacheMissException(parentId, name)
+ val fieldKey = field.nameWithArguments(variables)
+ if (!parent.containsKey(fieldKey)) {
+ throw CacheMissException(parentId, fieldKey)
}
- return parent[name]
+ return parent[fieldKey]
}
}
@@ -126,12 +126,12 @@ object DefaultCacheResolver : CacheResolver {
*/
object DefaultApolloResolver : ApolloResolver {
override fun resolveField(context: ResolverContext): Any? {
- val name = context.fieldNameGenerator.getFieldName(FieldNameContext(context.parentType, context.field, context.variables))
- if (!context.parent.containsKey(name)) {
- throw CacheMissException(context.parentId, name)
+ val fieldKey = context.fieldKeyGenerator.getFieldKey(FieldKeyContext(context.parentType, context.field, context.variables))
+ if (!context.parent.containsKey(fieldKey)) {
+ throw CacheMissException(context.parentKey, fieldKey)
}
- return context.parent[name]
+ return context.parent[fieldKey]
}
}
@@ -142,31 +142,29 @@ object DefaultApolloResolver : ApolloResolver {
class ReceiveDateApolloResolver(private val maxAge: Int) : ApolloResolver {
override fun resolveField(context: ResolverContext): Any? {
- val field = context.field
val parent = context.parent
- val variables = context.variables
- val parentId = context.parentId
+ val parentKey = context.parentKey
- val name = field.nameWithArguments(variables)
- if (!parent.containsKey(name)) {
- throw CacheMissException(parentId, name)
+ val fieldKey = context.fieldKeyGenerator.getFieldKey(FieldKeyContext(context.parentType, context.field, context.variables))
+ if (!parent.containsKey(fieldKey)) {
+ throw CacheMissException(parentKey, fieldKey)
}
if (parent is Record) {
- val lastUpdated = parent.dates?.get(name)
+ val lastUpdated = parent.dates?.get(fieldKey)
if (lastUpdated != null) {
val maxStale = context.cacheHeaders.headerValue(ApolloCacheHeaders.MAX_STALE)?.toLongOrNull() ?: 0L
if (maxStale < Long.MAX_VALUE) {
val age = currentTimeMillis() / 1000 - lastUpdated
if (maxAge + maxStale - age < 0) {
- throw CacheMissException(parentId, name, true)
+ throw CacheMissException(parentKey, fieldKey, true)
}
}
}
}
- return parent[name]
+ return parent[fieldKey]
}
}
@@ -184,21 +182,21 @@ class ExpireDateCacheResolver : CacheResolver {
parent: Map,
parentId: String,
): Any? {
- val name = field.nameWithArguments(variables)
- if (!parent.containsKey(name)) {
- throw CacheMissException(parentId, name)
+ val fieldKey = field.nameWithArguments(variables)
+ if (!parent.containsKey(fieldKey)) {
+ throw CacheMissException(parentId, fieldKey)
}
if (parent is Record) {
- val expires = parent.dates?.get(name)
+ val expires = parent.dates?.get(fieldKey)
if (expires != null) {
if (currentTimeMillis() / 1000 - expires >= 0) {
- throw CacheMissException(parentId, name, true)
+ throw CacheMissException(parentId, fieldKey, true)
}
}
}
- return parent[name]
+ return parent[fieldKey]
}
}
diff --git a/libraries/apollo-normalized-cache-api-incubating/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/api/FieldKeyGenerator.kt b/libraries/apollo-normalized-cache-api-incubating/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/api/FieldKeyGenerator.kt
new file mode 100644
index 00000000000..be9509ba1f9
--- /dev/null
+++ b/libraries/apollo-normalized-cache-api-incubating/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/api/FieldKeyGenerator.kt
@@ -0,0 +1,71 @@
+package com.apollographql.apollo3.cache.normalized.api
+
+import com.apollographql.apollo3.annotations.ApolloExperimental
+import com.apollographql.apollo3.api.CompiledField
+import com.apollographql.apollo3.api.Executable
+
+/**
+ * A generator for field keys.
+ *
+ * Field keys uniquely identify fields within their parent [Record]. By default they take the form of the field's name and its encoded
+ * arguments, for example `hero({"episode": "Jedi"})` (see [CompiledField.nameWithArguments]).
+ *
+ * A [FieldKeyGenerator] can be used to customize this format, for instance to exclude certain pagination arguments when storing a
+ * connection field.
+ */
+@ApolloExperimental
+interface FieldKeyGenerator {
+ /**
+ * Returns the field key to use within its parent [Record].
+ */
+ fun getFieldKey(context: FieldKeyContext): String
+}
+
+/**
+ * Context passed to the [FieldKeyGenerator.getFieldKey] method.
+ */
+@ApolloExperimental
+class FieldKeyContext(
+ val parentType: String,
+ val field: CompiledField,
+ val variables: Executable.Variables,
+)
+
+/**
+ * A [FieldKeyGenerator] that returns the field name with its arguments, excluding pagination arguments defined with the
+ * `@fieldPolicy(forField: "...", paginationArgs: "...")` directive.
+ *
+ * @see CompiledField.nameWithArguments
+ */
+@ApolloExperimental
+object DefaultFieldKeyGenerator : FieldKeyGenerator {
+ override fun getFieldKey(context: FieldKeyContext): String {
+ return context.field.nameWithArguments(context.variables)
+ }
+}
+
+/**
+ * A [FieldKeyGenerator] that generates field keys by excluding
+ * [Relay connection types](https://relay.dev/graphql/connections.htm#sec-Connection-Types) pagination arguments.
+ */
+@ApolloExperimental
+class ConnectionFieldKeyGenerator(private val connectionFields: Map>) : FieldKeyGenerator {
+ companion object {
+ private val paginationArguments = setOf("first", "last", "before", "after")
+ }
+
+ override fun getFieldKey(context: FieldKeyContext): String {
+ return if (context.field.name in connectionFields[context.parentType].orEmpty()) {
+ context.field.newBuilder()
+ .arguments(
+ context.field.arguments.filter { argument ->
+ argument.name !in paginationArguments
+ }
+ )
+ .build()
+ .nameWithArguments(context.variables)
+ } else {
+ DefaultFieldKeyGenerator.getFieldKey(context)
+ }
+ }
+}
diff --git a/libraries/apollo-normalized-cache-api-incubating/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/api/FieldNameGenerator.kt b/libraries/apollo-normalized-cache-api-incubating/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/api/FieldNameGenerator.kt
deleted file mode 100644
index a950e0f7ce8..00000000000
--- a/libraries/apollo-normalized-cache-api-incubating/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/api/FieldNameGenerator.kt
+++ /dev/null
@@ -1,65 +0,0 @@
-package com.apollographql.apollo3.cache.normalized.api
-
-import com.apollographql.apollo3.annotations.ApolloExperimental
-import com.apollographql.apollo3.api.CompiledField
-import com.apollographql.apollo3.api.Executable
-
-/**
- * A generator for field names.
- *
- * For instance, [FieldNameGenerator] can be used to exclude certain pagination arguments when storing a connection field.
- */
-@ApolloExperimental
-interface FieldNameGenerator {
- /**
- * Returns the field name to use within its parent [Record].
- */
- fun getFieldName(context: FieldNameContext): String
-}
-
-/**
- * Context passed to the [FieldNameGenerator.getFieldName] method.
- */
-@ApolloExperimental
-class FieldNameContext(
- val parentType: String,
- val field: CompiledField,
- val variables: Executable.Variables,
-)
-
-/**
- * A [FieldNameGenerator] that returns the field name with its arguments, excluding pagination arguments defined with the
- * `@fieldPolicy(forField: "...", paginationArgs: "...")` directive.
- */
-@ApolloExperimental
-object DefaultFieldNameGenerator : FieldNameGenerator {
- override fun getFieldName(context: FieldNameContext): String {
- return context.field.nameWithArguments(context.variables)
- }
-}
-
-/**
- * A [FieldNameGenerator] that generates field names excluding
- * [Relay connection types](https://relay.dev/graphql/connections.htm#sec-Connection-Types) pagination arguments.
- */
-@ApolloExperimental
-class ConnectionFieldNameGenerator(private val connectionFields: Map>) : FieldNameGenerator {
- companion object {
- private val paginationArguments = setOf("first", "last", "before", "after")
- }
-
- override fun getFieldName(context: FieldNameContext): String {
- return if (context.field.name in connectionFields[context.parentType].orEmpty()) {
- context.field.newBuilder()
- .arguments(
- context.field.arguments.filter { argument ->
- argument.name !in paginationArguments
- }
- )
- .build()
- .nameWithArguments(context.variables)
- } else {
- DefaultFieldNameGenerator.getFieldName(context)
- }
- }
-}
diff --git a/libraries/apollo-normalized-cache-api-incubating/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/api/OperationCacheExtensions.kt b/libraries/apollo-normalized-cache-api-incubating/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/api/OperationCacheExtensions.kt
index 44b055c7183..84452c8a3af 100644
--- a/libraries/apollo-normalized-cache-api-incubating/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/api/OperationCacheExtensions.kt
+++ b/libraries/apollo-normalized-cache-api-incubating/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/api/OperationCacheExtensions.kt
@@ -17,16 +17,17 @@ fun Operation.normalize(
customScalarAdapters: CustomScalarAdapters,
cacheKeyGenerator: CacheKeyGenerator,
metadataGenerator: MetadataGenerator = EmptyMetadataGenerator,
- fieldNameGenerator: FieldNameGenerator = DefaultFieldNameGenerator,
+ fieldKeyGenerator: FieldKeyGenerator = DefaultFieldKeyGenerator,
embeddedFieldsProvider: EmbeddedFieldsProvider = DefaultEmbeddedFieldsProvider,
-) = normalize(data, customScalarAdapters, cacheKeyGenerator, metadataGenerator, fieldNameGenerator, embeddedFieldsProvider, CacheKey.rootKey().key)
+) =
+ normalize(data, customScalarAdapters, cacheKeyGenerator, metadataGenerator, fieldKeyGenerator, embeddedFieldsProvider, CacheKey.rootKey().key)
fun Executable.normalize(
data: D,
customScalarAdapters: CustomScalarAdapters,
cacheKeyGenerator: CacheKeyGenerator,
metadataGenerator: MetadataGenerator = EmptyMetadataGenerator,
- fieldNameGenerator: FieldNameGenerator = DefaultFieldNameGenerator,
+ fieldKeyGenerator: FieldKeyGenerator = DefaultFieldKeyGenerator,
embeddedFieldsProvider: EmbeddedFieldsProvider = DefaultEmbeddedFieldsProvider,
rootKey: String,
): Map {
@@ -34,7 +35,7 @@ fun Executable.normalize(
adapter().toJson(writer, customScalarAdapters, data)
val variables = variables(customScalarAdapters)
@Suppress("UNCHECKED_CAST")
- return Normalizer(variables, rootKey, cacheKeyGenerator, metadataGenerator, fieldNameGenerator, embeddedFieldsProvider)
+ return Normalizer(variables, rootKey, cacheKeyGenerator, metadataGenerator, fieldKeyGenerator, embeddedFieldsProvider)
.normalize(writer.root() as Map, rootField().selections, rootField().type.rawType())
}
@@ -44,7 +45,7 @@ fun Executable.readDataFromCache(
cache: ReadOnlyNormalizedCache,
cacheResolver: CacheResolver,
cacheHeaders: CacheHeaders,
- fieldNameGenerator: FieldNameGenerator = DefaultFieldNameGenerator,
+ fieldKeyGenerator: FieldKeyGenerator = DefaultFieldKeyGenerator,
): D {
val variables = variables(customScalarAdapters, true)
return readInternal(
@@ -53,7 +54,7 @@ fun Executable.readDataFromCache(
cacheResolver = cacheResolver,
cacheHeaders = cacheHeaders,
variables = variables,
- fieldNameGenerator = fieldNameGenerator,
+ fieldKeyGenerator = fieldKeyGenerator,
).toData(adapter(), customScalarAdapters, variables)
}
@@ -64,7 +65,7 @@ fun Executable.readDataFromCache(
cache: ReadOnlyNormalizedCache,
cacheResolver: CacheResolver,
cacheHeaders: CacheHeaders,
- fieldNameGenerator: FieldNameGenerator = DefaultFieldNameGenerator,
+ fieldKeyGenerator: FieldKeyGenerator = DefaultFieldKeyGenerator,
): D {
val variables = variables(customScalarAdapters, true)
return readInternal(
@@ -73,7 +74,7 @@ fun Executable.readDataFromCache(
cacheResolver = cacheResolver,
cacheHeaders = cacheHeaders,
variables = variables,
- fieldNameGenerator = fieldNameGenerator,
+ fieldKeyGenerator = fieldKeyGenerator,
).toData(adapter(), customScalarAdapters, variables)
}
@@ -83,7 +84,7 @@ fun Executable.readDataFromCache(
cache: ReadOnlyNormalizedCache,
cacheResolver: ApolloResolver,
cacheHeaders: CacheHeaders,
- fieldNameGenerator: FieldNameGenerator = DefaultFieldNameGenerator,
+ fieldKeyGenerator: FieldKeyGenerator = DefaultFieldKeyGenerator,
): D {
val variables = variables(customScalarAdapters, true)
return readInternal(
@@ -92,7 +93,7 @@ fun Executable.readDataFromCache(
cacheResolver = cacheResolver,
cacheHeaders = cacheHeaders,
variables = variables,
- fieldNameGenerator = fieldNameGenerator,
+ fieldKeyGenerator = fieldKeyGenerator,
).toData(adapter(), customScalarAdapters, variables)
}
@@ -103,7 +104,7 @@ fun Executable.readDataFromCache(
cache: ReadOnlyNormalizedCache,
cacheResolver: ApolloResolver,
cacheHeaders: CacheHeaders,
- fieldNameGenerator: FieldNameGenerator = DefaultFieldNameGenerator,
+ fieldKeyGenerator: FieldKeyGenerator = DefaultFieldKeyGenerator,
): D {
val variables = variables(customScalarAdapters, true)
return readInternal(
@@ -112,7 +113,7 @@ fun Executable.readDataFromCache(
cacheResolver = cacheResolver,
cacheHeaders = cacheHeaders,
variables = variables,
- fieldNameGenerator = fieldNameGenerator,
+ fieldKeyGenerator = fieldKeyGenerator,
).toData(adapter(), customScalarAdapters, variables)
}
@@ -123,14 +124,14 @@ fun Executable.readDataFromCacheInternal(
cacheResolver: CacheResolver,
cacheHeaders: CacheHeaders,
variables: Executable.Variables,
- fieldNameGenerator: FieldNameGenerator,
+ fieldKeyGenerator: FieldKeyGenerator,
): CacheData = readInternal(
cacheKey = cacheKey,
cache = cache,
cacheResolver = cacheResolver,
cacheHeaders = cacheHeaders,
variables = variables,
- fieldNameGenerator = fieldNameGenerator,
+ fieldKeyGenerator = fieldKeyGenerator,
)
@ApolloInternal
@@ -140,14 +141,14 @@ fun Executable.readDataFromCacheInternal(
cacheResolver: ApolloResolver,
cacheHeaders: CacheHeaders,
variables: Executable.Variables,
- fieldNameGenerator: FieldNameGenerator,
+ fieldKeyGenerator: FieldKeyGenerator,
): CacheData = readInternal(
cacheKey = cacheKey,
cache = cache,
cacheResolver = cacheResolver,
cacheHeaders = cacheHeaders,
variables = variables,
- fieldNameGenerator = fieldNameGenerator,
+ fieldKeyGenerator = fieldKeyGenerator,
)
@@ -157,7 +158,7 @@ private fun Executable.readInternal(
cacheResolver: Any,
cacheHeaders: CacheHeaders,
variables: Executable.Variables,
- fieldNameGenerator: FieldNameGenerator,
+ fieldKeyGenerator: FieldKeyGenerator,
): CacheData {
return CacheBatchReader(
cache = cache,
@@ -167,7 +168,7 @@ private fun Executable.readInternal(
rootKey = cacheKey.key,
rootSelections = rootField().selections,
rootTypename = rootField().type.rawType().name,
- fieldNameGenerator = fieldNameGenerator,
+ fieldKeyGenerator = fieldKeyGenerator,
).collectData()
}
@@ -187,5 +188,7 @@ fun CacheData.toData(
root = toMap(),
)
- return adapter.fromJson(reader, customScalarAdapters.newBuilder().falseVariables(variables.valueMap.filter { it.value == false }.keys).build())
+ return adapter.fromJson(reader, customScalarAdapters.newBuilder().falseVariables(variables.valueMap.filter { it.value == false }.keys)
+ .build()
+ )
}
diff --git a/libraries/apollo-normalized-cache-api-incubating/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/api/internal/CacheBatchReader.kt b/libraries/apollo-normalized-cache-api-incubating/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/api/internal/CacheBatchReader.kt
index fe15eb7d927..6b245eb6377 100644
--- a/libraries/apollo-normalized-cache-api-incubating/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/api/internal/CacheBatchReader.kt
+++ b/libraries/apollo-normalized-cache-api-incubating/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/api/internal/CacheBatchReader.kt
@@ -9,7 +9,7 @@ import com.apollographql.apollo3.cache.normalized.api.CacheData
import com.apollographql.apollo3.cache.normalized.api.CacheHeaders
import com.apollographql.apollo3.cache.normalized.api.CacheKey
import com.apollographql.apollo3.cache.normalized.api.CacheResolver
-import com.apollographql.apollo3.cache.normalized.api.FieldNameGenerator
+import com.apollographql.apollo3.cache.normalized.api.FieldKeyGenerator
import com.apollographql.apollo3.cache.normalized.api.ReadOnlyNormalizedCache
import com.apollographql.apollo3.cache.normalized.api.Record
import com.apollographql.apollo3.cache.normalized.api.ResolverContext
@@ -30,7 +30,7 @@ internal class CacheBatchReader(
private val cacheHeaders: CacheHeaders,
private val rootSelections: List,
private val rootTypename: String,
- private val fieldNameGenerator: FieldNameGenerator,
+ private val fieldKeyGenerator: FieldKeyGenerator,
) {
/**
* @param key: the key of the record we need to fetch
@@ -64,6 +64,7 @@ internal class CacheBatchReader(
is CompiledField -> {
state.fields.add(compiledSelection)
}
+
is CompiledFragment -> {
if ((typename in compiledSelection.possibleTypes || compiledSelection.typeCondition == parentType) && !compiledSelection.shouldSkip(state.variables.valueMap)) {
collect(compiledSelection.selections, parentType, typename, state)
@@ -112,7 +113,8 @@ internal class CacheBatchReader(
}
}
- val collectedFields = collectAndMergeSameDirectives(pendingReference.selections, pendingReference.parentType, variables, record["__typename"] as? String)
+ val collectedFields =
+ collectAndMergeSameDirectives(pendingReference.selections, pendingReference.parentType, variables, record["__typename"] as? String)
val map = collectedFields.mapNotNull {
if (it.shouldSkip(variables.valueMap)) {
@@ -122,16 +124,19 @@ internal class CacheBatchReader(
val value = when (cacheResolver) {
is CacheResolver -> cacheResolver.resolveField(it, variables, record, record.key)
is ApolloResolver -> {
- cacheResolver.resolveField(ResolverContext(
- field = it,
- variables = variables,
- parent = record,
- parentId = record.key,
- parentType = pendingReference.parentType,
- cacheHeaders = cacheHeaders,
- fieldNameGenerator = fieldNameGenerator,
- ))
+ cacheResolver.resolveField(
+ ResolverContext(
+ field = it,
+ variables = variables,
+ parent = record,
+ parentKey = record.key,
+ parentType = pendingReference.parentType,
+ cacheHeaders = cacheHeaders,
+ fieldKeyGenerator = fieldKeyGenerator,
+ )
+ )
}
+
else -> throw IllegalStateException()
}
value.registerCacheKeys(pendingReference.path + it.responseName, it.selections, it.type.rawType().name)
@@ -161,11 +166,13 @@ internal class CacheBatchReader(
)
)
}
+
is List<*> -> {
forEachIndexed { index, value ->
value.registerCacheKeys(path + index, selections, parentType)
}
}
+
is Map<*, *> -> {
@Suppress("UNCHECKED_CAST")
this as Map
@@ -178,16 +185,19 @@ internal class CacheBatchReader(
val value = when (cacheResolver) {
is CacheResolver -> cacheResolver.resolveField(it, variables, this, "")
is ApolloResolver -> {
- cacheResolver.resolveField(ResolverContext(
- field = it,
- variables = variables,
- parent = this,
- parentId = "",
- parentType = parentType,
- cacheHeaders = cacheHeaders,
- fieldNameGenerator = fieldNameGenerator,
- ))
+ cacheResolver.resolveField(
+ ResolverContext(
+ field = it,
+ variables = variables,
+ parent = this,
+ parentKey = "",
+ parentType = parentType,
+ cacheHeaders = cacheHeaders,
+ fieldKeyGenerator = fieldKeyGenerator,
+ )
+ )
}
+
else -> throw IllegalStateException()
}
value.registerCacheKeys(path + it.responseName, it.selections, it.type.rawType().name)
@@ -200,7 +210,7 @@ internal class CacheBatchReader(
private data class CacheBatchReaderData(
private val data: Map, Map>,
- ): CacheData {
+ ) : CacheData {
@Suppress("UNCHECKED_CAST")
override fun toMap(): Map {
return data[emptyList()].replaceCacheKeys(emptyList()) as Map
@@ -211,17 +221,20 @@ internal class CacheBatchReader(
is CacheKey -> {
data[path].replaceCacheKeys(path)
}
+
is List<*> -> {
mapIndexed { index, src ->
src.replaceCacheKeys(path + index)
}
}
+
is Map<*, *> -> {
// This will traverse Map custom scalars but this is ok as it shouldn't contain any CacheKey
mapValues {
it.value.replaceCacheKeys(path + (it.key as String))
}
}
+
else -> {
// Scalar value
this
diff --git a/libraries/apollo-normalized-cache-api-incubating/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/api/internal/Normalizer.kt b/libraries/apollo-normalized-cache-api-incubating/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/api/internal/Normalizer.kt
index 3a77428ea49..fe241ad4311 100644
--- a/libraries/apollo-normalized-cache-api-incubating/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/api/internal/Normalizer.kt
+++ b/libraries/apollo-normalized-cache-api-incubating/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/api/internal/Normalizer.kt
@@ -14,8 +14,8 @@ import com.apollographql.apollo3.cache.normalized.api.CacheKeyGenerator
import com.apollographql.apollo3.cache.normalized.api.CacheKeyGeneratorContext
import com.apollographql.apollo3.cache.normalized.api.EmbeddedFieldsContext
import com.apollographql.apollo3.cache.normalized.api.EmbeddedFieldsProvider
-import com.apollographql.apollo3.cache.normalized.api.FieldNameContext
-import com.apollographql.apollo3.cache.normalized.api.FieldNameGenerator
+import com.apollographql.apollo3.cache.normalized.api.FieldKeyContext
+import com.apollographql.apollo3.cache.normalized.api.FieldKeyGenerator
import com.apollographql.apollo3.cache.normalized.api.MetadataGenerator
import com.apollographql.apollo3.cache.normalized.api.MetadataGeneratorContext
import com.apollographql.apollo3.cache.normalized.api.Record
@@ -29,7 +29,7 @@ internal class Normalizer(
private val rootKey: String,
private val cacheKeyGenerator: CacheKeyGenerator,
private val metadataGenerator: MetadataGenerator,
- private val fieldNameGenerator: FieldNameGenerator,
+ private val fieldKeyGenerator: FieldKeyGenerator,
private val embeddedFieldsProvider: EmbeddedFieldsProvider,
) {
private val records = mutableMapOf()
@@ -83,7 +83,7 @@ internal class Normalizer(
.condition(emptyList())
.build()
- val fieldKey = fieldNameGenerator.getFieldName(FieldNameContext(parentType.name, mergedField, variables))
+ val fieldKey = fieldKeyGenerator.getFieldKey(FieldKeyContext(parentType.name, mergedField, variables))
val base = if (key == CacheKey.rootKey().key) {
// If we're at the root level, skip `QUERY_ROOT` altogether to save a few bytes
diff --git a/libraries/apollo-normalized-cache-api/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/api/CacheResolver.kt b/libraries/apollo-normalized-cache-api/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/api/CacheResolver.kt
index a0a1f3e52ab..1b2fb0d2de1 100644
--- a/libraries/apollo-normalized-cache-api/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/api/CacheResolver.kt
+++ b/libraries/apollo-normalized-cache-api/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/api/CacheResolver.kt
@@ -91,12 +91,12 @@ object DefaultCacheResolver : CacheResolver {
parent: Map,
parentId: String,
): Any? {
- val name = field.nameWithArguments(variables)
- if (!parent.containsKey(name)) {
- throw CacheMissException(parentId, name)
+ val fieldKey = field.nameWithArguments(variables)
+ if (!parent.containsKey(fieldKey)) {
+ throw CacheMissException(parentId, fieldKey)
}
- return parent[name]
+ return parent[fieldKey]
}
}
@@ -115,22 +115,22 @@ class ReceiveDateCacheResolver(private val maxAge: Int) : CacheResolver {
parent: Map,
parentId: String,
): Any? {
- val name = field.nameWithArguments(variables)
- if (!parent.containsKey(name)) {
- throw CacheMissException(parentId, name)
+ val fieldKey = field.nameWithArguments(variables)
+ if (!parent.containsKey(fieldKey)) {
+ throw CacheMissException(parentId, fieldKey)
}
if (parent is Record) {
- val lastUpdated = parent.date?.get(name)
+ val lastUpdated = parent.date?.get(fieldKey)
if (lastUpdated != null) {
- val age = currentTimeMillis()/1000 - lastUpdated
+ val age = currentTimeMillis() / 1000 - lastUpdated
if (age > maxAge) {
- throw CacheMissException(parentId, name, true)
+ throw CacheMissException(parentId, fieldKey, true)
}
}
}
- return parent[name]
+ return parent[fieldKey]
}
}
@@ -148,21 +148,21 @@ class ExpireDateCacheResolver() : CacheResolver {
parent: Map,
parentId: String,
): Any? {
- val name = field.nameWithArguments(variables)
- if (!parent.containsKey(name)) {
- throw CacheMissException(parentId, name)
+ val fieldKey = field.nameWithArguments(variables)
+ if (!parent.containsKey(fieldKey)) {
+ throw CacheMissException(parentId, fieldKey)
}
if (parent is Record) {
- val expires = parent.date?.get(name)
+ val expires = parent.date?.get(fieldKey)
if (expires != null) {
- if (currentTimeMillis()/1000 - expires >= 0) {
- throw CacheMissException(parentId, name, true)
+ if (currentTimeMillis() / 1000 - expires >= 0) {
+ throw CacheMissException(parentId, fieldKey, true)
}
}
}
- return parent[name]
+ return parent[fieldKey]
}
}
diff --git a/libraries/apollo-normalized-cache-incubating/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/ApolloStore.kt b/libraries/apollo-normalized-cache-incubating/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/ApolloStore.kt
index c724cbf7bce..40d08691e26 100644
--- a/libraries/apollo-normalized-cache-incubating/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/ApolloStore.kt
+++ b/libraries/apollo-normalized-cache-incubating/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/ApolloStore.kt
@@ -10,11 +10,11 @@ import com.apollographql.apollo3.cache.normalized.api.CacheKey
import com.apollographql.apollo3.cache.normalized.api.CacheKeyGenerator
import com.apollographql.apollo3.cache.normalized.api.CacheResolver
import com.apollographql.apollo3.cache.normalized.api.DefaultEmbeddedFieldsProvider
-import com.apollographql.apollo3.cache.normalized.api.DefaultFieldNameGenerator
+import com.apollographql.apollo3.cache.normalized.api.DefaultFieldKeyGenerator
import com.apollographql.apollo3.cache.normalized.api.DefaultRecordMerger
import com.apollographql.apollo3.cache.normalized.api.EmbeddedFieldsProvider
import com.apollographql.apollo3.cache.normalized.api.EmptyMetadataGenerator
-import com.apollographql.apollo3.cache.normalized.api.FieldNameGenerator
+import com.apollographql.apollo3.cache.normalized.api.FieldKeyGenerator
import com.apollographql.apollo3.cache.normalized.api.FieldPolicyApolloResolver
import com.apollographql.apollo3.cache.normalized.api.FieldPolicyCacheResolver
import com.apollographql.apollo3.cache.normalized.api.MetadataGenerator
@@ -214,7 +214,7 @@ fun ApolloStore(
metadataGenerator = EmptyMetadataGenerator,
cacheResolver = cacheResolver,
recordMerger = DefaultRecordMerger,
- fieldNameGenerator = DefaultFieldNameGenerator,
+ fieldKeyGenerator = DefaultFieldKeyGenerator,
embeddedFieldsProvider = DefaultEmbeddedFieldsProvider,
)
@@ -225,7 +225,7 @@ fun ApolloStore(
metadataGenerator: MetadataGenerator = EmptyMetadataGenerator,
apolloResolver: ApolloResolver = FieldPolicyApolloResolver,
recordMerger: RecordMerger = DefaultRecordMerger,
- fieldNameGenerator: FieldNameGenerator = DefaultFieldNameGenerator,
+ fieldKeyGenerator: FieldKeyGenerator = DefaultFieldKeyGenerator,
embeddedFieldsProvider: EmbeddedFieldsProvider = DefaultEmbeddedFieldsProvider,
): ApolloStore = DefaultApolloStore(
normalizedCacheFactory = normalizedCacheFactory,
@@ -233,7 +233,7 @@ fun ApolloStore(
metadataGenerator = metadataGenerator,
cacheResolver = apolloResolver,
recordMerger = recordMerger,
- fieldNameGenerator = fieldNameGenerator,
+ fieldKeyGenerator = fieldKeyGenerator,
embeddedFieldsProvider = embeddedFieldsProvider,
)
diff --git a/libraries/apollo-normalized-cache-incubating/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/ClientCacheExtensions.kt b/libraries/apollo-normalized-cache-incubating/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/ClientCacheExtensions.kt
index 2048396f9ad..4132e659139 100644
--- a/libraries/apollo-normalized-cache-incubating/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/ClientCacheExtensions.kt
+++ b/libraries/apollo-normalized-cache-incubating/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/ClientCacheExtensions.kt
@@ -21,11 +21,11 @@ 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.DefaultEmbeddedFieldsProvider
-import com.apollographql.apollo3.cache.normalized.api.DefaultFieldNameGenerator
+import com.apollographql.apollo3.cache.normalized.api.DefaultFieldKeyGenerator
import com.apollographql.apollo3.cache.normalized.api.DefaultRecordMerger
import com.apollographql.apollo3.cache.normalized.api.EmbeddedFieldsProvider
import com.apollographql.apollo3.cache.normalized.api.EmptyMetadataGenerator
-import com.apollographql.apollo3.cache.normalized.api.FieldNameGenerator
+import com.apollographql.apollo3.cache.normalized.api.FieldKeyGenerator
import com.apollographql.apollo3.cache.normalized.api.FieldPolicyApolloResolver
import com.apollographql.apollo3.cache.normalized.api.FieldPolicyCacheResolver
import com.apollographql.apollo3.cache.normalized.api.MetadataGenerator
@@ -127,7 +127,7 @@ fun ApolloClient.Builder.normalizedCache(
metadataGenerator: MetadataGenerator = EmptyMetadataGenerator,
apolloResolver: ApolloResolver = FieldPolicyApolloResolver,
recordMerger: RecordMerger = DefaultRecordMerger,
- fieldNameGenerator: FieldNameGenerator = DefaultFieldNameGenerator,
+ fieldKeyGenerator: FieldKeyGenerator = DefaultFieldKeyGenerator,
embeddedFieldsProvider: EmbeddedFieldsProvider = DefaultEmbeddedFieldsProvider,
writeToCacheAsynchronously: Boolean = false,
): ApolloClient.Builder {
@@ -138,9 +138,10 @@ fun ApolloClient.Builder.normalizedCache(
metadataGenerator = metadataGenerator,
apolloResolver = apolloResolver,
recordMerger = recordMerger,
- fieldNameGenerator = fieldNameGenerator,
+ fieldKeyGenerator = fieldKeyGenerator,
embeddedFieldsProvider = embeddedFieldsProvider
- ), writeToCacheAsynchronously)
+ ), writeToCacheAsynchronously
+ )
}
@JvmName("-logCacheMisses")
@@ -176,14 +177,16 @@ fun ApolloClient.Builder.store(store: ApolloStore, writeToCacheAsynchronously: B
fun ApolloCall.watch(
fetchThrows: Boolean,
refetchThrows: Boolean,
-): Flow> = throw UnsupportedOperationException("watch(fetchThrows: Boolean, refetchThrows: Boolean) is no longer supported, use watch() instead")
+): Flow> =
+ throw UnsupportedOperationException("watch(fetchThrows: Boolean, refetchThrows: Boolean) is no longer supported, use watch() instead")
@Deprecated(level = DeprecationLevel.ERROR, message = "Exceptions no longer throw", replaceWith = ReplaceWith("watch()"))
@ApolloDeprecatedSince(v4_0_0)
@Suppress("UNUSED_PARAMETER")
fun ApolloCall.watch(
fetchThrows: Boolean,
-): Flow> = throw UnsupportedOperationException("watch(fetchThrows: Boolean, refetchThrows: Boolean) is no longer supported, use watch() instead")
+): Flow> =
+ throw UnsupportedOperationException("watch(fetchThrows: Boolean, refetchThrows: Boolean) is no longer supported, use watch() instead")
/**
* Gets initial response(s) then observes the cache for any changes.
@@ -589,7 +592,9 @@ val ApolloResponse.isFromCache: Boolean
val ApolloResponse.cacheInfo
get() = executionContext[CacheInfo]
-internal fun ApolloResponse.withCacheInfo(cacheInfo: CacheInfo) = newBuilder().addExecutionContext(cacheInfo).build()
+internal fun ApolloResponse.withCacheInfo(cacheInfo: CacheInfo) =
+ newBuilder().addExecutionContext(cacheInfo).build()
+
internal fun ApolloResponse.Builder.cacheInfo(cacheInfo: CacheInfo) = addExecutionContext(cacheInfo)
internal class FetchPolicyContext(val interceptor: ApolloInterceptor) : ExecutionContext.Element {
@@ -680,7 +685,7 @@ internal val ApolloRequest.fetchFromCache
get() = executionContext[FetchFromCacheContext]?.value ?: false
fun ApolloResponse.Builder.cacheHeaders(cacheHeaders: CacheHeaders) =
- addExecutionContext(CacheHeadersContext(cacheHeaders))
+ addExecutionContext(CacheHeadersContext(cacheHeaders))
val ApolloResponse.cacheHeaders
get() = executionContext[CacheHeadersContext]?.value ?: CacheHeaders.NONE
diff --git a/libraries/apollo-normalized-cache-incubating/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/internal/DefaultApolloStore.kt b/libraries/apollo-normalized-cache-incubating/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/internal/DefaultApolloStore.kt
index cd5c0f52683..82b62968516 100644
--- a/libraries/apollo-normalized-cache-incubating/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/internal/DefaultApolloStore.kt
+++ b/libraries/apollo-normalized-cache-incubating/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/internal/DefaultApolloStore.kt
@@ -13,7 +13,7 @@ import com.apollographql.apollo3.cache.normalized.api.CacheKey
import com.apollographql.apollo3.cache.normalized.api.CacheKeyGenerator
import com.apollographql.apollo3.cache.normalized.api.CacheResolver
import com.apollographql.apollo3.cache.normalized.api.EmbeddedFieldsProvider
-import com.apollographql.apollo3.cache.normalized.api.FieldNameGenerator
+import com.apollographql.apollo3.cache.normalized.api.FieldKeyGenerator
import com.apollographql.apollo3.cache.normalized.api.MetadataGenerator
import com.apollographql.apollo3.cache.normalized.api.NormalizedCache
import com.apollographql.apollo3.cache.normalized.api.NormalizedCacheFactory
@@ -33,7 +33,7 @@ import kotlin.reflect.KClass
internal class DefaultApolloStore(
normalizedCacheFactory: NormalizedCacheFactory,
private val cacheKeyGenerator: CacheKeyGenerator,
- private val fieldNameGenerator: FieldNameGenerator,
+ private val fieldKeyGenerator: FieldKeyGenerator,
private val metadataGenerator: MetadataGenerator,
private val cacheResolver: Any,
private val recordMerger: RecordMerger,
@@ -111,7 +111,7 @@ internal class DefaultApolloStore(
customScalarAdapters = customScalarAdapters,
cacheKeyGenerator = cacheKeyGenerator,
metadataGenerator = metadataGenerator,
- fieldNameGenerator = fieldNameGenerator,
+ fieldKeyGenerator = fieldKeyGenerator,
embeddedFieldsProvider = embeddedFieldsProvider,
)
}
@@ -128,7 +128,7 @@ internal class DefaultApolloStore(
cacheHeaders = cacheHeaders,
cacheKey = CacheKey.rootKey(),
variables = variables,
- fieldNameGenerator = fieldNameGenerator,
+ fieldKeyGenerator = fieldKeyGenerator,
).toData(operation.adapter(), customScalarAdapters, variables)
}
@@ -146,7 +146,7 @@ internal class DefaultApolloStore(
cacheHeaders = cacheHeaders,
cacheKey = cacheKey,
variables = variables,
- fieldNameGenerator = fieldNameGenerator,
+ fieldKeyGenerator = fieldKeyGenerator,
).toData(fragment.adapter(), customScalarAdapters, variables)
}
@@ -165,7 +165,7 @@ internal class DefaultApolloStore(
customScalarAdapters = customScalarAdapters,
cacheKeyGenerator = cacheKeyGenerator,
metadataGenerator = metadataGenerator,
- fieldNameGenerator = fieldNameGenerator,
+ fieldKeyGenerator = fieldKeyGenerator,
embeddedFieldsProvider = embeddedFieldsProvider,
).values.toSet()
@@ -184,7 +184,7 @@ internal class DefaultApolloStore(
customScalarAdapters = customScalarAdapters,
cacheKeyGenerator = cacheKeyGenerator,
metadataGenerator = metadataGenerator,
- fieldNameGenerator = fieldNameGenerator,
+ fieldKeyGenerator = fieldKeyGenerator,
embeddedFieldsProvider = embeddedFieldsProvider,
rootKey = cacheKey.key
).values
@@ -203,7 +203,7 @@ internal class DefaultApolloStore(
customScalarAdapters = customScalarAdapters,
cacheKeyGenerator = cacheKeyGenerator,
metadataGenerator = metadataGenerator,
- fieldNameGenerator = fieldNameGenerator,
+ fieldKeyGenerator = fieldKeyGenerator,
embeddedFieldsProvider = embeddedFieldsProvider,
).values.map { record ->
Record(
@@ -242,7 +242,7 @@ internal class DefaultApolloStore(
cacheResolver: Any,
cacheHeaders: CacheHeaders,
variables: Executable.Variables,
- fieldNameGenerator: FieldNameGenerator,
+ fieldKeyGenerator: FieldKeyGenerator,
): CacheData {
return when (cacheResolver) {
is CacheResolver -> readDataFromCacheInternal(
@@ -251,7 +251,7 @@ internal class DefaultApolloStore(
cacheResolver = cacheResolver,
cacheHeaders = cacheHeaders,
variables = variables,
- fieldNameGenerator = fieldNameGenerator,
+ fieldKeyGenerator = fieldKeyGenerator,
)
is ApolloResolver -> readDataFromCacheInternal(
@@ -260,7 +260,7 @@ internal class DefaultApolloStore(
cacheResolver = cacheResolver,
cacheHeaders = cacheHeaders,
variables = variables,
- fieldNameGenerator = fieldNameGenerator,
+ fieldKeyGenerator = fieldKeyGenerator,
)
else -> throw IllegalStateException()
diff --git a/tests/pagination/src/commonTest/kotlin/ConnectionProgrammaticPaginationTest.kt b/tests/pagination/src/commonTest/kotlin/ConnectionProgrammaticPaginationTest.kt
index e5f4d22db18..60bd4adcc5b 100644
--- a/tests/pagination/src/commonTest/kotlin/ConnectionProgrammaticPaginationTest.kt
+++ b/tests/pagination/src/commonTest/kotlin/ConnectionProgrammaticPaginationTest.kt
@@ -3,7 +3,7 @@ package pagination
import com.apollographql.apollo3.api.Optional
import com.apollographql.apollo3.cache.normalized.ApolloStore
import com.apollographql.apollo3.cache.normalized.api.ConnectionEmbeddedFieldsProvider
-import com.apollographql.apollo3.cache.normalized.api.ConnectionFieldNameGenerator
+import com.apollographql.apollo3.cache.normalized.api.ConnectionFieldKeyGenerator
import com.apollographql.apollo3.cache.normalized.api.ConnectionMetadataGenerator
import com.apollographql.apollo3.cache.normalized.api.ConnectionRecordMerger
import com.apollographql.apollo3.cache.normalized.api.FieldPolicyApolloResolver
@@ -54,7 +54,7 @@ class ConnectionProgrammaticPaginationTest {
metadataGenerator = ConnectionMetadataGenerator(connectionTypes),
apolloResolver = FieldPolicyApolloResolver,
recordMerger = ConnectionRecordMerger,
- fieldNameGenerator = ConnectionFieldNameGenerator(connectionFields),
+ fieldKeyGenerator = ConnectionFieldKeyGenerator(connectionFields),
embeddedFieldsProvider = ConnectionEmbeddedFieldsProvider(
connectionTypes = connectionTypes,
connectionFields = connectionFields
diff --git a/tests/pagination/src/commonTest/kotlin/OffsetBasedWithPageAndInputPaginationTest.kt b/tests/pagination/src/commonTest/kotlin/OffsetBasedWithPageAndInputPaginationTest.kt
index 5af35f7023b..d1339ebc929 100644
--- a/tests/pagination/src/commonTest/kotlin/OffsetBasedWithPageAndInputPaginationTest.kt
+++ b/tests/pagination/src/commonTest/kotlin/OffsetBasedWithPageAndInputPaginationTest.kt
@@ -6,9 +6,9 @@ import com.apollographql.apollo3.api.Executable
import com.apollographql.apollo3.api.Optional
import com.apollographql.apollo3.api.json.ApolloJsonElement
import com.apollographql.apollo3.cache.normalized.ApolloStore
-import com.apollographql.apollo3.cache.normalized.api.DefaultFieldNameGenerator
-import com.apollographql.apollo3.cache.normalized.api.FieldNameContext
-import com.apollographql.apollo3.cache.normalized.api.FieldNameGenerator
+import com.apollographql.apollo3.cache.normalized.api.DefaultFieldKeyGenerator
+import com.apollographql.apollo3.cache.normalized.api.FieldKeyContext
+import com.apollographql.apollo3.cache.normalized.api.FieldKeyGenerator
import com.apollographql.apollo3.cache.normalized.api.FieldPolicyApolloResolver
import com.apollographql.apollo3.cache.normalized.api.FieldRecordMerger
import com.apollographql.apollo3.cache.normalized.api.MemoryCacheFactory
@@ -54,7 +54,7 @@ class OffsetBasedWithPageAndInputPaginationTest {
metadataGenerator = OffsetPaginationMetadataGenerator("UserPage"),
apolloResolver = FieldPolicyApolloResolver,
recordMerger = FieldRecordMerger(OffsetPaginationFieldMerger()),
- fieldNameGenerator = UsersFieldNameGenerator,
+ fieldKeyGenerator = UsersFieldKeyGenerator,
)
apolloStore.clearAll()
@@ -237,12 +237,12 @@ class OffsetBasedWithPageAndInputPaginationTest {
}
}
- object UsersFieldNameGenerator : FieldNameGenerator {
- override fun getFieldName(context: FieldNameContext): String {
+ object UsersFieldKeyGenerator : FieldKeyGenerator {
+ override fun getFieldKey(context: FieldKeyContext): String {
return if (context.parentType == "Query" && context.field.name == "users") {
context.field.nameWithoutPaginationArguments(context.variables)
} else {
- DefaultFieldNameGenerator.getFieldName(context)
+ DefaultFieldKeyGenerator.getFieldKey(context)
}
}