Scala library for nice business logic oriented, for-comprehension-style error handling. Write logic that even your manager can understand!
Or in more technical terms, think of EitherT on steroids, with more human-readable method names.
Add the following to your build.sbt
:
libraryDependencies += "pl.iterators" %% "sealed-monad" % "2.0.0"
Available for Scala 2.13.x and 3.x in JVM, ScalaNative and Scala.js flavours.
def createTodo(userId: UUID, organizationId: UUID, request: CreateTodoRequest): IO[CreateTodoResponse] = {
(for {
user <- userRepository
.find(userId) // IO[Option[User]]
.valueOr(CreateTodoResponse.UserNotFound) // extracts User or returns UserNotFound
_ <- organizationRepository
.findFor(userId) // IO[Option[Organization]]
.valueOr(CreateTodoResponse.UserNotInOrganization) // extracts Organization or returns UserNotInOrganization
.ensure(_.canCreateTodos(user), CreateTodoResponse.UserNotAllowedToCreateTodos) // checks if user can create todos or returns UserNotAllowedToCreateTodos
_ <- todoRepository
.find(request.title) // IO[Option[Todo]]
.ensure(_.isEmpty, CreateTodoResponse.TodoAlreadyExists) // checks if todo already exists or returns TodoAlreadyExists
_ <- Todo
.from(request)
.pure[IO] // IO[Todo]
.ensure(_.title.nonEmpty, CreateTodoResponse.TodoTitleEmpty) // checks if todo title is non-empty or returns TodoTitleEmpty
todo <- todoRepository.insert(Todo(UUID.randomUUID(), request.title)).seal // todo created!
} yield CreateTodoResponse.Created(todo)).run // compile to IO[CreateTodoResponse]
}
Please refer to the docs site.
This project is licensed under the Apache 2.0 License - see the LICENSE file for details.