pepegar / hammock
1
import cats._
2
import cats.data.{EitherK, NonEmptyList}
3
import cats.free.Free
4
import cats.effect.Sync
5
import contextual._
6

7
package object hammock {
8

9
  import hammock.marshalling._
10
  import hammock.InterpTrans
11

12
  type HammockF[A] = EitherK[HttpF, MarshallF, A]
13

14
  implicit class HttpRequestIOSyntax[A](fa: Free[HttpF, A]) {
15
    def exec[F[_]: Sync](implicit interp: InterpTrans[F]): F[A] =
16 0
      fa foldMap interp.trans
17
  }
18

19
  implicit class HammockFSyntax[A](fa: Free[HammockF, A]) {
20
    def exec[F[_]: Sync](implicit NT: HammockF ~> F): F[A] =
21 0
      fa foldMap NT
22
  }
23

24
  implicit class AsSyntaxOnHttpF[F[_], A](fa: Free[F, HttpResponse])(
25
      implicit
26
      H: InjectK[HttpF, F]) {
27
    def as[B](implicit D: Decoder[B], M: MarshallC[EitherK[F, MarshallF, *]]): Free[EitherK[F, MarshallF, *], B] =
28 0
      fa.inject[EitherK[F, MarshallF, *]] flatMap { response =>
29 0
        M.unmarshall(response.entity)
30
      }
31
  }
32

33
  implicit def hammockNT[F[_]: Sync](
34
      implicit H: InterpTrans[F],
35
      M: MarshallF ~> F
36 0
  ): HammockF ~> F = H.trans or M
37

38
  object UriContext extends Context
39

40
  object UriInterpolator extends Interpolator {
41
    type Output      = Uri
42
    type ContextType = UriContext.type
43
    type Input       = String
44
    def contextualize(interpolation: StaticInterpolation) = {
45 1
      interpolation.parts.foldLeft(List.empty[ContextType]) {
46 1
        case (contexts, Hole(_, _)) => UriContext :: contexts
47
        case (contexts, _)          => contexts
48
      }
49
    }
50

51
    def evaluate(interpolation: RuntimeInterpolation): Uri = {
52
      val substituted = interpolation.literals
53
        .zipAll(interpolation.substitutions, "", "")
54
        .flatMap(x => List(x._1, x._2))
55 1
        .mkString("")
56 1
      Uri.fromString(substituted).right.get
57
    }
58

59
  }
60

61 1
  implicit val embedString = UriInterpolator.embed[String](Case(UriContext, UriContext) { x =>
62
    x
63
  })
64

65
  /**
66
   * Unsafe string interpolator allowing uri parsing.  It's unsafe
67
   * because in case of any error happen (a Left is returned by the
68
   * `fromString` method), it will throw an exception.
69
   *
70
   * {{{
71
   * scala> uri"http://user:pass@pepegar.com/path?page=4#index"
72
   * res1: hammock.Uri = Uri(Some(http),Some(user:pass),pepegar.com/path,Map(page -> 4),Some(index))
73
   * }}}
74
   */
75
  implicit class UriStringContext(sc: StringContext) {
76 0
    val uri = Prefix(UriInterpolator, sc)
77
  }
78

79
  /**
80
   * Methods providing URI query parameters building syntax
81
   * Used in [[Uri.?]] method
82
    **/
83
  implicit class UriQueryParamsBuilder(val self: NonEmptyList[(String, String)]) extends AnyVal {
84 0
    def &(param: (String, String)): NonEmptyList[(String, String)] = param :: self
85
  }
86
  implicit class UriQueryInitBuilder(val self: (String, String)) extends AnyVal {
87 0
    def &(param: (String, String)): NonEmptyList[(String, String)] = NonEmptyList(self, param :: Nil)
88
  }
89
}

Read our documentation on viewing source code .

Loading