All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.com.apollographql.apollo3.api.CustomScalarAdapters.kt Maven / Gradle / Ivy

There is a newer version: 4.0.0-beta.7
Show newest version
package com.apollographql.apollo3.api

import com.apollographql.apollo3.annotations.ApolloDeprecatedSince
import com.apollographql.apollo3.annotations.ApolloDeprecatedSince.Version.v3_0_0
import com.apollographql.apollo3.annotations.ApolloDeprecatedSince.Version.v3_2_1
import com.apollographql.apollo3.annotations.ApolloExperimental
import com.apollographql.apollo3.api.internal.Version2CustomTypeAdapterToAdapter
import kotlin.jvm.JvmField

/**
 * A wrapper around a Map used to retrieve custom scalar adapters at runtime
 */
class CustomScalarAdapters private constructor(
    customScalarAdapters: Map>,
    // We piggyback CustomScalarAdapters to pass around a context which is used in the Adapters at parse time.
    // This is currently used for @skip/@include and @defer.
    // Ideally it should be passed as its own parameter, but we're avoiding a breaking change.
    // See https://github.com/apollographql/apollo-kotlin/pull/3813
    val adapterContext: AdapterContext,
    private val unsafe: Boolean
) : ExecutionContext.Element {

  private val adaptersMap: Map> = customScalarAdapters

  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.apollo3.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 CustomScalarAdapter?")
    } as Adapter
  }

  @Deprecated("Use adapterContext.variables() instead", ReplaceWith("adapterContext.variables()"))
  @ApolloDeprecatedSince(v3_2_1)
  fun variables() = adapterContext.variables()

  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()
  }

  fun newBuilder() = Builder().addAll(this)

  class Builder {
    private val adaptersMap: MutableMap> = mutableMapOf()
    private var adapterContext: AdapterContext = AdapterContext.Builder().build()
    private var unsafe = false

    fun  add(
        customScalarType: CustomScalarType,
        customScalarAdapter: Adapter,
    ) = apply {
      adaptersMap[customScalarType.name] = customScalarAdapter
    }

    @Suppress("DEPRECATION")
    @Deprecated("Used for backward compatibility with 2.x")
    @ApolloDeprecatedSince(v3_0_0)
    fun  add(
        customScalarType: CustomScalarType,
        customTypeAdapter: CustomTypeAdapter,
    ) = apply {
      adaptersMap[customScalarType.name] = Version2CustomTypeAdapterToAdapter(customTypeAdapter)
    }

    fun addAll(customScalarAdapters: CustomScalarAdapters) = apply {
      this.adaptersMap.putAll(customScalarAdapters.adaptersMap)
    }

    @ApolloExperimental
    fun unsafe(unsafe: Boolean) = apply {
      this.unsafe = unsafe
    }

    fun clear() {
      adaptersMap.clear()
    }

    @Suppress("DEPRECATION")
    fun build() = CustomScalarAdapters(adaptersMap, adapterContext, unsafe)

    fun adapterContext(adapterContext: AdapterContext): Builder = apply {
      this.adapterContext = adapterContext
    }

    @Deprecated("Use AdapterContext.Builder.variables() instead")
    @ApolloDeprecatedSince(v3_2_1)
    fun variables(variables: Executable.Variables): Builder = apply {
      adapterContext = adapterContext.newBuilder().variables(variables).build()
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy