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

io.finch.EndpointModule.scala Maven / Gradle / Ivy

package io.finch

import cats.Applicative
import cats.data.NonEmptyList
import cats.effect.{Resource, Sync}
import com.twitter.finagle.http.exp.Multipart
import com.twitter.finagle.http.{Cookie, Request}
import com.twitter.io.Buf
import shapeless.HNil

import java.io.{File, InputStream}
import scala.reflect.ClassTag

/** Enables users to construct [[Endpoint]] instances without specifying the effect type `F[_]` every time.
  *
  * For example, via extending the `Endpoint.Module[F[_]]`:
  *
  * {{{
  *   import io.finch._
  *   import io.cats.effect.IO
  *
  *   object Main extends App with Endpoint.Module[IO] {
  *     def foo = path("foo")
  *   }
  * }}}
  *
  * It's also possible to instantiate an [[EndpointModule]] for a given effect and import its symbols into the score. For example:
  *
  * {{{
  *   import io.finch._
  *   import io.cats.effect.IO
  *
  *   object Main extends App {
  *     val io = Endpoint[IO]
  *     import io._
  *
  *     def foo = path("foo")
  *   }
  * }}}
  *
  * There is a pre-defined [[EndpointModule]] for Cats' `IO`, available via the import:
  *
  * {{{
  *   import io.finch._
  *   import io.finch.catsEffect._
  *
  *   object Main extends App {
  *     def foo = path("foo")
  *   }
  * }}}
  */
trait EndpointModule[F[_]] {

  /** An alias for [[Endpoint.empty]].
    */
  def empty[A]: Endpoint[F, A] =
    Endpoint.empty[F, A]

  /** An alias for [[Endpoint.zero]].
    */
  def zero(implicit F: Applicative[F]): Endpoint[F, HNil] =
    Endpoint.zero[F]

  /** An alias for [[Endpoint.const]].
    */
  def const[A](a: A)(implicit F: Applicative[F]): Endpoint[F, A] =
    Endpoint.const[F, A](a)

  /** An alias for [[Endpoint.lift]]. */
  def lift[A](a: => A)(implicit F: Sync[F]): Endpoint[F, A] =
    Endpoint.lift[F, A](a)

  /** An alias for [[Endpoint.liftAsync]].
    */
  def liftAsync[A](fa: => F[A])(implicit F: Sync[F]): Endpoint[F, A] =
    Endpoint.liftAsync[F, A](fa)

  /** An alias for [[Endpoint.liftOutput]].
    */
  def liftOutput[A](oa: => Output[A])(implicit F: Sync[F]): Endpoint[F, A] =
    Endpoint.liftOutput[F, A](oa)

  /** An alias for [[Endpoint.liftOutputAsync]].
    */
  def liftOutputAsync[A](foa: => F[Output[A]])(implicit F: Sync[F]): Endpoint[F, A] =
    Endpoint.liftOutputAsync[F, A](foa)

  /** An alias for [[Endpoint.fromInputStream]]. */
  def fromInputStream(stream: Resource[F, InputStream])(implicit F: Sync[F]): Endpoint[F, Buf] =
    Endpoint.fromInputStream[F](stream)

  /** An alias for [[Endpoint.fromFile]]. */
  def fromFile(file: File)(implicit F: Sync[F]): Endpoint[F, Buf] =
    Endpoint.fromFile[F](file)

  /** An alias for [[Endpoint.classpathAsset]]. */
  def classpathAsset(path: String)(implicit F: Sync[F]): Endpoint[F, Buf] =
    Endpoint.classpathAsset[F](path)

  /** An alias for [[Endpoint.classpathAsset]]. */
  def filesystemAsset(path: String)(implicit F: Sync[F]): Endpoint[F, Buf] =
    Endpoint.filesystemAsset[F](path)

  /** An alias for [[Endpoint.root]].
    */
  def root(implicit F: Sync[F]): Endpoint[F, Request] =
    Endpoint.root[F]

  /** An alias for [[Endpoint.pathAny]].
    */
  def pathAny(implicit F: Applicative[F]): Endpoint[F, HNil] =
    Endpoint.pathAny[F]

  /** An alias for [[Endpoint.pathEmpty]].
    */
  def pathEmpty(implicit F: Applicative[F]): Endpoint[F, HNil] =
    Endpoint.pathEmpty[F]

  /** An alias for `Endpoint.path`. */
  def path[A: DecodePath: ClassTag](implicit F: Sync[F]): Endpoint[F, A] =
    Endpoint.path[F, A]

  /** An alias for [[Endpoint.paths]].
    */
  def paths[A: DecodePath: ClassTag](implicit F: Sync[F]): Endpoint[F, List[A]] =
    Endpoint.paths[F, A]

  /** An alias for `Endpoint.path`.
    *
    * @note
    *   This method is implicit such that an implicit conversion `String => Endpoint[F, HNil]` works.
    */
  implicit def path(s: String)(implicit F: Sync[F]): Endpoint[F, HNil] =
    Endpoint.path[F](s)

  /** An alias for [[Endpoint.get]].
    */
  def get[A](e: Endpoint[F, A]): Endpoint.Mappable[F, A] =
    Endpoint.get[F, A](e)

  /** An alias for [[Endpoint.post]].
    */
  def post[A](e: Endpoint[F, A]): Endpoint.Mappable[F, A] =
    Endpoint.post[F, A](e)

  /** An alias for [[Endpoint.patch]].
    */
  def patch[A](e: Endpoint[F, A]): Endpoint.Mappable[F, A] =
    Endpoint.patch[F, A](e)

  /** An alias for [[Endpoint.delete]].
    */
  def delete[A](e: Endpoint[F, A]): Endpoint.Mappable[F, A] =
    Endpoint.delete[F, A](e)

  /** An alias for [[Endpoint.head]].
    */
  def head[A](e: Endpoint[F, A]): Endpoint.Mappable[F, A] =
    Endpoint.head[F, A](e)

  /** An alias for [[Endpoint.options]].
    */
  def options[A](e: Endpoint[F, A]): Endpoint.Mappable[F, A] =
    Endpoint.options[F, A](e)

  /** An alias for [[Endpoint.put]].
    */
  def put[A](e: Endpoint[F, A]): Endpoint.Mappable[F, A] =
    Endpoint.put[F, A](e)

  /** An alias for [[Endpoint.trace]].
    */
  def trace[A](e: Endpoint[F, A]): Endpoint.Mappable[F, A] =
    Endpoint.trace[F, A](e)

  /** An alias for [[Endpoint.header]].
    */
  def header[A: DecodeEntity: ClassTag](name: String)(implicit F: Sync[F]): Endpoint[F, A] =
    Endpoint.header[F, A](name)

  /** An alias for [[Endpoint.headerOption]].
    */
  def headerOption[A: DecodeEntity: ClassTag](name: String)(implicit F: Sync[F]): Endpoint[F, Option[A]] =
    Endpoint.headerOption[F, A](name)

  /** An alias for [[Endpoint.binaryBodyOption]].
    */
  def binaryBodyOption(implicit F: Sync[F]): Endpoint[F, Option[Array[Byte]]] =
    Endpoint.binaryBodyOption[F]

  /** An alias for [[Endpoint.binaryBody]].
    */
  def binaryBody(implicit F: Sync[F]): Endpoint[F, Array[Byte]] =
    Endpoint.binaryBody[F]

  /** An alias for [[Endpoint.stringBodyOption]].
    */
  def stringBodyOption(implicit F: Sync[F]): Endpoint[F, Option[String]] =
    Endpoint.stringBodyOption[F]

  /** An alias for [[Endpoint.stringBody]].
    */
  def stringBody(implicit F: Sync[F]): Endpoint[F, String] =
    Endpoint.stringBody[F]

  /** An alias for [[Endpoint.bodyOption]].
    */
  def bodyOption[A: ClassTag, CT](implicit F: Sync[F], D: Decode.Dispatchable[A, CT]): Endpoint[F, Option[A]] =
    Endpoint.bodyOption[F, A, CT]

  /** An alias for [[Endpoint.body]].
    */
  def body[A: ClassTag, CT](implicit D: Decode.Dispatchable[A, CT], F: Sync[F]): Endpoint[F, A] =
    Endpoint.body[F, A, CT]

  /** An alias for [[Endpoint.jsonBody]].
    */
  def jsonBody[A: Decode.Json: ClassTag](implicit F: Sync[F]): Endpoint[F, A] =
    Endpoint.jsonBody[F, A]

  /** An alias for [[Endpoint.jsonBodyOption]].
    */
  def jsonBodyOption[A: Decode.Json: ClassTag](implicit F: Sync[F]): Endpoint[F, Option[A]] =
    Endpoint.jsonBodyOption[F, A]

  /** An alias for [[Endpoint.textBody]].
    */
  def textBody[A: Decode.Text: ClassTag](implicit F: Sync[F]): Endpoint[F, A] =
    Endpoint.textBody[F, A]

  /** An alias for [[Endpoint.textBodyOption]].
    */
  def textBodyOption[A: Decode.Text: ClassTag](implicit F: Sync[F]): Endpoint[F, Option[A]] =
    Endpoint.textBodyOption[F, A]

  /** An alias for [[Endpoint.binaryBodyStream]].
    */
  def binaryBodyStream[S[_[_], _]](implicit
      F: Sync[F],
      LR: LiftReader[S, F]
  ): Endpoint[F, S[F, Array[Byte]]] = Endpoint.binaryBodyStream[F, S]

  /** An alias for [[Endpoint.stringBodyStream]].
    */
  def stringBodyStream[S[_[_], _]](implicit
      F: Sync[F],
      LR: LiftReader[S, F]
  ): Endpoint[F, S[F, String]] = Endpoint.stringBodyStream[F, S]

  /** An alias for [[Endpoint.bodyStream]].
    */
  def bodyStream[S[_[_], _], A, CT <: String](implicit
      F: Sync[F],
      LR: LiftReader[S, F],
      A: DecodeStream.Aux[S, F, A, CT]
  ): Endpoint[F, S[F, A]] = Endpoint.bodyStream[F, S, A, CT]

  /** An alias for [[Endpoint.jsonBodyStream]].
    */
  def jsonBodyStream[S[_[_], _], A](implicit
      F: Sync[F],
      LR: LiftReader[S, F],
      A: DecodeStream.Aux[S, F, A, Application.Json]
  ): Endpoint[F, S[F, A]] = Endpoint.jsonBodyStream[F, S, A]

  /** An alias for [[Endpoint.textBodyStream]].
    */
  def textBodyStream[S[_[_], _], A](implicit
      F: Sync[F],
      LR: LiftReader[S, F],
      A: DecodeStream.Aux[S, F, A, Text.Plain]
  ): Endpoint[F, S[F, A]] = Endpoint.textBodyStream[F, S, A]

  /** An alias for [[Endpoint.cookieOption]].
    */
  def cookieOption(name: String)(implicit F: Sync[F]): Endpoint[F, Option[Cookie]] =
    Endpoint.cookieOption[F](name)

  /** An alias for [[Endpoint.cookie]].
    */
  def cookie(name: String)(implicit F: Sync[F]): Endpoint[F, Cookie] =
    Endpoint.cookie[F](name)

  /** An alias for [[Endpoint.paramOption]].
    */
  def paramOption[A: DecodeEntity: ClassTag](name: String)(implicit F: Sync[F]): Endpoint[F, Option[A]] =
    Endpoint.paramOption[F, A](name)

  /** An alias for [[Endpoint.param]].
    */
  def param[A: DecodeEntity: ClassTag](name: String)(implicit F: Sync[F]): Endpoint[F, A] =
    Endpoint.param[F, A](name)

  /** An alias for [[Endpoint.params]].
    */
  def params[A: DecodeEntity: ClassTag](name: String)(implicit F: Sync[F]): Endpoint[F, List[A]] =
    Endpoint.params[F, A](name)

  /** An alias for [[Endpoint.paramsNel]].
    */
  def paramsNel[A: DecodeEntity: ClassTag](name: String)(implicit F: Sync[F]): Endpoint[F, NonEmptyList[A]] =
    Endpoint.paramsNel[F, A](name)

  /** An alias for [[Endpoint.multipartFileUploadOption]].
    */
  def multipartFileUploadOption(name: String)(implicit F: Sync[F]): Endpoint[F, Option[Multipart.FileUpload]] =
    Endpoint.multipartFileUploadOption[F](name)

  /** An alias for [[Endpoint.multipartFileUpload]].
    */
  def multipartFileUpload(name: String)(implicit F: Sync[F]): Endpoint[F, Multipart.FileUpload] =
    Endpoint.multipartFileUpload[F](name)

  /** An alias for [[Endpoint.multipartFileUploads]].
    */
  def multipartFileUploads(name: String)(implicit F: Sync[F]): Endpoint[F, List[Multipart.FileUpload]] =
    Endpoint.multipartFileUploads[F](name)

  /** An alias for [[Endpoint.multipartFileUploadsNel]].
    */
  def multipartFileUploadsNel(name: String)(implicit F: Sync[F]): Endpoint[F, NonEmptyList[Multipart.FileUpload]] =
    Endpoint.multipartFileUploadsNel[F](name)

  /** An alias for [[Endpoint.multipartAttribute]].
    */
  def multipartAttribute[A: DecodeEntity: ClassTag](name: String)(implicit F: Sync[F]): Endpoint[F, A] =
    Endpoint.multipartAttribute[F, A](name)

  /** An alias for [[Endpoint.multipartAttributeOption]].
    */
  def multipartAttributeOption[A: DecodeEntity: ClassTag](name: String)(implicit F: Sync[F]): Endpoint[F, Option[A]] =
    Endpoint.multipartAttributeOption[F, A](name)

  /** An alias for [[Endpoint.multipartAttributes]].
    */
  def multipartAttributes[A: DecodeEntity: ClassTag](name: String)(implicit F: Sync[F]): Endpoint[F, List[A]] =
    Endpoint.multipartAttributes[F, A](name)

  /** An alias for [[Endpoint.multipartAttributesNel]].
    */
  def multipartAttributesNel[A: DecodeEntity: ClassTag](name: String)(implicit F: Sync[F]): Endpoint[F, NonEmptyList[A]] =
    Endpoint.multipartAttributesNel[F, A](name)
}

object EndpointModule {
  def apply[F[_]]: EndpointModule[F] = catsEffect.asInstanceOf[EndpointModule[F]]
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy