Skip to content

A simple rest library for speeding up http4s development

License

Notifications You must be signed in to change notification settings

sapienapps/universal-rest

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

53 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

universal-rest

A Scala library for rapidly building type-safe CRUD REST APIs with http4s.

Scala CI

Features

  • Composable CRUD endpoints with minimal boilerplate
  • Support for both open and authenticated routes
  • Pagination and filtering via query parameters
  • Tagless final design with Cats Effect
  • Functional error handling with EitherT
  • Built-in JSON serialization via Circe
  • CORS support out of the box

Installation

Add to your build.sbt:

resolvers += "GitHub Package Registry (sapienapps)" at "https://maven.pkg.github.com/sapienapps/universal-rest"

libraryDependencies += "com.sapienapps" %% "universal-rest" % "0.9.6"

Quick Start

1. Define your repository

import cats.Applicative
import cats.data.EitherT
import com.sapienapps.http4s._

case class UserRepo[F[_]: Applicative]() extends CrudRepository[F, String, User, AppError, Session] {
  def create(entity: User)(implicit session: Session): EitherT[F, AppError, User] = ???
  def get(id: String)(implicit session: Session): EitherT[F, AppError, User] = ???
  def update(entity: User)(implicit session: Session): EitherT[F, AppError, User] = ???
  def delete(id: String)(implicit session: Session): EitherT[F, AppError, User] = ???
  def collection(isCount: Boolean)(implicit session: Session): EitherT[F, AppError, DataResult[User]] = ???

  // Optional: Override for pagination/filtering support
  override def collection(isCount: Boolean, params: QueryParams)(implicit session: Session) = {
    // Use params.limit, params.offset, params.filters
    ???
  }
}

2. Create an error handler

import com.sapienapps.http4s.ErrorHandler

case class MyErrorHandler[F[_]]() extends ErrorHandler[F, AppError] {
  def handle(e: AppError)(implicit m: Monad[F]): F[Response[F]] = e match {
    case NotFound(msg) => NotFound(msg)
    case ValidationError(msg) => BadRequest(msg)
    case _ => InternalServerError("Something went wrong")
  }
}

3. Wire up endpoints

Open (unauthenticated) endpoints:

import com.sapienapps.http4s.open.UniversalEndpoint

val endpoint = UniversalEndpoint[IO, String, User, AppError, String, Any, Session](
  toParams = _ => Right(Map.empty),
  toSession = _ => Session(),
  errorHandler = MyErrorHandler[IO](),
  toId = identity
)

// Using a service
val routes: HttpRoutes[IO] = endpoint.endpoints(UniversalService(UserRepo[IO]()))

// Or directly with a repository (convenience method)
val routes: HttpRoutes[IO] = endpoint.endpoints(UserRepo[IO]())

Authenticated endpoints:

import com.sapienapps.http4s.auth.AuthUniversalEndpoint
import org.http4s.server.AuthMiddleware

val authEndpoint = AuthUniversalEndpoint[IO, String, User, AppError, String, Any, UserContext](
  toParams = _ => Right(Map.empty),
  toSession = (_, ctx) => ctx,
  errorHandler = MyErrorHandler[IO](),
  toId = identity
)

// Using a service
val authRoutes: HttpRoutes[IO] = authEndpoint.endpoints(
  UniversalService(UserRepo[IO]()),
  authMiddleware
)

// Or directly with a repository
val authRoutes: HttpRoutes[IO] = authEndpoint.endpoints(UserRepo[IO](), authMiddleware)

Generated Endpoints

Each endpoint class generates the following routes:

Method Path Description Query Params
POST / Create entity -
GET /:id Get entity by ID -
GET / List entities limit, offset, custom filters
GET /count Get entity count -
PUT / Update entity -
DELETE /:id Delete entity by ID -

Pagination & Filtering

The list endpoint (GET /) automatically extracts query parameters:

GET /users?limit=10&offset=20&status=active&role=admin

These are passed to your repository as QueryParams:

case class QueryParams(
  limit: Option[Int] = None,
  offset: Option[Int] = None,
  filters: Map[String, String] = Map.empty
)

Architecture

CrudEndpoint (HTTP routing)
    ↓
CrudService (business logic) ← optional, can use repo directly
    ↓
CrudRepository (data access)

Tech Stack

  • Scala 2.13 & Scala 3.3 LTS (cross-compiled)
  • http4s 0.23.x (Ember)
  • Circe (JSON)
  • Cats Effect 3

License

MIT

About

A simple rest library for speeding up http4s development

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Languages