Automatic Validations
By bringing in zio-config-refined
module, you get validations for your config parameters almost for free.
zio-config
elegantly integrates with Refined
library for you to achieve this with same ergonomics.
If you are not familiar with refined
library, refer https://github.com/fthomas/refined.
There are various ways that zio-config can interact with refined library.
Take a look at zio.config.refined
package.
import zio.Config
import zio.ConfigProvider
import zio.config._, refined._
A few examples are given below.
Basic Example
import eu.timepit.refined.types.string.NonEmptyString
case class Jdbc(username: NonEmptyString, password: NonEmptyString)
val jdbc: Config[Jdbc] =
(refineType[NonEmptyString]("username") zip
refineType[NonEmptyString]("password")).to[Jdbc]
ConfigProvider.fromMap(Map("username" -> "", "password" -> "")).load(jdbc)
Direct Interaction with Refined Predicates
If you need to directly interact with Predicate
s (ex: NonEmpty
), then
refine[A, P]
method is useful.
import eu.timepit.refined._, api._, string._, collection._
type NonEmptyString = String Refined NonEmpty
val refinedConfig: Config[NonEmptyString] =
refineType[NonEmptyString]("USERNAME")
// Another way of doing it is
val urlConfig: Config[Refined[String, Url]] =
refine[String, Url]("URL")
// refineType takes a fully formed type (String Refined NonEmpty) where as refine allows you to play with the predicate directly (NonEmpty)
Derive from existing Config
Of various methods available in zio.config.refined
package,
the most interesting one is being able to get a refined type out of an already derived Config.
This shows the composable nature of zio-config.
Take a look at the below example
import eu.timepit.refined._, api._, numeric._, collection._
import zio.config.magnolia.deriveConfig
case class MyConfig(url: String, port: Int)
val configs: Config[List[MyConfig]] =
Config.listOf("databases", deriveConfig[MyConfig])
// A list of database configs, such that size should be greater than 2.
val databaseList: Config[Refined[List[MyConfig], Size[Greater[W.`2`.T]]]] =
refine[Size[Greater[W.`2`.T]]](configs)
Auto-Derivation and Refined
You can also use auto derivations with refined.
import zio.ConfigProvider
import eu.timepit.refined.W
import eu.timepit.refined.api.Refined
import eu.timepit.refined.collection.{ NonEmpty, Size }
import zio.config.magnolia.deriveConfig
object RefinedReadConfig extends App {
case class RefinedProd(
ldap: Refined[String, NonEmpty],
port: Refined[Int, GreaterEqual[W.`1024`.T]],
dbUrl: Option[Refined[String, NonEmpty]]
)
val configMap =
Map(
"LDAP" -> "ldap",
"PORT" -> "1999",
"DBURL" -> "ddd"
)
val result =
ConfigProvider.fromMap(configMap).load(deriveConfig[RefinedProd].mapKey(_.toUpperCase))
// RefinedProd(ldap,1999,Some(ddd))
}