You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

144 lines
4.3 KiB

package wow.doge.http4sdemo
import cats.effect.Sync
import cats.implicits._
import fs2.interop.reactivestreams._
import io.circe.Codec
import io.circe.generic.semiauto._
import monix.bio.Task
import monix.reactive.Observable
import org.http4s.HttpRoutes
import org.http4s.dsl.Http4sDsl
import slick.jdbc.JdbcBackend.DatabaseDef
import slick.jdbc.JdbcProfile
import wow.doge.http4sdemo.dto.Book
import wow.doge.http4sdemo.dto.BookUpdate
import wow.doge.http4sdemo.dto.NewBook
import wow.doge.http4sdemo.services.LibraryService
import wow.doge.http4sdemo.slickcodegen.Tables._
object Http4sdemoRoutes {
def jokeRoutes[F[_]: Sync](J: Jokes[F]): HttpRoutes[F] = {
val dsl = Http4sDsl[F]
import dsl._
HttpRoutes.of[F] { case GET -> Root / "joke" =>
for {
joke <- J.get
resp <- Ok(joke)
} yield resp
}
}
def helloWorldRoutes[F[_]: Sync](H: HelloWorld[F]): HttpRoutes[F] = {
val dsl = new Http4sDsl[F] {}
import dsl._
HttpRoutes.of[F] { case GET -> Root / "hello" / name =>
for {
greeting <- H.hello(HelloWorld.Name(name))
resp <- Ok(greeting)
r2 <- BadRequest("Bad request")
} yield r2
}
}
def userRoutes(userService: UserService): HttpRoutes[Task] = {
val dsl = Http4sDsl[Task]
import dsl._
import org.http4s.circe.CirceEntityCodec._
HttpRoutes.of[Task] { case GET -> Root / "users" =>
Task.deferAction(implicit s =>
for {
_ <- Task.unit
users = userService.users.toReactivePublisher.toStream[Task]
res <- Ok(users)
} yield res
)
}
}
def libraryRoutes(libraryService: LibraryService): HttpRoutes[Task] = {
val dsl = Http4sDsl[Task]
import dsl._
HttpRoutes.of[Task] {
case GET -> Root / "api" / "get" / "books" =>
import org.http4s.circe.streamJsonArrayEncoder
import io.circe.syntax._
Task.deferAction(implicit s =>
for {
books <- Task.pure(
libraryService.getBooks.toReactivePublisher
.toStream[Task]
)
res <- Ok(books.map(_.asJson))
} yield res
)
case GET -> Root / "api" / "get" / "book" / IntVar(id) =>
// import org.http4s.circe.CirceEntityCodec._
import org.http4s.circe.jsonEncoder
import io.circe.syntax._
for {
bookJson <- libraryService.getBookById(id).map(_.asJson)
res <- Ok(bookJson)
} yield res
case req @ POST -> Root / "api" / "post" / "book" =>
import org.http4s.circe.CirceEntityCodec._
for {
newBook <- req.as[NewBook]
book <- libraryService.insertBook(newBook)
res <- Created(book)
} yield res
case req @ PATCH -> Root / "api" / "update" / "book" / IntVar(id) =>
import org.http4s.circe.CirceEntityCodec._
for {
updateData <- req.as[BookUpdate]
_ <- libraryService
.updateBook(id, updateData)
.void
.onErrorHandleWith(ex =>
Task(println(s"Handled -> ${ex.getMessage}"))
)
// .mapError(e => new Exception(e))
res <- Ok()
} yield res
case req @ DELETE -> Root / "api" / "delete" / "book" / IntVar(id) =>
for {
_ <- libraryService.deleteBook(id)
res <- Ok()
} yield res
case req @ POST -> Root / "api" / "post" / "books" / "read" =>
import org.http4s.circe.CirceEntityCodec.circeEntityDecoder
for {
newBook <- req.as[List[Book]]
// book <- libraryService.insertBook(newBook)
res <- Ok("blah")
} yield res
}
}
}
case class User(id: String, email: String)
object User {
val tupled = (this.apply _).tupled
// implicit val decoder: Decoder[User] = deriveDecoder
// implicit def entityDecoder[F[_]: Sync]: EntityDecoder[F, User] =
// jsonOf
// implicit val encoder: Encoder[User] = deriveEncoder
// implicit def entityEncoder[F[_]: Applicative]: EntityEncoder[F, User] =
// jsonEncoderOf
implicit val codec: Codec[User] = deriveCodec
}
class UserService(profile: JdbcProfile, db: DatabaseDef) {
import profile.api._
def users: Observable[User] =
Observable.fromReactivePublisher(
db.stream(Users.map(u => (u.id, u.email).mapTo[User]).result)
)
}