All Projects → kxbmap → Configs

kxbmap / Configs

Licence: apache-2.0
Scala wrapper for Typesafe config

Programming Languages

scala
5932 projects

Projects that are alternatives of or similar to Configs

Fig
A minimalist Go configuration library
Stars: ✭ 142 (-13.41%)
Mutual labels:  configuration
Condenserdotnet
API Condenser / Reverse Proxy using Kestrel and Consul, Including light weight consul lib
Stars: ✭ 147 (-10.37%)
Mutual labels:  configuration
Dotter
A dotfile manager and templater written in rust 🦀
Stars: ✭ 154 (-6.1%)
Mutual labels:  configuration
Omniconf
Configuration library for Clojure that favors explicitness
Stars: ✭ 142 (-13.41%)
Mutual labels:  configuration
Gcfg
read INI-style configuration files into Go structs; supports user-defined types and subsections
Stars: ✭ 146 (-10.98%)
Mutual labels:  configuration
Homematic Manager
Homematic Device Configuration and Administration
Stars: ✭ 149 (-9.15%)
Mutual labels:  configuration
Config
Manage Laravel configuration by persistent storage
Stars: ✭ 139 (-15.24%)
Mutual labels:  configuration
Config
Configuration module for Nest framework (node.js) 🍓
Stars: ✭ 161 (-1.83%)
Mutual labels:  configuration
I3 Rice Rin Shelter
My i3wm rice with theme "Rin : shelter"
Stars: ✭ 146 (-10.98%)
Mutual labels:  configuration
Toml
A PHP parser for TOML
Stars: ✭ 152 (-7.32%)
Mutual labels:  configuration
Config
Easiest way to add multi-environment yaml settings to Rails, Sinatra, Pandrino and other Ruby projects.
Stars: ✭ 1,821 (+1010.37%)
Mutual labels:  configuration
Phpdotenv
Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.
Stars: ✭ 11,648 (+7002.44%)
Mutual labels:  configuration
Env
Simple lib to parse environment variables to structs
Stars: ✭ 2,164 (+1219.51%)
Mutual labels:  configuration
Local Repl
🐚 Project-specific configuration for the Node.js REPL
Stars: ✭ 143 (-12.8%)
Mutual labels:  configuration
Libelektra
Elektra serves as a universal and secure framework to access configuration parameters in a global, hierarchical key database.
Stars: ✭ 155 (-5.49%)
Mutual labels:  configuration
Autofac.annotation
Autofac extras library for component registration via attributes 用注解来load autofac 摆脱代码或者xml配置和java的spring的注解注入一样的体验
Stars: ✭ 140 (-14.63%)
Mutual labels:  configuration
Configurate
A simple configuration library for Java applications providing a node structure, a variety of formats, and tools for transformation
Stars: ✭ 148 (-9.76%)
Mutual labels:  configuration
Color Scheme
color-scheme,颜色方案,color主题,scheme,webstrom,phpstrom,pytharm,配色方案,编辑器,xfce4主题,护眼,暗色,dark
Stars: ✭ 162 (-1.22%)
Mutual labels:  configuration
Magento2 Configurator
Magento 2 Configurator
Stars: ✭ 158 (-3.66%)
Mutual labels:  configuration
Qconf
Qihoo Distributed Configuration Management System
Stars: ✭ 1,843 (+1023.78%)
Mutual labels:  configuration

configs

Build Status Maven Central Scaladoc

configs is Scala wrapper for Typesafe config.

Usage

Add the following line to your build file:

libraryDependencies += "com.github.kxbmap" %% "configs" % "0.5.0"

Quick Start

import com.typesafe.config.ConfigFactory
import configs.ConfigReader

Result type of get a value from config is configs.Result. If get successfully, returns configs.Result.Success, if not configs.Result.Failure:

val config = ConfigFactory.parseString("foo = 42")
val foo = ConfigReader[Int].read(config, "foo")
// foo: configs.Result[Int] = Success(value = 42)

foo.valueOrElse(0)
// res0: Int = 42

val missing = ConfigReader[Int].read(config, "missing")
// missing: configs.Result[Int] = Failure(
//   error = ConfigError(
//     head = Exceptional(
//       throwable = com.typesafe.config.ConfigException$Missing: String: 1: No configuration setting found for key 'missing',
//       paths = List("missing")
//     ),
//     tail = Vector()
//   )
// )

missing.valueOrElse(0)
// res1: Int = 0

Import configs.syntax._ provides extension methods for Config:

import configs.syntax._
config.get[Int]("foo")
// res2: configs.Result[Int] = Success(value = 42)

get[Option[A]] will return success with value None if path is not exists:

config.get[Option[Int]]("missing")
// res3: configs.Result[Option[Int]] = Success(value = None)

config.getOrElse("missing", 0) // Alias for config.get[Option[Int]]("missing").map(_.getOrElse(0))
// res4: configs.Result[Int] = Success(value = 0)

You can get a case class value out of the box:

import scala.concurrent.duration.FiniteDuration

case class MyConfig(foo: String, bar: Int, baz: List[FiniteDuration])
val config = ConfigFactory.parseString("""
  my-config {
    foo = My config value
    bar = 123456
    baz = [1h, 2m, 3s]
  }
  """)
config.get[MyConfig]("my-config")
// res5: configs.Result[MyConfig] = Success(
//   value = MyConfig(
//     foo = "My config value",
//     bar = 123456,
//     baz = List(1 hour, 2 minutes, 3 seconds)
//   )
// )

If failed, Result accumulates error messages:

val config = ConfigFactory.parseString("""
  my-config {
    bar = 2147483648
    baz = [aaa, bbb, ccc]
  }
  """)
val result = config.get[MyConfig]("my-config")
// result: configs.Result[MyConfig] = Failure(
//   error = ConfigError(
//     head = Exceptional(
//       throwable = com.typesafe.config.ConfigException$Missing: String: 2: No configuration setting found for key 'foo',
//       paths = List("my-config", "foo")
//     ),
//     tail = Vector(
//       Exceptional(
//         throwable = com.typesafe.config.ConfigException$WrongType: String: 2: bar has type out-of-range value 2147483648 rather than int (32-bit integer),
//         paths = List("my-config", "bar")
//       ),
//       Exceptional(
//         throwable = com.typesafe.config.ConfigException$BadValue: String: 4: Invalid value at '0': No number in duration value 'aaa',
//         paths = List("my-config", "baz", "0")
//       ),
//       Exceptional(
//         throwable = com.typesafe.config.ConfigException$BadValue: String: 4: Invalid value at '1': No number in duration value 'bbb',
//         paths = List("my-config", "baz", "1")
//       ),
//       Exceptional(
//         throwable = com.typesafe.config.ConfigException$BadValue: String: 4: Invalid value at '2': No number in duration value 'ccc',
//         paths = List("my-config", "baz", "2")
//       )
//     )
//   )
// )

result.failed.foreach { error =>
  error.messages.foreach(println)
}
// [my-config.foo] String: 2: No configuration setting found for key 'foo'
// [my-config.bar] String: 2: bar has type out-of-range value 2147483648 rather than int (32-bit integer)
// [my-config.baz.0] String: 4: Invalid value at '0': No number in duration value 'aaa'
// [my-config.baz.1] String: 4: Invalid value at '1': No number in duration value 'bbb'
// [my-config.baz.2] String: 4: Invalid value at '2': No number in duration value 'ccc'

You can get a value without key using extract:

val config = ConfigFactory.parseString("""
  foo = My config value
  bar = 123456
  baz = [1h, 2m, 3s]
  """)
config.extract[MyConfig]
// res7: configs.Result[MyConfig] = Success(
//   value = MyConfig(
//     foo = "My config value",
//     bar = 123456,
//     baz = List(1 hour, 2 minutes, 3 seconds)
//   )
// )

You may use the ~ operator to combine multiple results and apply a function with the results passed as arguments, this is useful when you want to construct a complex case class from several config extractors.

case class ServiceConfig(name: String, port: Int, hosts: List[String])

val config = ConfigFactory.parseString(
  """
    |name = "foo"
    |port = 9876
    |hosts = ["localhost", "foo.com"]
  """.stripMargin)
(
  config.get[String]("name") ~
  config.get[Int]("port") ~
  config.get[List[String]]("hosts")
)(ServiceConfig) // Alternatively (name, port, hosts) => ServerConfig(name, port, posts)
// res8: configs.Result[ServiceConfig] = Success(
//   value = ServiceConfig(
//     name = "foo",
//     port = 9876,
//     hosts = List("localhost", "foo.com")
//   )
// )

Supported types

configs can get many type values from config. It is provided by type class ConfigReader.

There are a number of built-in ConfigReader instances:

  • Primitive/Wrapper types
    • Long, Int, Short, Byte, Double, Float, Char, Boolean
    • java.lang.{Long, Integer, Short, Byte, Double, Float, Character, Boolean}
  • Big number types
    • BigInt, BigDecimal
    • java.math.{BigInteger, BigDecimal}
  • String representation types
    • String
    • Symbol, java.util.{UUID, Locale}
    • java.io.File, java.nio.file.Path
    • java.net.{URI, InetAddress}
  • Duration types
    • java.time.Duration
    • scala.concurrent.duration.{Duration, FiniteDuration}
  • Config types
    • com.typesafe.config.{Config, ConfigValue, ConfigList, ConfigObject, ConfigMemorySize}
    • configs.Bytes
  • Enum types
    • Java enum types
    • Scala Enumeration types
  • Collection types
    • F[A] (using CanBuildFrom[Nothing, A, F[A]], e.g. List[String], Seq[Int])
    • M[S, A] (using CanBuildFrom[Nothing, (S, A), M[S, A]], e.g. Map[String, Int], TreeMap[UUID, Config])
    • java.util.{List[A], Map[S, A], Set[A], Collection[A]}, java.lang.Iterable[A]
    • java.util.Properties
  • Optional types
    • Option[A]
    • java.util.{Optional[A], OptionalLong, OptionalInt, OptionalDouble}
  • case classes
  • ADTs (sealed trait + classes/objects). See ADTs support
  • Java Beans. See Java Beans support

In this list, A means any type that is ConfigReader instance. And S means any type that is StringConverter instance.

ADTs support

If there is such an ADT:

sealed trait Tree
case class Branch(value: Int, left: Tree, right: Tree) extends Tree
case object Leaf extends Tree

You can get an ADT value from config:

val config = ConfigFactory.parseString("""
  tree = {
    value = 42
    left = Leaf
    right {
      value = 123
      left = Leaf
      right = Leaf
    }
  }
  """)
config.get[Tree]("tree")
// res9: configs.Result[Tree] = Success(
//   value = Branch(
//     value = 42,
//     left = Leaf,
//     right = Branch(value = 123, left = Leaf, right = Leaf)
//   )
// )

Java Beans support

If there is Java Beans class like the follows:

package com.example;

@lombok.Data
public class MyBean {
    private int intValue;
    private java.util.List<String> stringList;
    private java.util.Map<java.util.Locale, java.time.Duration> localeToDuration;
}

Then you define ConfigReader instance using deriveBean macro:

import com.example.MyBean

implicit val myBeanConfigReader: ConfigReader[MyBean] =
  ConfigReader.deriveBean[MyBean]

And then you can get Java Beans value:

val config = ConfigFactory.parseString("""
  int-value = 42
  string-list = [foo, bar, baz]
  locale-to-duration {
    ja_JP = 42ms
    en_US = 123s
  }
  """)
config.extract[MyBean]
// res11: configs.Result[MyBean] = Success(
//   value = MyBean(intValue=42, stringList=[foo, bar, baz], localeToDuration={en_US=PT2M3S, ja_JP=PT0.042S})
// )

License

Copyright 2013-2016 Tsukasa Kitachi

Apache License, Version 2.0

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].