Kebs

repository·master·Indexed 41 days ago

https://github.com/theiterators/kebs

A Scala library for Scala 2.13 and Scala 3 that automates the derivation of typeclass instances for domain types to reduce boilerplate. It provides specialized modules for JSON codecs (Circe, Play JSON, Spray JSON), database mappings (Slick, Doobie), HTTP unmarshallers (Pekko HTTP, Akka HTTP, http4s), and other tools like PureConfig and ScalaCheck.

Tokens
22.9K
Snippets
90
Records
106
Agent score
100%

What's inside Kebs

  1. What is Kebs?

    master

    Kebs is a Scala library (supporting Scala 2.13 and Scala 3) designed to eliminate boilerplate by automatically deriving typeclass instances for domain types. It handles tasks such as JSON codecs, database column mappings, and HTTP unmarshallers at compile time. Instead of manually writing implicit instances for every type and library combination, you simply mix in specific traits to your domain models.

    case class UserId(value: String) extends AnyVal
    case class Email(value: String) extends AnyVal
    
    // With Kebs — just mix in a trait. Everything is derived at compile time.
  2. Use numeric mixins to override default String encodings

    master

    By default, many types use a String representation. You can override this behavior by mixing in specific numeric encoding traits into your protocol object. This is useful for performance or compatibility with systems expecting numeric timestamps or durations.

    Available Mixins

    Duration Mixins:

    • pl.iterators.kebs.instances.time.mixins.DurationNanosLong: Duration as nanoseconds
    • pl.iterators.kebs.instances.time.mixins.DurationMillisLong: Duration as milliseconds
    • pl.iterators.kebs.instances.time.mixins.DurationSecondsLong: Duration as seconds
    • pl.iterators.kebs.instances.time.mixins.DurationMinutesLong: Duration as minutes

    Instant Mixins:

    • pl.iterators.kebs.instances.time.mixins.InstantEpochMilliLong: Instant as epoch millis
    • pl.iterators.kebs.instances.time.mixins.InstantEpochSecondLong: Instant as epoch seconds

    Period Mixins:

    • pl.iterators.kebs.instances.time.mixins.PeriodDays: Period as days (Int)
    • pl.iterators.kebs.instances.time.mixins.PeriodMonthsInt: Period as months (Int)
    • pl.iterators.kebs.instances.time.mixins.PeriodYearsInt: Period as years (Int)

    Example Usage

    To configure a protocol where Instant is epoch millis and Duration is nanoseconds, while all other java.time types remain ISO Strings:

    import pl.iterators.kebs.instances.TimeInstances
    import pl.iterators.kebs.instances.time.mixins.{InstantEpochMilliLong, DurationNanosLong}
    
    object MyProtocol extends KebsCirce with TimeInstances with InstantEpochMilliLong with DurationNanosLong
    import pl.iterators.kebs.instances.TimeInstances
    import pl.iterators.kebs.instances.time.mixins.{InstantEpochMilliLong, DurationNanosLong}
    
    // Instant as epoch millis, Duration as nanos, everything else as ISO String
    object MyProtocol extends KebsCirce with TimeInstances with InstantEpochMilliLong with DurationNanosLong
  3. Use column extension methods on wrapped types

    master

    When using KebsSlickSupport, wrapped columns (Rep[CC]) automatically inherit the extension methods of their underlying base type. For example:

    • Rep[CC] wrapping a String provides StringColumnExtensionMethods (e.g., .toLowerCase, .like).
    • Rep[CC] wrapping a numeric type provides arithmetic and comparison methods.
    • Rep[CC] wrapping a Boolean provides logical operators like && and ||.

    You can also compare a Rep[CC] directly against its unwrapped base type without explicit conversion.

  4. How Kebs typeclasses compose for integration

    master

    Kebs uses a composition pattern to provide encoders and decoders for domain types. Integration modules (like circe or slick) define implicit rules that combine the core typeclasses.

    Common composition patterns include:

    • ValueClassLike[VC, F1] + Encoder[F1] → Encoder[VC]
    • EnumLike[T] → Encoder[T] (via name)
    • ValueEnumLike[V, E] → Encoder[E] (via value)
    • InstanceConverter[Obj, Val] + Encoder[Val] → Encoder[Obj]

    This allows you to define your domain types using the core abstractions, and Kebs automatically provides the necessary glue for serialization and database interaction.

  5. Setup kebs-tagged (Scala 2)

    master

    To use tagged types in Scala 2, add the following dependencies to your build configuration. If you intend to use the @tagged code generation feature, you must also include kebs-tagged-meta.

    libraryDependencies += "pl.iterators" %% "kebs-tagged" % kebsVersion
    libraryDependencies += "pl.iterators" %% "kebs-tagged-meta" % kebsVersion // for @tagged code generation (Scala 2 only)
  6. Derive standard library typeclasses for wrappers

    master

    By importing pl.iterators.kebs.core.support._, you can automatically derive standard Scala typeclasses for your wrapper types. This enables mathematical and comparison operations directly on the wrapper types.

    Supported derivations include:

    • Numeric[A] (enables .sum, .min, .max, arithmetic)
    • Integral[A] (integer division for Int/Long-backed wrappers)
    • Fractional[A] (real division for BigDecimal/Double-backed wrappers)
    • Ordering[A] (sorting and comparison)
    • PartialOrdering[A]
    • Equiv[A]
    import pl.iterators.kebs.core.support._
    
    case class Price(amount: BigDecimal) extends AnyVal
    // with kebs support._ in scope:
    List(Price(3), Price(1), Price(2)).sorted  // works
    List(Price(10), Price(20)).sum             // works
  7. Use kebs-baklava for schema and parameter support

    master

    The kebs-baklava module provides support for value classes, instance converter types, enums, and value enums within Kebs.

    • For standard enums, use KebsBaklavaEnumsParams and KebsBaklavaEnumsSchema.
    • For value enums, use KebsBaklavaValueEnumsParams and KebsBaklavaValueEnumsSchema.

    Additionally, types implementing an InstanceConverter receive format-aware schema derivation for specific JSON Schema formats such as "date", "date-time", "uri", and "uuid".

    import pl.iterators.kebs.baklava.params.KebsBaklavaParams
    import pl.iterators.kebs.baklava.schema.KebsBaklavaSchema
    import pl.iterators.kebs.baklava.params.enums.KebsBaklavaEnumsParams
    import pl.iterators.kebs.baklava.schema.enums.KebsBaklavaEnumsSchema
  8. Migrate to Kebs 2.0

    master

    If you are upgrading from a previous version to Kebs 2.0, apply the following changes:

    • Value Classes: Mix in CaseClass1ToValueClass if you use value classes.
    • Value Enums: Extend value-enums with ValueEnumLikeEntry[V].
    • Enumeratum: Use KebsEnumeratum / KebsValueEnumeratum for Enumeratum.
    • Native Enums: Use KebsEnum / KebsValueEnum for native enums.
  9. Install kebs-akka-http or kebs-pekko-http

    master

    Depending on whether you are using Akka HTTP (Scala 2 only) or Pekko HTTP (Scala 2 & 3), add the corresponding dependency to your libraryDependencies using kebsVersion.

    // Akka HTTP (Scala 2 only)
    libraryDependencies += "pl.iterators" %% "kebs-akka-http" % kebsVersion
    
    // Pekko HTTP (Scala 2 & 3)
    libraryDependencies += "pl.iterators" %% "kebs-pekko-http" % kebsVersion