ConfigDocs
holds the descriptions and details of a ConfigDescriptor
which can be used to produce documentation.
ConfigDocs
holds the descriptions and details of a ConfigDescriptor
which can be used to produce documentation.
Every ConfigSource at the core is just a Reader
,
which is essentially a function that goes from PropertyTreePath
to an actual PropertyTree
.
Every ConfigSource at the core is just a Reader
,
which is essentially a function that goes from PropertyTreePath
to an actual PropertyTree
.
i.e, f: PropertyTreePath[String] => IO[ReadError[String], PropertyTree[String, String]
Later on for each key
represented as PropertyTreePath[String]
internally, f
is used to
applied to get the value as a PropertyTree
itself.
Internal details:
This function f
can be retrieved under an ZManaged effect. This implies it may involve an IO with managing resources
to even form this function. Example: In order to retrieve a property-tree corresponding to a key (PropertyTreePath),
it requires a database connection in the very first instance.
// pseudo-logic, doesn't compile
val source: ConfigSource = ConfigSource.Reader( ZManaged(getDatabaseConnection) .flatMap(connection => (key: PropertyTreePath[String] => IO.effect(connection.getStatement.executeQuery(s"get key from table"))) )
Note that ConfigSource
has a generalised memoize
function that allows you to memoize the effect required to form the
function. In the context of the above example, with source.memoize
we acquire only a single connection to retrieve
the values for all the keys in your product/coproduct for an instance of read
.
A Table is a recursive structure that is more easier to be interpreted as Json or Markdown than trying
to convert ConfigDocs
to a readable format.
A Table is a recursive structure that is more easier to be interpreted as Json or Markdown than trying
to convert ConfigDocs
to a readable format.
Convert a ConfigDescriptor to a Layer, which further requires a ConfigSource as input.
Convert a ConfigDescriptor to a Layer, which further requires a ConfigSource as input.
Note: Use configLayer_
instead of configLayer
if ConfigSource information is already embedded in the descriptor.
Example usage:
final case class MyConfig(age: Int) val appConfigLayer = ConfigSource.fromMap(Map("age" -> "20")).toLayer >>> configLayer(int("age").to[MyConfig]) val app: ZIO[MyConfig with zio.console.Console,java.io.IOException, Unit] = getConfig[MyConfig].flatMap(Console.printLine) app.provideSomeLayer[Console](appConfigLayer) // ZIO[zio.console.Console, Exception, Unit]
This can also be simplified to
val appConfigLayer = configLayer_(int("age").to[MyConfig] from ConfigSource.fromMap(Map("age" -> "20"))) app.provideSomeLayer[Console](appConfigLayer)
The preference depends on how you want to design the entry point to managing config of your app.
Convert a ConfigDescriptor to a Layer.
Convert a ConfigDescriptor to a Layer.
Example usage:
final case class MyConfig(age: Int, name: String) object MyConfig { val config = (int("age") zip string("name")).to[MyConfig] from ConfigSource.fromMap(Map("age" -> "20", "name" -> "afsal")) } val app: ZIO[Has[MyConfig] with zio.console.Console, java.io.IOException, Unit] = getConfig[MyConfig].flatMap(putStrLn) val io: ZIO[zio.console.Console, Exception, Unit] = app.provideSomeLayer[Console](configLayer_(MyConfig.config)) println(zio.Runtime.default.unsafeRun(io))
Generate documentation based on the ConfigDescriptor
, where a
ConfigDescriptor
is a structure representing the logic to fetch the application config
from various sources.
Generate documentation based on the ConfigDescriptor
, where a
ConfigDescriptor
is a structure representing the logic to fetch the application config
from various sources.
Once we generate the docs, this can be converted to a light weight Table
structure which is much more easier to be converted
to markdown or json formats.
Example :
val configDescriptor: ConfigDescriptor[MyAppConfig] = ???
generatedDocs(configDescriptor).toTable.toGithubFlavouredMarkdown
Generate a report based on the ConfigDescriptor
and an A
, where a
ConfigDescriptor
represents the logic to fetch the application config
from various sources, and A
represents the actual config value that was retrieved.
Generate a report based on the ConfigDescriptor
and an A
, where a
ConfigDescriptor
represents the logic to fetch the application config
from various sources, and A
represents the actual config value that was retrieved.
Example usage:
Example usage:
A helper method allowing you to forget passing configs as arguments to all over the place
in your app. Whereever, you need to access the config, simply
call getConfig[MyConfig].flatMap(config => ???)
.
PS: if you are familiar with Kleisli, this is similar
to using Kleisi[IO, Config, A]
, except for the fact that it is Has[Config]
instead of Config
allowing you to mixin with other dependencies keeping your Monad
the same
import zio.console._ final case class MyConfig(username: String, port: Int) val app: ZIO[Has[MyConfig] with Console, java.io.IOException, Unit] = for { config <- getConfig[MyConfig] _ <- putStrLn(config.toString) } yield () val configDesc = (string("USERNAME") zip int("PORT")).to[MyConfig] from ConfigSource.fromMap(Map()) val main: ZIO[zio.console.Console, Exception, Unit] = app.provideSomeLayer[Console](configLayer_(configDesc))