conferer 0.3.0.0 → 0.4.0.0
raw patch · 38 files changed
+605/−605 lines, 38 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Conferer: Provider :: (Key -> IO (Maybe Text)) -> Provider
- Conferer: [getKeyInProvider] :: Provider -> Key -> IO (Maybe Text)
- Conferer: addProvider :: ProviderCreator -> Config -> IO Config
- Conferer: data Provider
- Conferer: type ProviderCreator = Config -> IO Provider
- Conferer.Core: addProvider :: ProviderCreator -> Config -> IO Config
- Conferer.Core: mkStandaloneProvider :: ProviderCreator -> IO Provider
- Conferer.Provider.CLIArgs: mkCLIArgsProvider :: ProviderCreator
- Conferer.Provider.CLIArgs: mkCLIArgsProvider' :: [String] -> ProviderCreator
- Conferer.Provider.CLIArgs: parseArgsIntoKeyValue :: [String] -> [(Key, Text)]
- Conferer.Provider.Env: keyToEnvVar :: Prefix -> Key -> Text
- Conferer.Provider.Env: mkEnvProvider :: Prefix -> ProviderCreator
- Conferer.Provider.Env: mkEnvProvider' :: LookupEnvFunc -> Prefix -> ProviderCreator
- Conferer.Provider.Env: type LookupEnvFunc = String -> IO (Maybe String)
- Conferer.Provider.Env: type Prefix = Text
- Conferer.Provider.Files: fromRight :: a -> Either e a -> a
- Conferer.Provider.Files: getFilePathFromEnv :: Config -> String -> IO FilePath
- Conferer.Provider.Mapping: mkMappingProvider :: Map Key Key -> ProviderCreator -> ProviderCreator
- Conferer.Provider.Mapping: mkMappingProvider' :: (Key -> Maybe Key) -> ProviderCreator -> ProviderCreator
- Conferer.Provider.Namespaced: mkNamespacedProvider :: Key -> ProviderCreator -> ProviderCreator
- Conferer.Provider.Null: mkNullProvider :: ProviderCreator
- Conferer.Provider.PropertiesFile: lineToKeyValue :: Text -> Maybe (Key, Text)
- Conferer.Provider.PropertiesFile: mkPropertiesFileProvider :: ProviderCreator
- Conferer.Provider.PropertiesFile: mkPropertiesFileProvider' :: Text -> ProviderCreator
- Conferer.Provider.Simple: mkMapProvider :: [(Key, Text)] -> ProviderCreator
- Conferer.Provider.Simple: mkMapProvider' :: Map Key Text -> ProviderCreator
- Conferer.Provider.Simple: mkPureMapProvider :: Map Key Text -> Provider
- Conferer.Types: Provider :: (Key -> IO (Maybe Text)) -> Provider
- Conferer.Types: [getKeyInProvider] :: Provider -> Key -> IO (Maybe Text)
- Conferer.Types: [providers] :: Config -> [Provider]
- Conferer.Types: data Provider
- Conferer.Types: type ProviderCreator = Config -> IO Provider
+ Conferer: Source :: (Key -> IO (Maybe Text)) -> Source
+ Conferer: [getKeyInSource] :: Source -> Key -> IO (Maybe Text)
+ Conferer: addSource :: SourceCreator -> Config -> IO Config
+ Conferer: data Source
+ Conferer: type SourceCreator = Config -> IO Source
+ Conferer.Core: addSource :: SourceCreator -> Config -> IO Config
+ Conferer.Core: mkStandaloneSource :: SourceCreator -> IO Source
+ Conferer.Source.CLIArgs: mkCLIArgsSource :: SourceCreator
+ Conferer.Source.CLIArgs: mkCLIArgsSource' :: [String] -> SourceCreator
+ Conferer.Source.CLIArgs: parseArgsIntoKeyValue :: [String] -> [(Key, Text)]
+ Conferer.Source.Env: keyToEnvVar :: Prefix -> Key -> Text
+ Conferer.Source.Env: mkEnvSource :: Prefix -> SourceCreator
+ Conferer.Source.Env: mkEnvSource' :: LookupEnvFunc -> Prefix -> SourceCreator
+ Conferer.Source.Env: type LookupEnvFunc = String -> IO (Maybe String)
+ Conferer.Source.Env: type Prefix = Text
+ Conferer.Source.Files: fromRight :: a -> Either e a -> a
+ Conferer.Source.Files: getFilePathFromEnv :: Config -> String -> IO FilePath
+ Conferer.Source.Mapping: mkMappingSource :: Map Key Key -> SourceCreator -> SourceCreator
+ Conferer.Source.Mapping: mkMappingSource' :: (Key -> Maybe Key) -> SourceCreator -> SourceCreator
+ Conferer.Source.Namespaced: mkNamespacedSource :: Key -> SourceCreator -> SourceCreator
+ Conferer.Source.Null: mkNullSource :: SourceCreator
+ Conferer.Source.PropertiesFile: lineToKeyValue :: Text -> Maybe (Key, Text)
+ Conferer.Source.PropertiesFile: mkPropertiesFileSource :: SourceCreator
+ Conferer.Source.PropertiesFile: mkPropertiesFileSource' :: Text -> SourceCreator
+ Conferer.Source.Simple: mkMapSource :: [(Key, Text)] -> SourceCreator
+ Conferer.Source.Simple: mkMapSource' :: Map Key Text -> SourceCreator
+ Conferer.Source.Simple: mkPureMapSource :: Map Key Text -> Source
+ Conferer.Types: Source :: (Key -> IO (Maybe Text)) -> Source
+ Conferer.Types: [getKeyInSource] :: Source -> Key -> IO (Maybe Text)
+ Conferer.Types: [sources] :: Config -> [Source]
+ Conferer.Types: data Source
+ Conferer.Types: type SourceCreator = Config -> IO Source
- Conferer.Types: Config :: [Provider] -> Map Key Text -> Config
+ Conferer.Types: Config :: [Source] -> Map Key Text -> Config
Files
- README.md +11/−11
- conferer.cabal +18/−18
- src/Conferer.hs +28/−28
- src/Conferer/Core.hs +15/−15
- src/Conferer/Provider/CLIArgs.hs +0/−43
- src/Conferer/Provider/Env.hs +0/−67
- src/Conferer/Provider/Files.hs +0/−21
- src/Conferer/Provider/Mapping.hs +0/−34
- src/Conferer/Provider/Namespaced.hs +0/−23
- src/Conferer/Provider/Null.hs +0/−18
- src/Conferer/Provider/PropertiesFile.hs +0/−54
- src/Conferer/Provider/Simple.hs +0/−34
- src/Conferer/Source/CLIArgs.hs +43/−0
- src/Conferer/Source/Env.hs +67/−0
- src/Conferer/Source/Files.hs +21/−0
- src/Conferer/Source/Mapping.hs +34/−0
- src/Conferer/Source/Namespaced.hs +23/−0
- src/Conferer/Source/Null.hs +18/−0
- src/Conferer/Source/PropertiesFile.hs +54/−0
- src/Conferer/Source/Simple.hs +34/−0
- src/Conferer/Types.hs +12/−12
- test/Conferer/FromConfig/BasicsSpec.hs +1/−1
- test/Conferer/GenericsSpec.hs +7/−7
- test/Conferer/Provider/ArgsSpec.hs +0/−38
- test/Conferer/Provider/EnvSpec.hs +0/−41
- test/Conferer/Provider/MappingSpec.hs +0/−43
- test/Conferer/Provider/NamespacedSpec.hs +0/−21
- test/Conferer/Provider/NullSpec.hs +0/−13
- test/Conferer/Provider/PropertiesFileSpec.hs +0/−39
- test/Conferer/Provider/SimpleSpec.hs +0/−22
- test/Conferer/Source/ArgsSpec.hs +38/−0
- test/Conferer/Source/EnvSpec.hs +41/−0
- test/Conferer/Source/MappingSpec.hs +43/−0
- test/Conferer/Source/NamespacedSpec.hs +21/−0
- test/Conferer/Source/NullSpec.hs +13/−0
- test/Conferer/Source/PropertiesFileSpec.hs +39/−0
- test/Conferer/Source/SimpleSpec.hs +22/−0
- test/ConfererSpec.hs +2/−2
README.md view
@@ -46,7 +46,7 @@ * Setting an environment variable called `AWESOMEAPP_SERVER_PORT=5555` * In a `config/dev.properties` file, you can have `server.port=5555` -And you may also get that value from different configuration providers like+And you may also get that value from different configuration sources like redis, json file, dhall file or whichever you may need. ## Example 2: many different values with defaults@@ -110,14 +110,14 @@ * `--hedis.host=redis.example.com`: set hedis' connection host to `redis.example.com` -## Existing providers+## Existing sources -Providers usually incur in many dependencies so they are split into different+Sources usually incur in many dependencies so they are split into different packages -* *[Json](https://hackage.haskell.org/package/conferer-provider-json)* (depends on `aeson`)-* *[Dhall](https://hackage.haskell.org/package/conferer-provider-dhall)* (depends on `dhall`)-* *[Yaml](https://hackage.haskell.org/package/conferer-provider-yaml)* (depends on `yaml`) +* *[Json](https://hackage.haskell.org/package/conferer-source-json)* (depends on `aeson`)+* *[Dhall](https://hackage.haskell.org/package/conferer-source-dhall)* (depends on `dhall`)+* *[Yaml](https://hackage.haskell.org/package/conferer-source-yaml)* (depends on `yaml`) ## Existing FromConfig instances @@ -131,17 +131,17 @@ ## Utilities -There are as well some utilities to change providers:+There are as well some utilities to change sources: -* `Conferer.Provider.Namespace`: All keys must be namespaced and the namespace+* `Conferer.Source.Namespace`: All keys must be namespaced and the namespace is striped for lookup-* `Conferer.Provider.Mapped`: Using a map key to maybe key you can change the+* `Conferer.Source.Mapped`: Using a map key to maybe key you can change the name of a key or even hiding some key-* `Conferer.Provider.Simple`: Get keys from a hardcoded map key to string+* `Conferer.Source.Simple`: Get keys from a hardcoded map key to string ## Future maybe things * Interpolate keys with other keys: `{a: "db", b: "${a}_thing"}`, getting `b` will give `"db_thing"` (maybe) even in different levels of configuration-* A LOT of providers+* A LOT of sources * A LOT of `FromConfig` implementations
conferer.cabal view
@@ -1,13 +1,13 @@ cabal-version: 1.18 --- This file has been generated from package.yaml by hpack version 0.31.2.+-- This file has been generated from package.yaml by hpack version 0.33.0. -- -- see: https://github.com/sol/hpack ----- hash: e9e6edef27397421e3ed20cd7b4269e086ded2fc7fd679dac79be16cf923d188+-- hash: 27fd2a5bad0744bb410d47e23efe3ef9a76a0bb35bd073e397f8f5f6c5c9a796 name: conferer-version: 0.3.0.0+version: 0.4.0.0 synopsis: Configuration management library description: Library to abstract the parsing of many haskell config values from different config sources@@ -28,14 +28,14 @@ Conferer Conferer.Core Conferer.FromConfig.Basics- Conferer.Provider.CLIArgs- Conferer.Provider.Env- Conferer.Provider.Files- Conferer.Provider.Mapping- Conferer.Provider.Namespaced- Conferer.Provider.Null- Conferer.Provider.PropertiesFile- Conferer.Provider.Simple+ Conferer.Source.CLIArgs+ Conferer.Source.Env+ Conferer.Source.Files+ Conferer.Source.Mapping+ Conferer.Source.Namespaced+ Conferer.Source.Null+ Conferer.Source.PropertiesFile+ Conferer.Source.Simple Conferer.Types other-modules: Paths_conferer@@ -56,13 +56,13 @@ other-modules: Conferer.FromConfig.BasicsSpec Conferer.GenericsSpec- Conferer.Provider.ArgsSpec- Conferer.Provider.EnvSpec- Conferer.Provider.MappingSpec- Conferer.Provider.NamespacedSpec- Conferer.Provider.NullSpec- Conferer.Provider.PropertiesFileSpec- Conferer.Provider.SimpleSpec+ Conferer.Source.ArgsSpec+ Conferer.Source.EnvSpec+ Conferer.Source.MappingSpec+ Conferer.Source.NamespacedSpec+ Conferer.Source.NullSpec+ Conferer.Source.PropertiesFileSpec+ Conferer.Source.SimpleSpec ConfererSpec Paths_conferer hs-source-dirs:
src/Conferer.hs view
@@ -50,23 +50,23 @@ -- (eg: @warp@) you can get anything that implements 'FromConfig' (like -- 'Warp.Settings') --- -- Internally a 'Config' is made of many 'Provider's which have a simpler+ -- Internally a 'Config' is made of many 'Source's which have a simpler -- interface: -- -- @- -- 'getKeyInProvider' :: Provider -> Key -> IO (Maybe Text)+ -- 'getKeyInSource' :: Source -> Key -> IO (Maybe Text) -- @ --- -- Most configuration providers can be abstracted away as Map String String,+ -- 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 provider+ -- 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 'Provider' you can add it to a 'Config' using the- -- 'addProvider' function. One final note: each provider has a different- -- priority, which depends on when is was added to the config ('Provider's- -- added later have lower priority) so the config searches keys in providers+ -- 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. module Conferer.Types@@ -75,14 +75,14 @@ , defaultConfigWithDefaults , Key(..) - -- * Providers- , module Conferer.Provider.Env- , module Conferer.Provider.Simple- , module Conferer.Provider.Namespaced- , module Conferer.Provider.Mapping- , module Conferer.Provider.CLIArgs- , module Conferer.Provider.Null- , module Conferer.Provider.PropertiesFile+ -- * 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+ , module Conferer.Source.PropertiesFile -- * Re-Exports , (&) ) where@@ -90,15 +90,15 @@ import Data.Text (Text) import Data.Function ((&)) -import Conferer.Core (emptyConfig, addProvider, getFromConfig, getFromRootConfig, getFromConfigWithDefault, safeGetFromConfig, safeGetFromConfigWithDefault, getKey, unsafeGetKey, (/.), withDefaults)-import Conferer.Types (Config, Key(..), ProviderCreator, Provider(..), DefaultConfig(..), FromConfig(..))-import Conferer.Provider.Env-import Conferer.Provider.Simple-import Conferer.Provider.Namespaced-import Conferer.Provider.Mapping-import Conferer.Provider.CLIArgs-import Conferer.Provider.Null-import Conferer.Provider.PropertiesFile+import Conferer.Core (emptyConfig, addSource, getFromConfig, getFromRootConfig, getFromConfigWithDefault, safeGetFromConfig, safeGetFromConfigWithDefault, getKey, unsafeGetKey, (/.), withDefaults)+import Conferer.Types (Config, Key(..), SourceCreator, Source(..), DefaultConfig(..), FromConfig(..))+import Conferer.Source.Env+import Conferer.Source.Simple+import Conferer.Source.Namespaced+import Conferer.Source.Mapping+import Conferer.Source.CLIArgs+import Conferer.Source.Null+import Conferer.Source.PropertiesFile -- | Default config which reads from command line arguments, env vars and -- property files@@ -111,7 +111,7 @@ defaultConfigWithDefaults :: Text -> [(Key, Text)] -> IO Config defaultConfigWithDefaults appName configMap = pure (emptyConfig & withDefaults configMap)- >>= addProvider (mkCLIArgsProvider)- >>= addProvider (mkEnvProvider appName)- >>= addProvider (mkPropertiesFileProvider)+ >>= addSource (mkCLIArgsSource)+ >>= addSource (mkEnvSource appName)+ >>= addSource (mkPropertiesFileSource)
src/Conferer/Core.hs view
@@ -10,22 +10,22 @@ import Data.Typeable (Typeable, Proxy(..), typeRep) import Control.Exception (try, throw, throwIO, evaluate) -import Conferer.Provider.Simple+import Conferer.Source.Simple import Conferer.Types -- | Most Basic function to interact directly with a 'Config'. It always returns -- 'Text' in the case of success and implements the logic to traverse--- providers inside the 'Config'.+-- sources inside the 'Config'. getKey :: Key -> Config -> IO (Maybe Text) getKey k config =- go $ providers config ++ [mkPureMapProvider (defaults config)]+ go $ sources config ++ [mkPureMapSource (defaults config)] where go [] = return Nothing- go (provider:providers) = do- res <- getKeyInProvider provider k+ go (source:sources) = do+ res <- getKeyInSource source k case res of Just t -> return $ Just t- Nothing -> go providers+ Nothing -> go sources -- | Fetch a value from a config under some specific key that's parsed using the 'FromConfig'@@ -93,20 +93,20 @@ withDefaults configMap config = config { defaults = Map.fromList configMap } --- | Instantiate a 'ProviderCreator' using the 'emptyConfig'-mkStandaloneProvider :: ProviderCreator -> IO Provider-mkStandaloneProvider mkProvider =- mkProvider emptyConfig+-- | Instantiate a 'SourceCreator' using the 'emptyConfig'+mkStandaloneSource :: SourceCreator -> IO Source+mkStandaloneSource mkSource =+ mkSource emptyConfig --- | Instantiate a 'Provider' using an 'ProviderCretor' and a 'Config' and add+-- | Instantiate a 'Source' using an 'SourceCretor' and a 'Config' and add -- to the config-addProvider :: ProviderCreator -> Config -> IO Config-addProvider mkProvider config = do- newProvider <- mkProvider config+addSource :: SourceCreator -> Config -> IO Config+addSource mkSource config = do+ newSource <- mkSource config return $ config- { providers = providers config ++ [ newProvider ]+ { sources = sources config ++ [ newSource ] } -- | Same as 'getKey' but it throws if the 'Key' isn't found
− src/Conferer/Provider/CLIArgs.hs
@@ -1,43 +0,0 @@-module Conferer.Provider.CLIArgs- (- -- * Command line arguments Provider- -- | This provider provides keys from the command line arguments passed into- -- the program. It only accepts arguments with @--@ and an equals, for- -- example: @./awesomeapp --warp.port=5000@- mkCLIArgsProvider- , mkCLIArgsProvider'- , parseArgsIntoKeyValue- )-where--import Data.Text (Text)-import qualified Data.Text as Text-import Data.Maybe (mapMaybe)-import Data.String (fromString)-import System.Environment (getArgs)--import Conferer.Types-import Conferer.Provider.Simple----- | Create a 'ProviderCreator' for CLIArgs from a argument list-mkCLIArgsProvider' :: [String] -> ProviderCreator-mkCLIArgsProvider' args = \config -> do- let configMap = parseArgsIntoKeyValue args- mkMapProvider configMap config---- | Same as 'mkCLIArgsProvider'' but using 'getArgs' to provide the argument--- list-mkCLIArgsProvider :: ProviderCreator-mkCLIArgsProvider = \config -> do- args <- getArgs- mkCLIArgsProvider' args config---- | Parse an argument list into a dictionary suitable for a 'Provider'-parseArgsIntoKeyValue :: [String] -> [(Key, Text)]-parseArgsIntoKeyValue =- fmap (\(k, s) -> (fromString $ Text.unpack k, s)) .- fmap (\s -> fmap (Text.drop 1) $ Text.breakOn "=" s).- mapMaybe (Text.stripPrefix "--") .- takeWhile (/= "--") .- fmap Text.pack
− src/Conferer/Provider/Env.hs
@@ -1,67 +0,0 @@-module Conferer.Provider.Env- (--- * Env Provider--- | This 'Provider' provides config values from env vars given a prefix that's--- used to avoid colliding with different system configuration------ For example if you use the 'Prefix' "awesomeapp" and get the 'Key'--- "warp.port" this provider will try to lookup the env var called--- @AWESOMEAPP_WARP_PORT@.---- * Usage--- | To use this provider simply choose a prefix and add it using the--- 'addProvider' function like:------ @--- config & 'addProvider' ('mkEnvProvider' "awesomeapp")--- @- mkEnvProvider- , mkEnvProvider'- , Prefix- , LookupEnvFunc- , keyToEnvVar- ) where---import Data.Text (Text)-import qualified Data.Text as Text-import qualified System.Environment as System--import Conferer.Types---- | 'ProviderCreator' for env 'Provider' that uses the real 'System.lookupEnv'--- function-mkEnvProvider :: Prefix -> ProviderCreator-mkEnvProvider prefix =- mkEnvProvider' System.lookupEnv prefix---- | 'ProviderCreator' for env 'Provider' that allows parameterizing the--- function used to lookup for testing-mkEnvProvider' :: LookupEnvFunc -> Prefix -> ProviderCreator-mkEnvProvider' lookupEnv prefix = \_config ->- return $- Provider- { getKeyInProvider = \k -> do- let envVarName = Text.unpack $ keyToEnvVar prefix k- fmap Text.pack <$> lookupEnv envVarName- }---- | Type alias for the function to lookup env vars-type LookupEnvFunc = String -> IO (Maybe String)----- | A text to namespace env vars-type Prefix = Text---- | Get the env name from a prefix and a key by uppercasing and--- intercalating underscores------ >>> keyToEnVar "awesomeapp" "warp.port"--- "AWESOMEAPP_WARP_PORT"-keyToEnvVar :: Prefix -> Key -> Text-keyToEnvVar prefix (Path keys) =- Text.toUpper- $ Text.intercalate "_"- $ filter (/= mempty)- $ prefix : keys-
− src/Conferer/Provider/Files.hs
@@ -1,21 +0,0 @@-module Conferer.Provider.Files where--import qualified Data.Text as Text-import Data.Maybe (fromMaybe)--import Conferer.Types-import Conferer.FromConfig.Basics ()--fromRight :: a -> Either e a -> a-fromRight a (Left _) = a-fromRight _ (Right a) = a--getFilePathFromEnv :: Config -> String -> IO FilePath-getFilePathFromEnv config extension = do- env <- updateFromConfig "env" config "development"- return $ mconcat- [ "config/"- , Text.unpack env- , "."- , extension- ]
− src/Conferer/Provider/Mapping.hs
@@ -1,34 +0,0 @@-module Conferer.Provider.Mapping- (- -- * Namespaced higher-order provider- -- | This provider takes a provider and returns a new provider that- -- always transforms the key according to either a function for- -- 'mkMappingProvider'' or a 'Map' for 'mkMappingProvider'- mkMappingProvider- , mkMappingProvider'- )-where--import Data.Map (Map)-import qualified Data.Map as Map--import Conferer.Types---- | Create a 'ProviderCreator' using a function to transform the supplied keys--- and another 'ProviderCreator'-mkMappingProvider' :: (Key -> Maybe Key) -> ProviderCreator -> ProviderCreator-mkMappingProvider' mapper providerCreator config = do- configProvider <- providerCreator config-- return $ Provider- { getKeyInProvider = \k -> do- case mapper k of- Just newKey -> getKeyInProvider configProvider newKey- Nothing -> return Nothing- }---- | Create a 'ProviderCreator' using a 'Map' 'Key' 'Key' to transform the supplied keys--- and another 'ProviderCreator'-mkMappingProvider :: Map Key Key -> ProviderCreator -> ProviderCreator-mkMappingProvider configMap configProvider =- mkMappingProvider' (`Map.lookup` configMap) configProvider
− src/Conferer/Provider/Namespaced.hs
@@ -1,23 +0,0 @@-module Conferer.Provider.Namespaced- (- -- * Namespaced higher-order provider- -- | This provider takes a provider and returns a new provider that- -- always checks that the 'Key' given always starts with certain 'Key'- -- and then strips that prefix before consulting its inner Provider- mkNamespacedProvider- ) where--import Data.List (stripPrefix)--import Conferer.Types---- | Create a 'ProviderCreator' from a prefix and another 'ProviderCreator'-mkNamespacedProvider :: Key -> ProviderCreator -> ProviderCreator-mkNamespacedProvider (Path key) configCreator = \config -> do- configProvider <- configCreator config- return $ Provider- { getKeyInProvider = \(Path k) -> do- case stripPrefix key k of- Just newKey -> getKeyInProvider configProvider (Path newKey)- Nothing -> return Nothing- }
− src/Conferer/Provider/Null.hs
@@ -1,18 +0,0 @@-module Conferer.Provider.Null- (- -- * Does Nothing Provider- -- | The stub provider that never has a key- mkNullProvider- )-where--import Conferer.Types---- | Create a null 'Provider'-mkNullProvider :: ProviderCreator-mkNullProvider _config =- return $ Provider- { getKeyInProvider =- \_k -> do- return Nothing- }
− src/Conferer/Provider/PropertiesFile.hs
@@ -1,54 +0,0 @@-module Conferer.Provider.PropertiesFile where--import Data.Text (Text)-import Data.Function ((&))-import System.Directory (doesFileExist)-import Data.Maybe (catMaybes)-import qualified Data.Text as Text-import qualified Data.Text.IO as Text--import Conferer.Types-import Conferer.Provider.Files-import Conferer.Provider.Null-import Conferer.Provider.Simple---- | 'ProviderCreator' for properties file 'Provider' that read from a--- config file in @config/{env}.properties@ and parses it as a properties--- file with @some.key=a value@ lines-mkPropertiesFileProvider :: ProviderCreator-mkPropertiesFileProvider = \config -> do- filePath <- getFilePathFromEnv config "properties"- fileExists <- doesFileExist filePath- if fileExists- then do- fileContent <- Text.readFile filePath- mkPropertiesFileProvider' fileContent config- else do- mkNullProvider config----- | 'ProviderCreator' for properties file 'Provider' that only parses a--- given 'Text' as a properties file-mkPropertiesFileProvider' :: Text -> ProviderCreator-mkPropertiesFileProvider' fileContent =- \config -> do- let keyValues =- fileContent- & Text.lines- & fmap lineToKeyValue- & catMaybes- mkMapProvider keyValues config----- | Transform a line into a key/value pair (or not)-lineToKeyValue :: Text -> Maybe (Key, Text)-lineToKeyValue line =- Text.breakOn "=" line- & (\(rawKey, rawValue) ->- case Text.stripPrefix "=" rawValue of- Just value ->- Just (Path $ Text.splitOn "." rawKey, value)- Nothing ->- Nothing- )-
− src/Conferer/Provider/Simple.hs
@@ -1,34 +0,0 @@-module Conferer.Provider.Simple- (- -- * Simple Provider- -- | This provider provides values from a hardcoded Map passed at creation- -- time that can not be changed afterwards, it's mostly used as a necessary- -- utility- mkMapProvider- , mkMapProvider'- , mkPureMapProvider- ) where--import Data.Map (Map)-import qualified Data.Map as Map-import Data.Text (Text)--import Conferer.Types---- | Make a 'ProviderCreator' from a 'Map'-mkMapProvider' :: Map Key Text -> ProviderCreator-mkMapProvider' configMap _config =- return $ mkPureMapProvider configMap---- | Make a 'Provider' from a 'Map'-mkPureMapProvider :: Map Key Text -> Provider-mkPureMapProvider configMap =- Provider- { getKeyInProvider =- \k -> do- return $ Map.lookup k configMap- }---- | Make a 'Provider' from 'List' of 'Key', 'Text' pairs-mkMapProvider :: [(Key, Text)] -> ProviderCreator-mkMapProvider = mkMapProvider' . Map.fromList
+ src/Conferer/Source/CLIArgs.hs view
@@ -0,0 +1,43 @@+module Conferer.Source.CLIArgs+ (+ -- * Command line arguments Source+ -- | This source provides keys from the command line arguments passed into+ -- the program. It only accepts arguments with @--@ and an equals, for+ -- example: @./awesomeapp --warp.port=5000@+ mkCLIArgsSource+ , mkCLIArgsSource'+ , parseArgsIntoKeyValue+ )+where++import Data.Text (Text)+import qualified Data.Text as Text+import Data.Maybe (mapMaybe)+import Data.String (fromString)+import System.Environment (getArgs)++import Conferer.Types+import Conferer.Source.Simple+++-- | Create a 'SourceCreator' for CLIArgs from a argument list+mkCLIArgsSource' :: [String] -> SourceCreator+mkCLIArgsSource' args = \config -> do+ let configMap = parseArgsIntoKeyValue args+ mkMapSource configMap config++-- | Same as 'mkCLIArgsSource'' but using 'getArgs' to provide the argument+-- list+mkCLIArgsSource :: SourceCreator+mkCLIArgsSource = \config -> do+ args <- getArgs+ mkCLIArgsSource' args config++-- | Parse an argument list into a dictionary suitable for a 'Source'+parseArgsIntoKeyValue :: [String] -> [(Key, Text)]+parseArgsIntoKeyValue =+ fmap (\(k, s) -> (fromString $ Text.unpack k, s)) .+ fmap (\s -> fmap (Text.drop 1) $ Text.breakOn "=" s).+ mapMaybe (Text.stripPrefix "--") .+ takeWhile (/= "--") .+ fmap Text.pack
+ src/Conferer/Source/Env.hs view
@@ -0,0 +1,67 @@+module Conferer.Source.Env+ (+-- * Env Source+-- | This 'Source' provides config values from env vars given a prefix that's+-- used to avoid colliding with different system configuration+--+-- For example if you use the 'Prefix' "awesomeapp" and get the 'Key'+-- "warp.port" this source will try to lookup the env var called+-- @AWESOMEAPP_WARP_PORT@.++-- * Usage+-- | To use this source simply choose a prefix and add it using the+-- 'addSource' function like:+--+-- @+-- config & 'addSource' ('mkEnvSource' "awesomeapp")+-- @+ mkEnvSource+ , mkEnvSource'+ , Prefix+ , LookupEnvFunc+ , keyToEnvVar+ ) where+++import Data.Text (Text)+import qualified Data.Text as Text+import qualified System.Environment as System++import Conferer.Types++-- | 'SourceCreator' for env 'Source' that uses the real 'System.lookupEnv'+-- function+mkEnvSource :: Prefix -> SourceCreator+mkEnvSource prefix =+ mkEnvSource' System.lookupEnv prefix++-- | 'SourceCreator' for env 'Source' that allows parameterizing the+-- function used to lookup for testing+mkEnvSource' :: LookupEnvFunc -> Prefix -> SourceCreator+mkEnvSource' lookupEnv prefix = \_config ->+ return $+ Source+ { getKeyInSource = \k -> do+ let envVarName = Text.unpack $ keyToEnvVar prefix k+ fmap Text.pack <$> lookupEnv envVarName+ }++-- | Type alias for the function to lookup env vars+type LookupEnvFunc = String -> IO (Maybe String)+++-- | A text to namespace env vars+type Prefix = Text++-- | Get the env name from a prefix and a key by uppercasing and+-- intercalating underscores+--+-- >>> keyToEnVar "awesomeapp" "warp.port"+-- "AWESOMEAPP_WARP_PORT"+keyToEnvVar :: Prefix -> Key -> Text+keyToEnvVar prefix (Path keys) =+ Text.toUpper+ $ Text.intercalate "_"+ $ filter (/= mempty)+ $ prefix : keys+
+ src/Conferer/Source/Files.hs view
@@ -0,0 +1,21 @@+module Conferer.Source.Files where++import qualified Data.Text as Text+import Data.Maybe (fromMaybe)++import Conferer.Types+import Conferer.FromConfig.Basics ()++fromRight :: a -> Either e a -> a+fromRight a (Left _) = a+fromRight _ (Right a) = a++getFilePathFromEnv :: Config -> String -> IO FilePath+getFilePathFromEnv config extension = do+ env <- updateFromConfig "env" config "development"+ return $ mconcat+ [ "config/"+ , Text.unpack env+ , "."+ , extension+ ]
+ src/Conferer/Source/Mapping.hs view
@@ -0,0 +1,34 @@+module Conferer.Source.Mapping+ (+ -- * Namespaced higher-order source+ -- | This source takes a source and returns a new source that+ -- always transforms the key according to either a function for+ -- 'mkMappingSource'' or a 'Map' for 'mkMappingSource'+ mkMappingSource+ , mkMappingSource'+ )+where++import Data.Map (Map)+import qualified Data.Map as Map++import Conferer.Types++-- | Create a 'SourceCreator' using a function to transform the supplied keys+-- and another 'SourceCreator'+mkMappingSource' :: (Key -> Maybe Key) -> SourceCreator -> SourceCreator+mkMappingSource' mapper sourceCreator config = do+ configSource <- sourceCreator config++ return $ Source+ { getKeyInSource = \k -> do+ case mapper k of+ Just newKey -> getKeyInSource configSource newKey+ Nothing -> return Nothing+ }++-- | Create a 'SourceCreator' using a 'Map' 'Key' 'Key' to transform the supplied keys+-- and another 'SourceCreator'+mkMappingSource :: Map Key Key -> SourceCreator -> SourceCreator+mkMappingSource configMap configSource =+ mkMappingSource' (`Map.lookup` configMap) configSource
+ src/Conferer/Source/Namespaced.hs view
@@ -0,0 +1,23 @@+module Conferer.Source.Namespaced+ (+ -- * Namespaced higher-order source+ -- | This source takes a source and returns a new source that+ -- always checks that the 'Key' given always starts with certain 'Key'+ -- and then strips that prefix before consulting its inner Source+ mkNamespacedSource+ ) where++import Data.List (stripPrefix)++import Conferer.Types++-- | Create a 'SourceCreator' from a prefix and another 'SourceCreator'+mkNamespacedSource :: Key -> SourceCreator -> SourceCreator+mkNamespacedSource (Path key) configCreator = \config -> do+ configSource <- configCreator config+ return $ Source+ { getKeyInSource = \(Path k) -> do+ case stripPrefix key k of+ Just newKey -> getKeyInSource configSource (Path newKey)+ Nothing -> return Nothing+ }
+ src/Conferer/Source/Null.hs view
@@ -0,0 +1,18 @@+module Conferer.Source.Null+ (+ -- * Does Nothing Source+ -- | The stub source that never has a key+ mkNullSource+ )+where++import Conferer.Types++-- | Create a null 'Source'+mkNullSource :: SourceCreator+mkNullSource _config =+ return $ Source+ { getKeyInSource =+ \_k -> do+ return Nothing+ }
+ src/Conferer/Source/PropertiesFile.hs view
@@ -0,0 +1,54 @@+module Conferer.Source.PropertiesFile where++import Data.Text (Text)+import Data.Function ((&))+import System.Directory (doesFileExist)+import Data.Maybe (catMaybes)+import qualified Data.Text as Text+import qualified Data.Text.IO as Text++import Conferer.Types+import Conferer.Source.Files+import Conferer.Source.Null+import Conferer.Source.Simple++-- | 'SourceCreator' for properties file 'Source' that read from a+-- config file in @config/{env}.properties@ and parses it as a properties+-- file with @some.key=a value@ lines+mkPropertiesFileSource :: SourceCreator+mkPropertiesFileSource = \config -> do+ filePath <- getFilePathFromEnv config "properties"+ fileExists <- doesFileExist filePath+ if fileExists+ then do+ fileContent <- Text.readFile filePath+ mkPropertiesFileSource' fileContent config+ else do+ mkNullSource config+++-- | 'SourceCreator' for properties file 'Source' that only parses a+-- given 'Text' as a properties file+mkPropertiesFileSource' :: Text -> SourceCreator+mkPropertiesFileSource' fileContent =+ \config -> do+ let keyValues =+ fileContent+ & Text.lines+ & fmap lineToKeyValue+ & catMaybes+ mkMapSource keyValues config+++-- | Transform a line into a key/value pair (or not)+lineToKeyValue :: Text -> Maybe (Key, Text)+lineToKeyValue line =+ Text.breakOn "=" line+ & (\(rawKey, rawValue) ->+ case Text.stripPrefix "=" rawValue of+ Just value ->+ Just (Path $ Text.splitOn "." rawKey, value)+ Nothing ->+ Nothing+ )+
+ src/Conferer/Source/Simple.hs view
@@ -0,0 +1,34 @@+module Conferer.Source.Simple+ (+ -- * Simple Source+ -- | This source provides values from a hardcoded Map passed at creation+ -- time that can not be changed afterwards, it's mostly used as a necessary+ -- utility+ mkMapSource+ , mkMapSource'+ , mkPureMapSource+ ) where++import Data.Map (Map)+import qualified Data.Map as Map+import Data.Text (Text)++import Conferer.Types++-- | Make a 'SourceCreator' from a 'Map'+mkMapSource' :: Map Key Text -> SourceCreator+mkMapSource' configMap _config =+ return $ mkPureMapSource configMap++-- | Make a 'Source' from a 'Map'+mkPureMapSource :: Map Key Text -> Source+mkPureMapSource configMap =+ Source+ { getKeyInSource =+ \k -> do+ return $ Map.lookup k configMap+ }++-- | Make a 'Source' from 'List' of 'Key', 'Text' pairs+mkMapSource :: [(Key, Text)] -> SourceCreator+mkMapSource = mkMapSource' . Map.fromList
src/Conferer/Types.hs view
@@ -17,14 +17,14 @@ -- | 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 provider-data Provider =- Provider- { getKeyInProvider :: Key -> IO (Maybe Text)+-- if it's present in that specific source+data Source =+ Source+ { getKeyInSource :: Key -> IO (Maybe Text) } --- | The way to index 'Provider's, basically list of names that will be adapted--- to whatever the provider needs+-- | The way to index 'Source's, basically list of names that will be adapted+-- to whatever the source needs newtype Key = Path { unKey :: [Text] } deriving (Show, Eq, Ord)@@ -37,17 +37,17 @@ keyName = Text.intercalate "." . unKey -- | Core type that the user of this library interact with, in the future it may--- contain more this besides a list of providers+-- contain more this besides a list of sources data Config = Config- { providers :: [Provider]+ { sources :: [Source] , defaults :: Map Key Text } --- | The type for creating a provider given a 'Config', some providers require a--- certain configuration to be initialized (for example: the redis provider+-- | 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)-type ProviderCreator = Config -> IO Provider+type SourceCreator = Config -> IO Source keyNotPresentError :: forall a. (Typeable a) => Key -> Proxy a -> FailedToFetchError keyNotPresentError key =@@ -62,7 +62,7 @@ configDef :: a -- | Main typeclass for defining the way to get values from config, hiding the--- 'Text' based nature of the 'Provider's.+-- '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' --
test/Conferer/FromConfig/BasicsSpec.hs view
@@ -13,7 +13,7 @@ import Control.DeepSeq configWith :: [(Key, Text)] -> IO Config-configWith keyValues = emptyConfig & addProvider (mkMapProvider keyValues)+configWith keyValues = emptyConfig & addSource (mkMapSource keyValues) configParserError_ :: ConfigParsingError -> Bool configParserError_ = const True
test/Conferer/GenericsSpec.hs view
@@ -38,14 +38,14 @@ context "when no keys are set" $ do it "returns the default" $ do c <- emptyConfig- & addProvider (mkMapProvider [ ])+ & addSource (mkMapSource [ ]) res <- fetch @Thing "somekey" c res `shouldBe` Thing { thingA = 0, thingB = 0 } context "when all keys are set" $ do it "return the keys set" $ do c <- emptyConfig- & addProvider (mkMapProvider+ & addSource (mkMapSource [ ("somekey.a", "1") , ("somekey.b", "2") ])@@ -56,7 +56,7 @@ context "when some keys are set" $ do it "uses the default and returns the keys set" $ do c <- emptyConfig- & addProvider (mkMapProvider+ & addSource (mkMapSource [ ("somekey.b", "2") ]) @@ -67,7 +67,7 @@ context "when none of the keys are set" $ do it "returns the default of both records" $ do c <- emptyConfig- & addProvider (mkMapProvider+ & addSource (mkMapSource [ ]) res <- fetch @Bigger "somekey" c@@ -76,7 +76,7 @@ context "when some keys of the top record are set" $ do it "returns the default for the inner record" $ do c <- emptyConfig- & addProvider (mkMapProvider+ & addSource (mkMapSource [ ("somekey.b", "30") ]) @@ -86,7 +86,7 @@ context "when some keys of the inner record are set" $ do it "returns the inner record updated" $ do c <- emptyConfig- & addProvider (mkMapProvider+ & addSource (mkMapSource [ ("somekey.thing.a", "30") ]) @@ -96,7 +96,7 @@ context "when every key is set" $ do it "returns everything with the right values" $ do c <- emptyConfig- & addProvider (mkMapProvider+ & addSource (mkMapSource [ ("somekey.thing.a", "10") , ("somekey.thing.b", "20") , ("somekey.b", "30")
− test/Conferer/Provider/ArgsSpec.hs
@@ -1,38 +0,0 @@-module Conferer.Provider.ArgsSpec where--import Test.Hspec--import Conferer--spec :: Spec-spec = do- describe "with a mapping provider" $ do- let mkConf args =- emptyConfig- & addProvider- (mkCLIArgsProvider' args)-- it "gets a parameters with it's value if it starts with the right prefix" $ do- c <- mkConf []- res <- getKey "some.key" c- res `shouldBe` Nothing-- it "with a value that begins with the right prefix it uses it" $ do- c <- mkConf ["--some.key=value"]- res <- getKey "some.key" c- res `shouldBe` Just "value"-- it "with a reapeated value it uses the last one" $ do- c <- mkConf ["--some.key=value", "--some.key=different value"]- res <- getKey "some.key" c- res `shouldBe` Just "different value"-- it "ignores values that don't start with the right prefix" $ do- c <- mkConf ["some.key=value", "-some.key=value", "-Xsome.key=value", "some.key"]- res <- getKey "some.key" c- res `shouldBe` Nothing-- it "after encountering a -- it stops parsing parameters" $ do- c <- mkConf ["--", "--some.key=value"]- res <- getKey "some.key" c- res `shouldBe` Nothing
− test/Conferer/Provider/EnvSpec.hs
@@ -1,41 +0,0 @@-module Conferer.Provider.EnvSpec where--import Test.Hspec-import qualified Data.Map as Map--import Conferer--fakeLookupEnv :: [(String, String)] -> LookupEnvFunc-fakeLookupEnv fakeEnv = \envName ->- return $ Map.lookup envName $ Map.fromList fakeEnv--spec :: Spec-spec = do- describe "with an env config" $ do- let- mkEnvConfig =- emptyConfig- & addProvider- (mkEnvProvider'- (fakeLookupEnv- [ ("TMUX","/tmp/tmux-1000/default,2822,0")- , ("TMUX_PANE","%1")- , ("TMUX_PLUGIN_MANAGER_PATH","/home/user/.tmux/plugins/")- ])- "TMUX"- )- it "getting an existent key returns unwraps top level value (wihtout \- \children)" $ do- c <- mkEnvConfig- res <- getKey "." c- res `shouldBe` Just "/tmp/tmux-1000/default,2822,0"-- it "getting an existent key for a child gets that value" $ do- c <- mkEnvConfig- res <- getKey "pane" c- res `shouldBe` Just "%1"-- it "keys should always be consistent as to how the words are separated" $ do- c <- mkEnvConfig- res <- getKey "pane" c- res `shouldBe` Just "%1"
− test/Conferer/Provider/MappingSpec.hs
@@ -1,43 +0,0 @@-module Conferer.Provider.MappingSpec where--import Test.Hspec-import qualified Data.Map as Map-import Data.Function ((&))--import Conferer--spec :: Spec-spec = do- describe "with a mapping provider" $ do- it "getting an existent key in the original map but that's not mapped in the \- \wrapper doesn't exist" $ do- c <- emptyConfig- & addProvider (mkMappingProvider Map.empty- $ mkMapProvider [("some.key", "some value")])- res <- getKey "some.key" c- res `shouldBe` Nothing-- it "getting a non existent key isn't there" $ do- c <- emptyConfig- & addProvider (mkMappingProvider (Map.fromList [("k", "key")])- $ mkMapProvider [("key", "75")])-- res <- getKey "xxxx" c- res `shouldBe` Nothing-- it "getting an existent key that's mapped but doesn't exist on the \- \inner provider isn't there" $ do- c <- emptyConfig- & addProvider (mkMappingProvider (Map.fromList [("another.key", "some.key")])- $ mkMapProvider [])-- res <- getKey "another.key" c- res `shouldBe` Nothing-- it "getting an existent key that's mapped properly gets it and exists on \- \the inner provider gets it" $ do- c <- emptyConfig- & addProvider (mkMappingProvider (Map.fromList [("another.key", "some.key")])- $ mkMapProvider [("some.key", "some value")])- res <- getKey "another.key" c- res `shouldBe` Just "some value"
− test/Conferer/Provider/NamespacedSpec.hs
@@ -1,21 +0,0 @@-module Conferer.Provider.NamespacedSpec where--import Test.Hspec--import Conferer--spec :: Spec-spec = do- describe "namespaced config" $ do- it "return nothing if the key doesn't match" $ do- c <- emptyConfig- & addProvider (mkNamespacedProvider "postgres"- $ mkMapProvider [("url", "some url")])- res <- getKey "url" c- res `shouldBe` Nothing- it "returns the wrapped value" $ do- c <- emptyConfig- & addProvider (mkNamespacedProvider "postgres"- $ mkMapProvider [("url", "some url")])- res <- getKey "postgres.url" c- res `shouldBe` Just "some url"
− test/Conferer/Provider/NullSpec.hs
@@ -1,13 +0,0 @@-module Conferer.Provider.NullSpec where--import Test.Hspec--import Conferer--spec :: Spec-spec = do- it "always fails to get a key" $ do- c <- emptyConfig- & addProvider mkNullProvider- res <- getKey "some.key" c- res `shouldBe` Nothing
− test/Conferer/Provider/PropertiesFileSpec.hs
@@ -1,39 +0,0 @@-module Conferer.Provider.PropertiesFileSpec where--import Test.Hspec-import Data.Text (Text)-import qualified Data.Text as Text-import qualified Data.Map as Map--import Conferer-import Conferer.Core-import Conferer.Provider.PropertiesFile--fakeLookupEnv :: [(String, String)] -> LookupEnvFunc-fakeLookupEnv fakeEnv = \envName ->- return $ Map.lookup envName $ Map.fromList fakeEnv--spec :: Spec-spec = do- describe "with a properties file config" $ do- it "getting an existent key returns unwraps top level value (wihtout \- \children)" $ do- c <- mkStandaloneProvider $ mkPropertiesFileProvider' "some.key=a value"- res <- getKeyInProvider c "some.key"- res `shouldBe` Just "a value"-- it "getting an existent key for a child gets that value" $ do- c <- mkStandaloneProvider $ mkPropertiesFileProvider' $ Text.unlines- [ "some.key=a value"- , "some.key=b"- ]- res <- getKeyInProvider c "some.key"- res `shouldBe` Just "b"-- it "keys should always be consistent as to how the words are separated" $ do- c <- mkStandaloneProvider $ mkPropertiesFileProvider' $ Text.unlines- [ "some.key=a value"- , "some.key=b"- ]- res <- getKeyInProvider c "another.key"- res `shouldBe` Nothing
− test/Conferer/Provider/SimpleSpec.hs
@@ -1,22 +0,0 @@-module Conferer.Provider.SimpleSpec where--import Test.Hspec--import Conferer--spec :: Spec-spec = do- describe "json provider" $ do- let creator =- emptyConfig- & addProvider (mkMapProvider [ ("postgres.url", "some url")])-- it "getting a non existent key returns an empty config" $ do- c <- creator- res <- getKey "some.key" c- res `shouldBe` Nothing-- it "getting an existent key returns unwraps the original map" $ do- c <- creator- res <- getKey "postgres.url" c- res `shouldBe` Just "some url"
+ test/Conferer/Source/ArgsSpec.hs view
@@ -0,0 +1,38 @@+module Conferer.Source.ArgsSpec where++import Test.Hspec++import Conferer++spec :: Spec+spec = do+ describe "with a mapping source" $ do+ let mkConf args =+ emptyConfig+ & addSource+ (mkCLIArgsSource' args)++ it "gets a parameters with it's value if it starts with the right prefix" $ do+ c <- mkConf []+ res <- getKey "some.key" c+ res `shouldBe` Nothing++ it "with a value that begins with the right prefix it uses it" $ do+ c <- mkConf ["--some.key=value"]+ res <- getKey "some.key" c+ res `shouldBe` Just "value"++ it "with a reapeated value it uses the last one" $ do+ c <- mkConf ["--some.key=value", "--some.key=different value"]+ res <- getKey "some.key" c+ res `shouldBe` Just "different value"++ it "ignores values that don't start with the right prefix" $ do+ c <- mkConf ["some.key=value", "-some.key=value", "-Xsome.key=value", "some.key"]+ res <- getKey "some.key" c+ res `shouldBe` Nothing++ it "after encountering a -- it stops parsing parameters" $ do+ c <- mkConf ["--", "--some.key=value"]+ res <- getKey "some.key" c+ res `shouldBe` Nothing
+ test/Conferer/Source/EnvSpec.hs view
@@ -0,0 +1,41 @@+module Conferer.Source.EnvSpec where++import Test.Hspec+import qualified Data.Map as Map++import Conferer++fakeLookupEnv :: [(String, String)] -> LookupEnvFunc+fakeLookupEnv fakeEnv = \envName ->+ return $ Map.lookup envName $ Map.fromList fakeEnv++spec :: Spec+spec = do+ describe "with an env config" $ do+ let+ mkEnvConfig =+ emptyConfig+ & addSource+ (mkEnvSource'+ (fakeLookupEnv+ [ ("TMUX","/tmp/tmux-1000/default,2822,0")+ , ("TMUX_PANE","%1")+ , ("TMUX_PLUGIN_MANAGER_PATH","/home/user/.tmux/plugins/")+ ])+ "TMUX"+ )+ it "getting an existent key returns unwraps top level value (wihtout \+ \children)" $ do+ c <- mkEnvConfig+ res <- getKey "." c+ res `shouldBe` Just "/tmp/tmux-1000/default,2822,0"++ it "getting an existent key for a child gets that value" $ do+ c <- mkEnvConfig+ res <- getKey "pane" c+ res `shouldBe` Just "%1"++ it "keys should always be consistent as to how the words are separated" $ do+ c <- mkEnvConfig+ res <- getKey "pane" c+ res `shouldBe` Just "%1"
+ test/Conferer/Source/MappingSpec.hs view
@@ -0,0 +1,43 @@+module Conferer.Source.MappingSpec where++import Test.Hspec+import qualified Data.Map as Map+import Data.Function ((&))++import Conferer++spec :: Spec+spec = do+ describe "with a mapping source" $ do+ it "getting an existent key in the original map but that's not mapped in the \+ \wrapper doesn't exist" $ do+ c <- emptyConfig+ & addSource (mkMappingSource Map.empty+ $ mkMapSource [("some.key", "some value")])+ res <- getKey "some.key" c+ res `shouldBe` Nothing++ it "getting a non existent key isn't there" $ do+ c <- emptyConfig+ & addSource (mkMappingSource (Map.fromList [("k", "key")])+ $ mkMapSource [("key", "75")])++ res <- getKey "xxxx" c+ res `shouldBe` Nothing++ it "getting an existent key that's mapped but doesn't exist on the \+ \inner source isn't there" $ do+ c <- emptyConfig+ & addSource (mkMappingSource (Map.fromList [("another.key", "some.key")])+ $ mkMapSource [])++ res <- getKey "another.key" c+ res `shouldBe` Nothing++ it "getting an existent key that's mapped properly gets it and exists on \+ \the inner source gets it" $ do+ c <- emptyConfig+ & addSource (mkMappingSource (Map.fromList [("another.key", "some.key")])+ $ mkMapSource [("some.key", "some value")])+ res <- getKey "another.key" c+ res `shouldBe` Just "some value"
+ test/Conferer/Source/NamespacedSpec.hs view
@@ -0,0 +1,21 @@+module Conferer.Source.NamespacedSpec where++import Test.Hspec++import Conferer++spec :: Spec+spec = do+ describe "namespaced config" $ do+ it "return nothing if the key doesn't match" $ do+ c <- emptyConfig+ & addSource (mkNamespacedSource "postgres"+ $ mkMapSource [("url", "some url")])+ res <- getKey "url" c+ res `shouldBe` Nothing+ it "returns the wrapped value" $ do+ c <- emptyConfig+ & addSource (mkNamespacedSource "postgres"+ $ mkMapSource [("url", "some url")])+ res <- getKey "postgres.url" c+ res `shouldBe` Just "some url"
+ test/Conferer/Source/NullSpec.hs view
@@ -0,0 +1,13 @@+module Conferer.Source.NullSpec where++import Test.Hspec++import Conferer++spec :: Spec+spec = do+ it "always fails to get a key" $ do+ c <- emptyConfig+ & addSource mkNullSource+ res <- getKey "some.key" c+ res `shouldBe` Nothing
+ test/Conferer/Source/PropertiesFileSpec.hs view
@@ -0,0 +1,39 @@+module Conferer.Source.PropertiesFileSpec where++import Test.Hspec+import Data.Text (Text)+import qualified Data.Text as Text+import qualified Data.Map as Map++import Conferer+import Conferer.Core+import Conferer.Source.PropertiesFile++fakeLookupEnv :: [(String, String)] -> LookupEnvFunc+fakeLookupEnv fakeEnv = \envName ->+ return $ Map.lookup envName $ Map.fromList fakeEnv++spec :: Spec+spec = do+ describe "with a properties file config" $ do+ it "getting an existent key returns unwraps top level value (wihtout \+ \children)" $ do+ c <- mkStandaloneSource $ mkPropertiesFileSource' "some.key=a value"+ res <- getKeyInSource c "some.key"+ res `shouldBe` Just "a value"++ it "getting an existent key for a child gets that value" $ do+ c <- mkStandaloneSource $ mkPropertiesFileSource' $ Text.unlines+ [ "some.key=a value"+ , "some.key=b"+ ]+ res <- getKeyInSource c "some.key"+ res `shouldBe` Just "b"++ it "keys should always be consistent as to how the words are separated" $ do+ c <- mkStandaloneSource $ mkPropertiesFileSource' $ Text.unlines+ [ "some.key=a value"+ , "some.key=b"+ ]+ res <- getKeyInSource c "another.key"+ res `shouldBe` Nothing
+ test/Conferer/Source/SimpleSpec.hs view
@@ -0,0 +1,22 @@+module Conferer.Source.SimpleSpec where++import Test.Hspec++import Conferer++spec :: Spec+spec = do+ describe "json source" $ do+ let creator =+ emptyConfig+ & addSource (mkMapSource [ ("postgres.url", "some url")])++ it "getting a non existent key returns an empty config" $ do+ c <- creator+ res <- getKey "some.key" c+ res `shouldBe` Nothing++ it "getting an existent key returns unwraps the original map" $ do+ c <- creator+ res <- getKey "postgres.url" c+ res `shouldBe` Just "some url"
test/ConfererSpec.hs view
@@ -14,8 +14,8 @@ describe "with a config with a nested value" $ do let mkConfig = pure emptyConfig- >>= addProvider (mkMapProvider [ ("postgres.url", "some url")])- >>= addProvider (mkMapProvider [ ("postgres.url", "different url") , ("server.port", "4000")])+ >>= addSource (mkMapSource [ ("postgres.url", "some url")])+ >>= addSource (mkMapSource [ ("postgres.url", "different url") , ("server.port", "4000")]) it "getting a non existent key returns an empty config" $ do c <- mkConfig