All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
zio.config.yaml.YamlConfigSource.scala Maven / Gradle / Ivy
package zio.config.yaml
import com.github.ghik.silencer.silent
import org.snakeyaml.engine.v2.api.{Load, LoadSettings}
import zio.ZIO
import zio.config._
import java.io.{File, FileInputStream, Reader}
import java.lang.{Boolean => JBoolean, Double => JDouble, Float => JFloat, Integer => JInteger, Long => JLong}
import java.nio.file.Path
import java.{util => ju}
import scala.jdk.CollectionConverters._
@silent("Unused import")
object YamlConfigSource {
import scala.collection.compat._
import VersionSpecificSupport._
/**
* Retrieve a `ConfigSource` from yaml path.
*
* A complete example usage:
*
* {{{
*
* case class MyConfig(port: Int, url: String)
*
* val result: Either[ReadError[String], MyConfig] =
* YamlConfigSource.fromYamlFile(new File("/path/to/file.yaml"))
* .flatMap(source => read(descriptor[MyConfig] from source)))
* }}}
*/
def fromYamlFile(file: File): ConfigSource =
fromYamlRepr(file)(loadYaml(_), file.getAbsolutePath)
/**
* Retrieve a `ConfigSource` from yaml path.
*
* A complete example usage:
*
* {{{
*
* case class MyConfig(port: Int, url: String)
*
* val result: Either[ReadError[String], MyConfig] =
* YamlConfigSource.fromYamlPath(Path.of("/path/to/file.yaml"))
* .flatMap(source => read(descriptor[MyConfig] from source)))
* }}}
*/
def fromYamlPath(path: Path): ConfigSource =
fromYamlFile(path.toFile)
/**
* Retrieve a `ConfigSource` from yaml reader.
*
* A complete example usage:
*
* {{{
*
* import zio.*
* import scala.io.Source
* import java.io.InputStreamReader
* import zio.config.yaml.YamlConfigSource
*
* case class MyConfig(port: Int, url: String)
*
* def acquire(yamlResourcePath: String) = ZIO.effect(Source.fromResource(yamlResourcePath).reader)
* def release(reader: InputStreamReader) = ZIO.effectTotal(reader.close())
*
* val myConfig: InputStreamReader => IO[ReadError[String], MyConfig] = reader =>
* IO.fromEither(
* for {
* source <- YamlConfigSource.fromYamlReader(reader)
* myConfig <- read(descriptor[MyConfig] from source)
* } yield myConfig
* )
*
* val result: Task[MyConfig] = ZManaged.make(acquire("relative/path/to/your/application/resource.yml"))(release).use(myConfig)
* }}}
*/
def fromYamlReader(
reader: Reader,
sourceName: String = "yaml"
): ConfigSource =
fromYamlRepr(reader)(loadYaml(_), sourceName)
/**
* Retrieve a `ConfigSource` from yaml path.
*
* A complete example usage:
*
* {{{
*
* val yamlString = ???
*
* case class MyConfig(port: Int, url: String)
*
* val result: Either[ReadError[String], MyConfig] =
* YamlConfigSource.fromYamlString(yamlString))
* .flatMap(source => read(descriptor[MyConfig] from source)))
* }}}
*/
def fromYamlString(
yamlString: String,
sourceName: String = "yaml"
): ConfigSource =
fromYamlRepr(yamlString)(loadYaml(_), sourceName)
private[config] def fromYamlRepr[A](repr: A)(
loadYaml: A => ZIO[Any, ReadError[String], AnyRef],
sourceName: String = "yaml"
): ConfigSource = {
val managedTree =
loadYaml(repr).flatMap(anyRef => convertYaml(anyRef))
ConfigSource
.fromManaged(
sourceName,
managedTree.map(tree => (path: PropertyTreePath[String]) => ZIO.succeed(tree.at(path)))
)
.memoize
}
private[yaml] def convertYaml(data: AnyRef): ZIO[Any, ReadError[String], PropertyTree[String, String]] = {
def strictLeaf[A](leaf: A) = PropertyTree.Leaf(leaf, canBeSequence = false)
data match {
case null => ZIO.succeed(PropertyTree.empty)
case t: JInteger => ZIO.succeed(strictLeaf(t.toString))
case t: JLong => ZIO.succeed(strictLeaf(t.toString))
case t: JFloat => ZIO.succeed(strictLeaf(t.toString))
case t: JDouble => ZIO.succeed(strictLeaf(t.toString))
case t: String => ZIO.succeed(strictLeaf(t))
case t: JBoolean => ZIO.succeed(strictLeaf(t.toString))
case t: ju.List[_] =>
ZIO
.foreach(
t.asInstanceOf[ju.List[AnyRef]].asScala.toList
)(each => convertYaml(each))
.map(PropertyTree.Sequence(_))
case t: ju.Map[_, _] =>
ZIO
.foreach(
t.asInstanceOf[ju.Map[String, AnyRef]].asScala.toList
)(each => convertYaml(each._2).map(r => (each._1, r)))
.map(res => PropertyTree.Record(res.toMap))
case _ => ZIO.fail(ReadError.SourceError("unexpected data type in convertYaml"))
}
}
private def loadYaml(yamlFile: File): ZIO[Any, ReadError[String], AnyRef] =
snakeYamlLoader().flatMap(r =>
ZIO
.attempt(r.loadFromInputStream(new FileInputStream(yamlFile)))
.mapError(throwable => ReadError.SourceError(throwable.toString))
)
private def loadYaml(yamlReader: Reader): ZIO[Any, ReadError[String], AnyRef] =
snakeYamlLoader().flatMap(r =>
ZIO
.attempt(r.loadFromReader(yamlReader))
.mapError(throwable => ReadError.SourceError(throwable.toString))
)
private def loadYaml(yamlString: String): ZIO[Any, ReadError[String], AnyRef] =
snakeYamlLoader().flatMap(r =>
ZIO
.attempt(r.loadFromString(yamlString))
.mapError(throwable => ReadError.SourceError(throwable.toString))
)
private def snakeYamlLoader(): ZIO[Any, ReadError[String], Load] =
ZIO
.attempt(
new Load(
LoadSettings.builder().setEnvConfig(ju.Optional.of(EnvConfigImpl)).build()
): Load
)
.mapError(throwable =>
ReadError.SourceError(s"Failed to load snake yaml environment config ${throwable.toString}")
)
}