diff --git a/README.md b/README.md index eb1e350..852a038 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ A series of implemetations of [Todo-Backend][todo-backend] REST API in **Scala** using different libraries. -- [x] Using `http4s` with `cats-effect` -- [ ] Using `zio-http` with `zio` +- [x] Using `http4s` with `cats-effect`: see `todobackend-http4s` module +- [ ] Using `zio-http` with `zio`: see `todobackend-zio` module [todo-backend]: https://www.todobackend.com/ diff --git a/common/src/main/scala/es/jesusmtnez/todobackend/TodoRepository.scala b/common/src/main/scala/es/jesusmtnez/todobackend/TodoRepository.scala deleted file mode 100644 index 22c3e5f..0000000 --- a/common/src/main/scala/es/jesusmtnez/todobackend/TodoRepository.scala +++ /dev/null @@ -1,19 +0,0 @@ -package es.jesusmtnez.todobackend - -import es.jesusmtnez.todobackend.domain.TodoItem - -import java.util.UUID - -trait TodoRepository[F[_]] { - def create(title: String, order: Option[Int]): F[Option[TodoItem]] - def delete(id: UUID): F[Unit] - def deleteAll(): F[Unit] - def getAll(): F[List[TodoItem]] - def getById(id: UUID): F[Option[TodoItem]] - def update( - id: UUID, - title: Option[String], - completed: Option[Boolean], - order: Option[Int] - ): F[Option[TodoItem]] -} diff --git a/todobackend-http4s/src/main/scala/es/jesusmtnez/todobackend/Main.scala b/todobackend-http4s/src/main/scala/es/jesusmtnez/todobackend/Main.scala deleted file mode 100644 index 0c3ff36..0000000 --- a/todobackend-http4s/src/main/scala/es/jesusmtnez/todobackend/Main.scala +++ /dev/null @@ -1,6 +0,0 @@ -package es.jesusmtnez.todobackend - -import cats.effect.{IO, IOApp} - -object Main extends IOApp.Simple: - val run = TodoBackendServer.run[IO] diff --git a/todobackend-http4s/src/main/scala/es/jesusmtnez/todobackend/TodoBackendServer.scala b/todobackend-http4s/src/main/scala/es/jesusmtnez/todobackend/TodoBackendApp.scala similarity index 85% rename from todobackend-http4s/src/main/scala/es/jesusmtnez/todobackend/TodoBackendServer.scala rename to todobackend-http4s/src/main/scala/es/jesusmtnez/todobackend/TodoBackendApp.scala index e82260f..e6ebd16 100644 --- a/todobackend-http4s/src/main/scala/es/jesusmtnez/todobackend/TodoBackendServer.scala +++ b/todobackend-http4s/src/main/scala/es/jesusmtnez/todobackend/TodoBackendApp.scala @@ -11,9 +11,10 @@ import org.typelevel.log4cats.slf4j.Slf4jFactory import org.http4s.Method import org.typelevel.ci.CIString -object TodoBackendServer { +object TodoBackendApp extends IOApp.Simple: + val run = startServer[IO] - def run[F[_]: Async: Network]: F[Unit] = + def startServer[F[_]: Async: Network]: F[Unit] = implicit val loggerFactory: LoggerFactory[F] = Slf4jFactory.create[F] val cors = @@ -28,14 +29,11 @@ object TodoBackendServer { ) ) .withAllowHeadersIn(Set(CIString("content-type"))) - for { - repository <- TodoRepositoryImpl.inMemory[F]() + repository <- TodoRepository.inMemory[F]() routes = TodoBackendRoutes.about[F]() <+> TodoBackendRoutes.todo[F](repository) httpApp <- cors(Logger.httpApp(true, true)(routes.orNotFound)) _ <- EmberServerBuilder.default[F].withHttpApp(httpApp).build.useForever } yield () - -} diff --git a/todobackend-http4s/src/main/scala/es/jesusmtnez/todobackend/TodoRepositoryImpl.scala b/todobackend-http4s/src/main/scala/es/jesusmtnez/todobackend/TodoRepository.scala similarity index 79% rename from todobackend-http4s/src/main/scala/es/jesusmtnez/todobackend/TodoRepositoryImpl.scala rename to todobackend-http4s/src/main/scala/es/jesusmtnez/todobackend/TodoRepository.scala index 1d6b2f1..d97a8db 100644 --- a/todobackend-http4s/src/main/scala/es/jesusmtnez/todobackend/TodoRepositoryImpl.scala +++ b/todobackend-http4s/src/main/scala/es/jesusmtnez/todobackend/TodoRepository.scala @@ -7,10 +7,30 @@ import es.jesusmtnez.todobackend.domain.TodoItem import java.util.UUID -object TodoRepositoryImpl { +trait TodoRepository[F[_]] { + def create(title: String, order: Option[Int]): F[Option[TodoItem]] + def delete(id: UUID): F[Unit] + def deleteAll(): F[Unit] + def getAll(): F[List[TodoItem]] + def getById(id: UUID): F[Option[TodoItem]] + def update( + id: UUID, + title: Option[String], + completed: Option[Boolean], + order: Option[Int] + ): F[Option[TodoItem]] +} + +object TodoRepository: + + def inMemory[F[_]: Sync](): F[TodoRepository[F]] = + Ref[F] + .of(Map.empty[UUID, TodoItem]) + .map(new InMemory[F](_)) + private final case class InMemory[F[_]: Sync]( private val store: Ref[F, Map[UUID, TodoItem]] - ) extends TodoRepository[F] { + ) extends TodoRepository[F]: override def create( title: String, @@ -62,12 +82,3 @@ object TodoRepositoryImpl { .fold(items)(item => items.removed(id) + (id -> item)) } .map(_.get(id)) - } - - def inMemory[F[_]: Sync](): F[TodoRepository[F]] = - Ref[F] - .of(Map.empty[UUID, TodoItem]) - .map( - new InMemory[F](_) - ) -} diff --git a/todobackend-http4s/src/test/scala/es/jesusmtnez/todobackend/InMemoryRepositorySuite.scala b/todobackend-http4s/src/test/scala/es/jesusmtnez/todobackend/InMemoryRepositorySuite.scala index 8ebf494..f95b02d 100644 --- a/todobackend-http4s/src/test/scala/es/jesusmtnez/todobackend/InMemoryRepositorySuite.scala +++ b/todobackend-http4s/src/test/scala/es/jesusmtnez/todobackend/InMemoryRepositorySuite.scala @@ -6,7 +6,7 @@ import es.jesusmtnez.todobackend.domain.TodoItem class InMemoryRepositorySuite extends CatsEffectSuite { - val repository = TodoRepositoryImpl.inMemory[IO]() + val repository = TodoRepository.inMemory[IO]() test("getAll should return empty when there are no items"): for {