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))
}