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

io.getquill.CalibanIntegration.scala Maven / Gradle / Ivy

There is a newer version: 4.8.6
Show newest version
package io.getquill

import caliban.CalibanError.ExecutionError
import caliban.GraphQL.graphQL
import caliban.introspection.adt.{ __InputValue, __Type, __TypeKind }
import caliban.schema.{ ArgBuilder, Schema, Step }
import caliban.{ InputValue, RootResolver }
import caliban.execution.Field
import caliban.schema.Types
import caliban.Value

case class ProductArgs[T](keyValues: Map[String, String])

object CalibanIntegration:

  def quillColumns(field: Field) =
    def recurseFetchFields(field: Field): List[Field] =
      if (Types.innerType(field.fieldType).kind == __TypeKind.OBJECT)
          field.fields.flatMap(recurseFetchFields(_))
      else
        List(field)
    field.fields.flatMap(recurseFetchFields(_)).map(_.name)

  def flattenToPairs(key: String, value: InputValue): List[(String, String)] =
    value match {
      // If it contains other keys, continue to get the pairs inside
      // e.g. for `name` in Person(name: Name, age: Int) this would be Name from which we need first:String, last:String
      case InputValue.ObjectValue(fields) => fields.toList.flatMap { case (k, v) => flattenToPairs(k, v) }
      // Need to look at StringValue directly because calling .toInputString on it will give double quoting i.e. "\"value\""
      case Value.StringValue(value)       => List((key, value))
      case _                              => List((key, value.toInputString))
    }

  implicit def productArgBuilder[T]: ArgBuilder[ProductArgs[T]] = {
    case InputValue.ObjectValue(fields) =>
      Right(ProductArgs[T](fields.flatMap { case (k, v) => flattenToPairs(k, v).toMap }))
    case other                          => Left(ExecutionError(s"Can't build a ProductArgs from input $other"))
  }

  implicit def productSchema[T](implicit ev: Schema[Any, T]): Schema[Any, ProductArgs[T]] =
    new Schema[Any, ProductArgs[T]] {

      def makeOptionalRecurse(f: __InputValue): __InputValue = {
        val fieldType         = f.`type`()
        val optionalFieldType = fieldType.kind match {
          case __TypeKind.NON_NULL => fieldType.ofType.getOrElse(fieldType)
          case _                   => fieldType
        }
        f.copy(`type` =
          () => optionalFieldType.copy(inputFields = optionalFieldType.inputFields.map(_.map(makeOptionalRecurse)))
        )
      }

      protected[this] def toType(isInput: Boolean, isSubscription: Boolean): __Type =
        __Type(
          __TypeKind.INPUT_OBJECT,
          inputFields = ev
            .toType_(isInput, isSubscription)
            .inputFields
            .map(_.map(f => makeOptionalRecurse(f)))
        )

      def resolve(value: ProductArgs[T]): Step[Any] = Step.NullStep
    }

end CalibanIntegration




© 2015 - 2024 Weber Informatics LLC | Privacy Policy