All Downloads are FREE. Search and download functionalities are using the official Maven repository.

zio.config.refined.package.scala Maven / Gradle / Ivy

package zio.config

import com.github.ghik.silencer.silent
import eu.timepit.refined.api.{RefType, Refined, Validate}
import zio.Config
import zio.config.magnolia.DeriveConfig

package object refined {

  /**
   * FIXME Automatically derive instances of Descriptor for any refined types
   */
  @silent("deprecated")
  implicit def deriveRefinedDescriptor[A, P](implicit
    desc: DeriveConfig[A],
    validate: Validate[A, P]
  ): DeriveConfig[Refined[A, P]] =
    DeriveConfig(refine[P](desc.desc))

  /**
   * `refine` allows us to retrieve a `refined` type from a given path.
   *
   * Example:
   *
   * {{{
   *   import eu.timepit.refined.string._
   *
   *   val configDescriptor: Config[Refined[String, Uuid]] =
   *     refined[String, Uuid]("ID")
   * }}}
   */
  @silent("deprecated")
  def refine[A, P](path: String)(implicit
    desc: DeriveConfig[A],
    validate: Validate[A, P]
  ): Config[Refined[A, P]] =
    desc.desc
      .nested(path)
      .mapOrFail[Refined[A, P]](v =>
        RefType.applyRef[Refined[A, P]](v).swap.map(str => Config.Error.InvalidData(message = str)).swap
      )

  /**
   * refine[Predicate] allows to retrieve a `refined` type given an existing `Config` and a predicate Predicate. Example
   * of a Predicate is `NonEmpty`.
   *
   * Example:
   *
   * {{{
   *
   *   final case class MyConfig(url: String, port: Int)
   *
   *   val configs: Config[List[MyConfig]] =
   *     listOf("databases", deriveConfig[MyConfig])
   *
   *   val configDescriptor: Config[Refined[List[MyConfig], Size[Greater[W.`2`.T]]]] =
   *     refine[Size[Greater[W.`2`.T]]](configs)
   * }}}
   *
   * If you don't care predicates specifically, and need to pass a fully formed Refined type (Example: type
   * NonEmptyString = String Refined NonEmpty), refer `refineType[RefinedType]`
   */
  def refine[Predicate]: PartialRefined[Predicate] =
    new PartialRefined[Predicate]

  /**
   * refineType[RefinedType] allows to retrieve a RefinedType (example: NonEmptyString) from a path.
   *
   * Unlike `refine[Predicate]` method, `refineType[RefinedType]` allows you to a pass a fully formed refined type and
   * be careless about the `Config` of the underlying type.
   *
   * Example:
   *
   * {{{
   *
   *   type NonEmptyString = String Refined NonEmpty
   *   refineType[NonEmptyString]("USERNAME")
   *
   *   // is same as
   *
   *   val userName: Config[String] = string("USERNAME")
   *   refine[NonEmpty](userName)
   *
   * }}}
   *
   * While, `refineType[RefinedType]` is useful for simple application, `refine[Predicate]` can be more flexible in
   * complex configurations where you need more orthogonality between raw config and refined configs.
   *
   * `refine[Predicate]` allows you to build entire Config without worrying about `Refined` modules, allowing you to
   * then pass the `Config[RawConfig]` to `refine[Predicate]` and refine the types, which is more into an orthogonal
   * design.
   *
   * A complete example of refineType:
   *
   * {{{
   *
   *   import zio.config._
   *   import eu.timepit.refined.types.string.NonEmptyString
   *
   *   final case class Jdbc(username: NonEmptyString, password: NonEmptyString)
   *
   *   val jdbc: Config[Jdbc] =
   *     (refineType[NonEmptyString]("username") zip refineType[NonEmptyString]("password")).to[Jdbc]
   * }}}
   */
  def refineType[R]: PartialRefinedPath[R] =
    PartialRefinedPath[R]()
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy