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.

116 lines
3.5 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. package wow.doge.http4sdemo.dto
  2. import java.time.LocalDateTime
  3. import cats.syntax.either._
  4. import enumeratum.EnumEntry
  5. import enumeratum._
  6. import io.circe.Printer
  7. import io.circe.generic.semiauto._
  8. import io.scalaland.chimney.dsl._
  9. import org.http4s.EntityEncoder
  10. import org.http4s.ParseFailure
  11. import org.http4s.QueryParamDecoder
  12. import org.http4s.circe.streamJsonArrayEncoderWithPrinterOf
  13. import org.http4s.dsl.impl.QueryParamDecoderMatcher
  14. import slick.jdbc.JdbcProfile
  15. import wow.doge.http4sdemo.slickcodegen.Tables
  16. final case class Book(
  17. bookId: Int,
  18. bookTitle: String,
  19. isbn: String,
  20. authorId: Int,
  21. createdAt: LocalDateTime
  22. )
  23. object Book {
  24. def tupled = (apply _).tupled
  25. implicit val codec = deriveCodec[Book]
  26. // implicit def streamEntityEncoder[F[_]]
  27. // : EntityEncoder[F, fs2.Stream[F, Book]] =
  28. // streamJsonArrayEncoderWithPrinterOf(Printer.noSpaces)
  29. def fromBooksRow(row: Tables.BooksRow) = row.transformInto[Book]
  30. def fromBooksTableFn(implicit profile: JdbcProfile) = {
  31. import profile.api._
  32. (b: Tables.Books) =>
  33. (b.bookId, b.bookTitle, b.isbn, b.authorId, b.createdAt).mapTo[Book]
  34. }
  35. def fromBooksTable(implicit profile: JdbcProfile) =
  36. Tables.Books.map(fromBooksTableFn)
  37. }
  38. final case class NewBook(bookTitle: String, isbn: String, authorId: Int)
  39. object NewBook {
  40. def tupled = (apply _).tupled
  41. implicit val decoder = deriveDecoder[NewBook]
  42. def fromBooksTable(implicit profile: JdbcProfile) = {
  43. import profile.api._
  44. Tables.Books.map(b => (b.bookTitle, b.isbn, b.authorId).mapTo[NewBook])
  45. }
  46. }
  47. final case class BookUpdate(title: Option[String], authorId: Option[Int]) {
  48. import com.softwaremill.quicklens._
  49. def update(row: Tables.BooksRow): Tables.BooksRow =
  50. row
  51. .modify(_.bookTitle)
  52. .setToIfDefined(title)
  53. .modify(_.authorId)
  54. .setToIfDefined(authorId)
  55. }
  56. object BookUpdate {
  57. implicit val codec = deriveCodec[BookUpdate]
  58. }
  59. final case class Author(authorId: Int, authorName: String)
  60. object Author {
  61. def tupled = (apply _).tupled
  62. implicit val codec = deriveCodec[Author]
  63. implicit def streamEntityEncoder[F[_]]
  64. : EntityEncoder[F, fs2.Stream[F, Author]] =
  65. streamJsonArrayEncoderWithPrinterOf(Printer.noSpaces)
  66. def fromAuthorsRow(row: Tables.AuthorsRow) = row.transformInto[Author]
  67. def fromAuthorsTableFn(implicit profile: JdbcProfile) = {
  68. import profile.api._
  69. (a: Tables.Authors) => (a.authorId, a.authorName).mapTo[Author]
  70. }
  71. }
  72. final case class NewAuthor(name: String)
  73. object NewAuthor {
  74. // def fromAuthorsTable(implicit profile: JdbcProfile) = {
  75. // import profile.api._
  76. // Tables.Authors.map(a => (a.authorName).mapTo[NewAuthor])
  77. // }
  78. }
  79. final case class BookWithAuthor(
  80. id: Int,
  81. title: String,
  82. isbn: String,
  83. author: Author,
  84. createdAt: LocalDateTime
  85. )
  86. object BookWithAuthor {
  87. def tupled = (apply _).tupled
  88. implicit val codec = deriveCodec[BookWithAuthor]
  89. implicit def streamEntityEncoder[F[_]]
  90. : EntityEncoder[F, fs2.Stream[F, BookWithAuthor]] =
  91. streamJsonArrayEncoderWithPrinterOf(Printer.noSpaces)
  92. }
  93. sealed trait BookSearchMode extends EnumEntry
  94. object BookSearchMode extends Enum[BookSearchMode] {
  95. val values = findValues
  96. case object BookTitle extends BookSearchMode
  97. case object AuthorName extends BookSearchMode
  98. implicit val yearQueryParamDecoder: QueryParamDecoder[BookSearchMode] =
  99. QueryParamDecoder[String].emap(s =>
  100. withNameEither(s).leftMap(e => ParseFailure(e.getMessage, e.getMessage))
  101. )
  102. object Matcher extends QueryParamDecoderMatcher[BookSearchMode]("mode")
  103. }