Zero boilerplate
Stop writing MappedColumnType.base, deriveEncoder, and Unmarshaller.strict for every wrapper type. Kebs derives all of that at compile time from a single typeclass.
Use strong types everywhere
Value classes, opaque types, tagged types, and enums just work with Slick, Doobie, Circe, Spray JSON, Play JSON, Akka HTTP, Pekko HTTP, http4s, ScalaCheck, PureConfig, and more.
Scala 2 & 3
Full cross-build support for Scala 2.13 and Scala 3, including JVM, Scala.js, and Scala Native where applicable.
Without Kebs
case class UserId(value: String) extends AnyVal
case class Email(value: String) extends AnyVal
// Slick
implicit val userIdCol: BaseColumnType[UserId] =
MappedColumnType.base(_.value, UserId.apply)
implicit val emailCol: BaseColumnType[Email] =
MappedColumnType.base(_.value, Email.apply)
// Circe
implicit val userIdEnc: Encoder[UserId] =
Encoder[String].contramap(_.value)
implicit val userIdDec: Decoder[UserId] =
Decoder[String].map(UserId.apply)
// ... repeat for every type × every library
With Kebs
case class UserId(value: String) extends AnyVal
case class Email(value: String) extends AnyVal
// That's it. Slick, Circe, Akka HTTP, Doobie,
// http4s, Play JSON, etc. all just work.
Quick start
// build.sbt — pick the modules you need
libraryDependencies ++= Seq(
"pl.iterators" %% "kebs-circe" % kebsVersion,
"pl.iterators" %% "kebs-slick" % kebsVersion,
"pl.iterators" %% "kebs-pekko-http" % kebsVersion,
"pl.iterators" %% "kebs-instances" % kebsVersion
)