Copyright | (c) 2019 Lucas David Traverso |
---|---|
License | MIT |
Maintainer | Lucas David Traverso <lucas6246@gmail.com> |
Stability | experimental |
Portability | portable |
Safe Haskell | Safe |
Language | Haskell2010 |
Types and functions for managing configuration effectively
Synopsis
- class FromConfig a where
- updateFromConfig :: Key -> Config -> a -> IO a
- fetchFromConfig :: Key -> Config -> IO (Maybe a)
- class DefaultConfig a where
- configDef :: a
- type SourceCreator = Config -> IO Source
- data Config
- newtype Key = Path {}
- data Source = Source {
- getKeyInSource :: Key -> IO (Maybe Text)
- getKey :: Key -> Config -> IO (Maybe Text)
- getFromConfig :: forall a. (Typeable a, FromConfig a, DefaultConfig a) => Key -> Config -> IO a
- getFromRootConfig :: forall a. (Typeable a, FromConfig a, DefaultConfig a) => Config -> IO a
- getFromConfigWithDefault :: forall a. (Typeable a, FromConfig a) => Key -> Config -> a -> IO a
- safeGetFromConfig :: forall a. (Typeable a, FromConfig a, DefaultConfig a) => Key -> Config -> IO (Maybe a)
- safeGetFromConfigWithDefault :: forall a. (Typeable a, FromConfig a) => Key -> Config -> a -> IO (Maybe a)
- (/.) :: Key -> Key -> Key
- emptyConfig :: Config
- withDefaults :: [(Key, Text)] -> Config -> Config
- addSource :: SourceCreator -> Config -> IO Config
- unsafeGetKey :: Key -> Config -> IO Text
- defaultConfig :: Text -> IO Config
- defaultConfigWithDefaults :: Text -> [(Key, Text)] -> IO Config
- newtype Key = Path {}
- module Conferer.Source.Env
- module Conferer.Source.Simple
- module Conferer.Source.Namespaced
- module Conferer.Source.Mapping
- module Conferer.Source.CLIArgs
- module Conferer.Source.Null
- module Conferer.Source.PropertiesFile
- (&) :: a -> (a -> b) -> b
How to use this library
This is the most basic example: which uses the default configuration
to get a configuration for warp, which can be overriden via env vars,
command line arguments of .properties
files
import Conferer import Conferer.FromConfig.Warp () -- from package conferer-warp main = do config <-defaultConfig
"awesomeapp" warpSettings <-getFromConfig
"warp" config runSettings warpSettings application
In the above example we see that we are getting a configuration value for
warp under the key warp, so for example to override it's default value
provided by warp the config keys for warp will always look like
warp.something
, for example to override the port for warp (3000 by
default) we could call our program as ./my_program --warp.port=8000
.
There are two sides to conferer: Getting configuration for other libraries like warp, hspec, snap, etc. and the way we choose to provide values like json files, properties files, env vars, etc.
Getting configuration for existing libraries
There is a typeclass FromConfig
that defines how to get a type
from a config, they are implemented in different packages since the
weight of the dependencies would be too high, the package is usually
named as conferer-DEPENDENCY
where DEPENDENCY is the name of the dependency (
for example: conferer-snap, conferer-warp, conferer-hspec), if you find
a library without a conferer port for its config you can create an issue
or maybe even create the library yourself!
Providing key value pairs for configuration
There is one important type in conferer: Config
from which, given a key
(eg: warp
) you can get anything that implements FromConfig
(like
Settings
)
Internally a Config
is made of many Source
s which have a simpler
interface:
getKeyInSource
:: Source -> Key -> IO (Maybe Text)
Most configuration sources can be abstracted away as Map String String, and they can use whatever logic they want to turn conferer keys (a list of strings) into a place to look for a string, (for example the env source requires a string to namespace the env vars that can affect the configuration)
Once you have your Source
you can add it to a Config
using the
addSource
function. One final note: each source has a different
priority, which depends on when is was added to the config (Source
s
added later have lower priority) so the config searches keys in sources
in the same order they were added.
class FromConfig a where Source #
Main typeclass for defining the way to get values from config, hiding the
Text
based nature of the Source
s.
updated using a config, so for example a Warp.Settings can get updated from a config,
but that doesn't make much sense for something like an Int
You'd normally would never implement this typeclass, if you want to implement
FromConfig
you should implement that directly, and if you want to use
DefaultConfig
and FromConfig
to implement FromConfig
you should let
the default Generics
based implementation do it's thing
Nothing
updateFromConfig :: Key -> Config -> a -> IO a Source #
updateFromConfig :: (Generic a, Typeable a, FromConfigG (Rep a)) => Key -> Config -> a -> IO a Source #
fetchFromConfig :: Key -> Config -> IO (Maybe a) Source #
fetchFromConfig :: (Generic a, FromConfigG (Rep a)) => Key -> Config -> IO (Maybe a) Source #
Instances
FromConfig Bool Source # | |
FromConfig Float Source # | |
FromConfig Int Source # | |
FromConfig Integer Source # | |
FromConfig () Source # | |
Defined in Conferer.FromConfig.Basics | |
FromConfig String Source # | |
FromConfig ByteString Source # | |
Defined in Conferer.FromConfig.Basics updateFromConfig :: Key -> Config -> ByteString -> IO ByteString Source # fetchFromConfig :: Key -> Config -> IO (Maybe ByteString) Source # | |
FromConfig Text Source # | |
FromConfig a => FromConfig (Maybe a) Source # | |
class DefaultConfig a where Source #
Default defining instance
Here a Nothing
means that the value didn't appear in the config, some
instances never return a value since they have defaults that can never
fail
Instances
DefaultConfig () Source # | |
Defined in Conferer.FromConfig.Basics | |
DefaultConfig (Maybe a) Source # | |
Defined in Conferer.FromConfig.Basics |
type SourceCreator = Config -> IO Source Source #
The type for creating a source given a Config
, some sources require a
certain configuration to be initialized (for example: the redis source
needs connection info to connect to the server)
Core type that the user of this library interact with, in the future it may contain more this besides a list of sources
The way to index Source
s, basically list of names that will be adapted
to whatever the source needs
Core interface for library provided configuration, basically consists of
getting a Key
and informing returning a maybe signaling the value and
if it's present in that specific source
getFromConfig :: forall a. (Typeable a, FromConfig a, DefaultConfig a) => Key -> Config -> IO a Source #
Fetch a value from a config under some specific key that's parsed using the FromConfig
instance, and as a default it uses the value from DefaultConfig
.
Notes: - This function may throw an exception if parsing fails for any subkey
getFromRootConfig :: forall a. (Typeable a, FromConfig a, DefaultConfig a) => Config -> IO a Source #
Same as getFromConfig
using the root key
Notes: - This function may throw an exception if parsing fails for any subkey
getFromConfigWithDefault :: forall a. (Typeable a, FromConfig a) => Key -> Config -> a -> IO a Source #
Same as getFromConfig
but with a user defined default (instead of DefaultConfig
instance)
Useful for fetching primitive types
safeGetFromConfig :: forall a. (Typeable a, FromConfig a, DefaultConfig a) => Key -> Config -> IO (Maybe a) Source #
Fetch a value from a config key that's parsed using the FromConfig instance.
Note: This function does not use default so the value must be fully defined by the config only,
meaning using this function for many records will always result in Nothing
(if the record contains
a value that can never be retrieved like a function)
safeGetFromConfigWithDefault :: forall a. (Typeable a, FromConfig a) => Key -> Config -> a -> IO (Maybe a) Source #
Same as safeGetFromConfig
but with a user defined default
emptyConfig :: Config Source #
The empty configuration, this Config
is used as the base for
most config creating functions.
defaultConfig :: Text -> IO Config Source #
Default config which reads from command line arguments, env vars and property files
defaultConfigWithDefaults :: Text -> [(Key, Text)] -> IO Config Source #
Default config which reads from command line arguments, env vars, property files and some default key/values
The way to index Source
s, basically list of names that will be adapted
to whatever the source needs
Sources
module Conferer.Source.Env
module Conferer.Source.Simple
module Conferer.Source.Namespaced
module Conferer.Source.Mapping
module Conferer.Source.CLIArgs
module Conferer.Source.Null