Packages

object DeriveConfigDescriptor extends DeriveConfigDescriptor

Linear Supertypes
Ordering
  1. Alphabetic
  2. By Inheritance
Inherited
  1. DeriveConfigDescriptor
  2. DeriveConfigDescriptor
  3. AnyRef
  4. Any
  1. Hide All
  2. Show All
Visibility
  1. Public
  2. Protected

Type Members

  1. case class Descriptor[T](desc: config.ConfigDescriptor[T], isObject: Boolean = false) extends Product with Serializable
    Definition Classes
    DeriveConfigDescriptor
  2. type Typeclass[T] = Descriptor[T]
    Definition Classes
    DeriveConfigDescriptor

Value Members

  1. final def !=(arg0: Any): Boolean
    Definition Classes
    AnyRef → Any
  2. final def ##: Int
    Definition Classes
    AnyRef → Any
  3. final def ==(arg0: Any): Boolean
    Definition Classes
    AnyRef → Any
  4. final def asInstanceOf[T0]: T0
    Definition Classes
    Any
  5. def clone(): AnyRef
    Attributes
    protected[lang]
    Definition Classes
    AnyRef
    Annotations
    @throws(classOf[java.lang.CloneNotSupportedException]) @native()
  6. final def combine[T](caseClass: CaseClass[Descriptor, T]): Descriptor[T]
    Definition Classes
    DeriveConfigDescriptor
  7. def descriptor[T](implicit config: Descriptor[T]): config.ConfigDescriptor[T]

    descriptor[A] allows the user to automatically derive ConfigDescriptor instead of using the ConfigDescriptor dsl explicitly (i.e, manual implementation).

    descriptor[A] allows the user to automatically derive ConfigDescriptor instead of using the ConfigDescriptor dsl explicitly (i.e, manual implementation). While manual implementation can be verbose, it is a recommended to use it when it comes to simple configurations.

    On the other hand, automatic derivation can become handly when the config is complex with relatively larger number of parameters, or when it is constantly changing during the software lifecycle, or it's just complex structure with nested products and coproducts.

    Below given is a small example to show the usage of descriptor[A].

    Example :

    final case class MyConfig(appName: String, port: Int, jdbcUrl: String)
    
    val configDesc: ConfigDescriptor[MyConfig]
    
    val config = read(configDesc from ConfigSource.fromMap(Map.empty))

    descriptor[MyConfig] works only if all the types that forms MyConfig has an instance of Descriptor. For almost all the important types, zio-config-magnolia already provides implicit instances for Descriptor.

    However, say you have a type ZonedDateTime, for which zio-config hasn't provided instance of Descriptor, then it will fail to compile.

    case class MyConfig(x: ZonedDateTime)

    In this case, define a Descriptor for ZonedDateTime using

    implicit def deriveForZonedDateTime: Descriptor[ZonedDateTime] =
     Descriptor[String].transformOrFail(string => Try(ZonedDateTime.parse(string).toEither.swap.map(_.getMessage).swap, r => Right(r.toString))
    
    descriptor[MyConfig] // then works

    descriptor[A] can also handle sealed traits, maps list etc.

    Example:

    sealed trait A
    
    object A {
      case class B(x: String, y: String) extends A
      case class C(z: String) extends A
      case object D extends A
    }
    
    val config = descriptor[A]
    
    val mapSource = ConfigSource.fromMap(Map("B.x" -> "l", "B.y" -> "m")
    val result = read(config from mapSource)
    // Right(B("x", "y"))
    
    val typesafeSource = TypesafeConfigSource.fromHoconString(
      s"""
        {
          B : {
             x : l
             y : m
          }
        }
    
      """
    
      val result = typesafeSource.flatMap(source => read(config from source))
    
      // Right(B("x", "y"))
    )

    While sealed trait can be fairly straight forward, there are historical errors users make with any advanced config libraries.

    Example: What happens if there is another B in the same package but for a different parent sealed trait name ?

    sealed trait X
    
    object X {
      case class B(x: String, y: String) extends X
      case class C(z: String) extends X
      case object D extends X
    }
    
    sealed trait Y
    
    object Y {
      case class B(x: String, y: String) extends Y
      case class Z(value: String) extends Y
    }
    
    final case class MyConfig(xOrY: Either[X, Y])
    
    val typesafeSource =
      TypesafeConfigSource.fromHoconString(
        s"""
         xOrY: {
           B : {
              x : l,
              y : m
           }
         }
       """
      )

    For zio-config, Either[X, Y] implies, it tries to fetch X and if it fails, it falls over to trying to read Y.

    However, in the above case, the output will be always X while user might have intended to provide Y.

    This was just an example, but similar conflicts can occur and zio-config-magnolia has strong semantics to handle such scenarios. The best way is to indicate the name of the sealed trait itself.

    That is

    Example:

     import zio.config._
    
     // This implies, not only we are making use of the names of the case classes (or case objects) but the actual
     // name of the sealed trait as well.
     val betterDerivation = new DeriveConfigDescriptor {
        override def sealedTraitStrategy: Descriptor.SealedTraitStrategy =
          wrapSubClassName && wrapSealedTraitName
    }

    If the source is HOCON, then

    betterDerivation.descriptor[MyConfig]

    can read:

    xOrY: {
      X : {
         B : {
            x : xyz
            y : xyz
         }
       }
    }

    Providing the name of the sealed traits is least commonly used. This is why the default derivation of sealed trait doesn't consider it.

    There is a third way of config derivation, especially for those who would like to migrate pure-config's implementation. In this case, we ignore the sealed-trait name, but we consider the sub-class name but not as a parent but part of the product itself.

     import zio.config._
     val customDerivation = new DeriveConfigDescriptor {
       override def sealedTraitStrategy: Descriptor.SealedTraitStrategy =
         labelSubClassName("type") && ignoreSealedTraitName
    }

    If the source is HOCON, then

    betterDerivation.descriptor[MyConfig]

    can read:

     x: {
       type : B
       x : r
       y : z
    }

    betterDerivation.descriptor[MyConfig] }}}

     x: {
       type : B
       x : r
       y : z
    }

    betterDerivation.descriptor[MyConfig] }}}

    xOrY: {
      X : {
         B : {
            x : xyz
            y : xyz
         }
       }
    }

    Providing the name of the sealed traits is least commonly used. This is why the default derivation of sealed trait doesn't consider it.

    There is a third way of config derivation, especially for those who would like to migrate pure-config's implementation. In this case, we ignore the sealed-trait name, but we consider the sub-class name but not as a parent but part of the product itself.

     import zio.config._
     val customDerivation = new DeriveConfigDescriptor {
       override def sealedTraitStrategy: Descriptor.SealedTraitStrategy =
         labelSubClassName("type") && ignoreSealedTraitName
    }

    If the source is HOCON, then

    betterDerivation.descriptor[MyConfig]

    can read:

     x: {
       type : B
       x : r
       y : z
    }

    betterDerivation.descriptor[MyConfig] }}}

     x: {
       type : B
       x : r
       y : z
    }
    Definition Classes
    DeriveConfigDescriptor
  8. final def dispatch[T](sealedTrait: SealedTrait[Descriptor, T]): Descriptor[T]
    Definition Classes
    DeriveConfigDescriptor
  9. def eitherDesc[A, B](left: config.ConfigDescriptor[A], right: config.ConfigDescriptor[B]): config.ConfigDescriptor[Either[A, B]]
    Attributes
    protected
    Definition Classes
    DeriveConfigDescriptor
  10. final def eq(arg0: AnyRef): Boolean
    Definition Classes
    AnyRef
  11. def equals(arg0: AnyRef): Boolean
    Definition Classes
    AnyRef → Any
  12. def finalize(): Unit
    Attributes
    protected[lang]
    Definition Classes
    AnyRef
    Annotations
    @throws(classOf[java.lang.Throwable])
  13. final def getClass(): Class[_ <: AnyRef]
    Definition Classes
    AnyRef → Any
    Annotations
    @native()
  14. implicit macro def getDescriptor[T]: Descriptor[T]
    Definition Classes
    DeriveConfigDescriptor
  15. def hashCode(): Int
    Definition Classes
    AnyRef → Any
    Annotations
    @native()
  16. implicit val implicitBigDecimalDesc: Descriptor[BigDecimal]
    Definition Classes
    DeriveConfigDescriptor
  17. implicit val implicitBigIntDesc: Descriptor[BigInt]
    Definition Classes
    DeriveConfigDescriptor
  18. implicit val implicitBooleanDesc: Descriptor[Boolean]
    Definition Classes
    DeriveConfigDescriptor
  19. implicit val implicitByteDesc: Descriptor[Byte]
    Definition Classes
    DeriveConfigDescriptor
  20. implicit val implicitDoubleDesc: Descriptor[Double]
    Definition Classes
    DeriveConfigDescriptor
  21. implicit val implicitDurationDesc: Descriptor[Duration]
    Definition Classes
    DeriveConfigDescriptor
  22. implicit def implicitEitherDesc[A, B](implicit arg0: Descriptor[A], arg1: Descriptor[B]): Descriptor[Either[A, B]]
    Definition Classes
    DeriveConfigDescriptor
  23. implicit val implicitFileDesc: Descriptor[File]
    Definition Classes
    DeriveConfigDescriptor
  24. implicit val implicitFloatDesc: Descriptor[Float]
    Definition Classes
    DeriveConfigDescriptor
  25. implicit val implicitInstantDesc: Descriptor[Instant]
    Definition Classes
    DeriveConfigDescriptor
  26. implicit val implicitIntDesc: Descriptor[Int]
    Definition Classes
    DeriveConfigDescriptor
  27. implicit val implicitJavaFilePathDesc: Descriptor[Path]
    Definition Classes
    DeriveConfigDescriptor
  28. implicit def implicitListDesc[A](implicit arg0: Descriptor[A]): Descriptor[List[A]]
    Definition Classes
    DeriveConfigDescriptor
  29. implicit val implicitLocalDateDesc: Descriptor[LocalDate]
    Definition Classes
    DeriveConfigDescriptor
  30. implicit val implicitLocalDateTimeDesc: Descriptor[LocalDateTime]
    Definition Classes
    DeriveConfigDescriptor
  31. implicit val implicitLocalTimeDesc: Descriptor[LocalTime]
    Definition Classes
    DeriveConfigDescriptor
  32. implicit val implicitLongDesc: Descriptor[Long]
    Definition Classes
    DeriveConfigDescriptor
  33. implicit def implicitMapDesc[K, A](implicit arg0: Descriptor[A]): Descriptor[Map[String, A]]
    Definition Classes
    DeriveConfigDescriptor
  34. implicit def implicitOptionDesc[A](implicit arg0: Descriptor[A]): Descriptor[Option[A]]
    Definition Classes
    DeriveConfigDescriptor
  35. implicit val implicitScalaDurationDesc: Descriptor[Duration]
    Definition Classes
    DeriveConfigDescriptor
  36. implicit def implicitSetDesc[A](implicit arg0: Descriptor[A]): Descriptor[Set[A]]
    Definition Classes
    DeriveConfigDescriptor
  37. implicit val implicitShortDesc: Descriptor[Short]
    Definition Classes
    DeriveConfigDescriptor
  38. implicit val implicitStringDesc: Descriptor[String]
    Definition Classes
    DeriveConfigDescriptor
  39. implicit val implicitUUIDDesc: Descriptor[UUID]
    Definition Classes
    DeriveConfigDescriptor
  40. implicit val implicitUriDesc: Descriptor[URI]
    Definition Classes
    DeriveConfigDescriptor
  41. implicit val implicitUrlDesc: Descriptor[URL]
    Definition Classes
    DeriveConfigDescriptor
  42. final def isInstanceOf[T0]: Boolean
    Definition Classes
    Any
  43. def listDesc[A](desc: config.ConfigDescriptor[A]): config.ConfigDescriptor[List[A]]
    Attributes
    protected
    Definition Classes
    DeriveConfigDescriptor
  44. def mapClassName(name: String): String

    Strategy on how to name the class names in the source config (if they are used in the config) By default, zio-config doesn't make assumptions that config keys or class names, especially when there is sealed traits or case objects

    Strategy on how to name the class names in the source config (if they are used in the config) By default, zio-config doesn't make assumptions that config keys or class names, especially when there is sealed traits or case objects

    Example:

    sealed trait Credentials
    
    object Credentials {
      final case class UsernamePassword(username: String, password: String) extends Credentials
      final case class Token(username: String, tokenId: String) extends Credentials.
    }
    
    final case class MyConfig(auth: Credentials)

    Given:

    import zio.config._
    
    val customDerivation = new DeriveConfigDescriptor {
        override def mapClassName(name: String): String = toKebabCase(name)
    }
    
    // Usage:
    customDerivation.descriptor[MyConfig]

    If the source is HOCON, then

    customDerivation.descriptor[MyConfig]

    can read:

    auth : {
      username-password : {
         username : xyz
         password : abc
    
      }
    }

    Alternative solution:

    sealed trait Credentials
    
    @name("username-password")
    case class UsernamePassword(username: String, password: String) extends Credentials
    
    @name("token")
    case class Token(username: String, tokenId: String) extends Credentials.

    With the above structure, if the source is HOCON, then

    descriptor[Credentials]

    can read:

    auth : {
      username-password : {
         username : xyz
         password : abc
      }
    }

    The latter solution is more specific to each sealed traits.

    descriptor[Credentials] }}}

    auth : {
      username-password : {
         username : xyz
         password : abc
      }
    }

    The latter solution is more specific to each sealed traits.

    customDerivation.descriptor[MyConfig] }}}

    auth : {
      username-password : {
         username : xyz
         password : abc
    
      }
    }

    Alternative solution:

    sealed trait Credentials
    
    @name("username-password")
    case class UsernamePassword(username: String, password: String) extends Credentials
    
    @name("token")
    case class Token(username: String, tokenId: String) extends Credentials.

    With the above structure, if the source is HOCON, then

    descriptor[Credentials]

    can read:

    auth : {
      username-password : {
         username : xyz
         password : abc
      }
    }

    The latter solution is more specific to each sealed traits.

    descriptor[Credentials] }}}

    auth : {
      username-password : {
         username : xyz
         password : abc
      }
    }

    The latter solution is more specific to each sealed traits.

    Definition Classes
    DeriveConfigDescriptor
  45. def mapDesc[A](desc: config.ConfigDescriptor[A]): config.ConfigDescriptor[Map[String, A]]
    Attributes
    protected
    Definition Classes
    DeriveConfigDescriptor
  46. def mapFieldName(name: String): String

    Strategy on how to name the field names in the actual config

    Strategy on how to name the field names in the actual config

    val customDerivation = new DeriveConfigDescriptor {
      override def mapFieldName(name: String): String = name.toUpperCase
    }
    
    // Usage:
    customDerivation.descriptor[MyConfig]

    Given,

    sealed trait Credentials
    
    object Credentials {
      final case class UsernamePassword(username: String, password: String) extends Credentials
      final case class Token(username: String, tokenId: String) extends Credentials.
    }
    
    final case class MyConfig(auth: Credentials)

    If the source is HOCON, then

    customDerivation.descriptor[MyConfig]

    can read:

    auth : {
      username_password : {
         USERNAME : xyz
         PASSWORD : abc
      }
    }

    customDerivation.descriptor[MyConfig] }}}

    auth : {
      username_password : {
         USERNAME : xyz
         PASSWORD : abc
      }
    }
    Definition Classes
    DeriveConfigDescriptor
  47. final def ne(arg0: AnyRef): Boolean
    Definition Classes
    AnyRef
  48. final def notify(): Unit
    Definition Classes
    AnyRef
    Annotations
    @native()
  49. final def notifyAll(): Unit
    Definition Classes
    AnyRef
    Annotations
    @native()
  50. def optionDesc[A](configDesc: config.ConfigDescriptor[A]): config.ConfigDescriptor[Option[A]]
    Attributes
    protected
    Definition Classes
    DeriveConfigDescriptor
  51. final def prepareClassName(annotations: Seq[Any], name: String): String
    Definition Classes
    DeriveConfigDescriptor
  52. final def prepareFieldName(annotations: Seq[Any], name: String): String
    Definition Classes
    DeriveConfigDescriptor
  53. def sealedTraitStrategy: SealedTraitStrategy
    Definition Classes
    DeriveConfigDescriptor
  54. def setDesc[A](desc: config.ConfigDescriptor[A]): config.ConfigDescriptor[Set[A]]
    Attributes
    protected
    Definition Classes
    DeriveConfigDescriptor
  55. final def synchronized[T0](arg0: => T0): T0
    Definition Classes
    AnyRef
  56. def toString(): String
    Definition Classes
    AnyRef → Any
  57. final def wait(): Unit
    Definition Classes
    AnyRef
    Annotations
    @throws(classOf[java.lang.InterruptedException])
  58. final def wait(arg0: Long, arg1: Int): Unit
    Definition Classes
    AnyRef
    Annotations
    @throws(classOf[java.lang.InterruptedException])
  59. final def wait(arg0: Long): Unit
    Definition Classes
    AnyRef
    Annotations
    @throws(classOf[java.lang.InterruptedException]) @native()
  60. final def wrapSealedTrait[T](label: String, desc: config.ConfigDescriptor[T]): config.ConfigDescriptor[T]
    Definition Classes
    DeriveConfigDescriptor
  61. object Descriptor extends Serializable
    Definition Classes
    DeriveConfigDescriptor

Inherited from DeriveConfigDescriptor

Inherited from AnyRef

Inherited from Any

Ungrouped