| Copyright | (c) 2019 Lucas David Traverso |
|---|---|
| License | MIT |
| Maintainer | Lucas David Traverso <lucas6246@gmail.com> |
| Stability | experimental |
| Portability | portable |
| Safe Haskell | Safe |
| Language | Haskell2010 |
Conferer
Contents
Description
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 Sources 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 (Sources
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 Sources.
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
Minimal complete definition
Nothing
Methods
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 Methods 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 Sources, 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 Sources, 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