commonMain.com.apollographql.apollo.api.CustomScalarAdapters.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of apollo-api-jvm Show documentation
Show all versions of apollo-api-jvm Show documentation
Apollo GraphQL API classes
The newest version!
package com.apollographql.apollo.api
import com.apollographql.apollo.annotations.ApolloExperimental
import kotlin.jvm.JvmField
/**
* A wrapper around a Map used to retrieve custom scalar adapters at runtime.
*
* For historical reasons, it also contains other context used when parsing response.
* See https://github.com/apollographql/apollo-kotlin/pull/3813
*/
class CustomScalarAdapters private constructor(
customScalarAdapters: Map>,
/**
* Operation variables used to determine whether the parser must parse @skip/@include fragments
*
*/
@JvmField
val falseVariables: Set?,
/**
* Defer identifiers used to determine whether the parser must parse @defer fragments
*/
@JvmField
val deferredFragmentIdentifiers: Set?,
/**
* Errors to use with @catch
*/
@JvmField
val errors: List?,
private val unsafe: Boolean,
) : ExecutionContext.Element {
private val adaptersMap: Map> = customScalarAdapters
fun adapterFor(name: String): Adapter? {
@Suppress("UNCHECKED_CAST")
return adaptersMap[name] as Adapter?
}
fun responseAdapterFor(customScalar: CustomScalarType): Adapter {
@Suppress("UNCHECKED_CAST")
return when {
adaptersMap[customScalar.name] != null -> {
adaptersMap[customScalar.name]
}
/**
* Below are shortcuts to save the users a call to `registerCustomScalarAdapter`
*/
customScalar.className == "com.apollographql.apollo.api.Upload" -> {
UploadAdapter
}
customScalar.className in listOf("kotlin.String", "java.lang.String") -> {
StringAdapter
}
customScalar.className in listOf("kotlin.Boolean", "java.lang.Boolean") -> {
BooleanAdapter
}
customScalar.className in listOf("kotlin.Int", "java.lang.Int") -> {
IntAdapter
}
customScalar.className in listOf("kotlin.Double", "java.lang.Double") -> {
DoubleAdapter
}
customScalar.className in listOf("kotlin.Long", "java.lang.Long") -> {
LongAdapter
}
customScalar.className in listOf("kotlin.Float", "java.lang.Float") -> {
FloatAdapter
}
customScalar.className in listOf("kotlin.Any", "java.lang.Object") -> {
AnyAdapter
}
unsafe -> PassThroughAdapter()
else -> error("Can't map GraphQL type: `${customScalar.name}` to: `${customScalar.className}`. Did you forget to add a scalar Adapter?")
} as Adapter
}
override val key: ExecutionContext.Key<*>
get() = Key
companion object Key : ExecutionContext.Key {
/**
* An empty [CustomScalarAdapters]. If the models were generated with some custom scalars, parsing will fail
*/
@JvmField
val Empty = Builder().build()
/**
* Unsafe [CustomScalarAdapters]. They can only be used with `MapJsonReader` and `MapJsonWriter`. It will passthrough the values using
* `MapJsonReader.nextValue` and `MapJsonWriter.value()`
*/
@JvmField
@ApolloExperimental
val PassThrough = Builder().unsafe(true).build()
}
@ApolloExperimental
fun firstErrorStartingWith(path: List): Error? {
return errors?.firstOrNull {
it.path?.startsWith(path) == true
}
}
private fun List.startsWith(responsePath: List): Boolean {
// start at 1 to drop the `data.`
for (i in 1.until(responsePath.size)) {
if (i - 1 >= this.size) {
return false
}
if (responsePath[i] != this[i - 1]) {
return false
}
}
return true
}
fun newBuilder(): Builder {
return Builder().addAll(this)
.falseVariables(falseVariables)
.deferredFragmentIdentifiers(deferredFragmentIdentifiers)
}
class Builder {
private val adaptersMap: MutableMap> = mutableMapOf()
private var unsafe = false
private var falseVariables: Set? = null
private var deferredFragmentIdentifiers: Set? = null
private var errors: List? = null
fun falseVariables(falseVariables: Set?) = apply {
this.falseVariables = falseVariables
}
fun deferredFragmentIdentifiers(deferredFragmentIdentifiers: Set?) = apply {
this.deferredFragmentIdentifiers = deferredFragmentIdentifiers
}
fun errors(errors: List?) = apply {
this.errors = errors
}
fun add(
name: String,
adapter: Adapter,
) = apply {
adaptersMap[name] = adapter
}
fun add(
customScalarType: CustomScalarType,
customScalarAdapter: Adapter,
) = apply {
adaptersMap[customScalarType.name] = customScalarAdapter
}
fun addAll(customScalarAdapters: CustomScalarAdapters) = apply {
this.adaptersMap.putAll(customScalarAdapters.adaptersMap)
}
@ApolloExperimental
fun unsafe(unsafe: Boolean) = apply {
this.unsafe = unsafe
}
fun clear() {
adaptersMap.clear()
}
fun build(): CustomScalarAdapters {
return CustomScalarAdapters(
adaptersMap,
falseVariables,
deferredFragmentIdentifiers,
errors,
unsafe,
)
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy