conferer 0.1.0.3 → 0.1.0.4
raw patch · 8 files changed
+134/−13 lines, 8 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
+ Conferer: defaultConfigWithDefaults :: Text -> [(Key, Text)] -> IO Config
+ Conferer: fetch :: FetchFromConfig a => Key -> Config -> IO (Either Text a)
+ Conferer: withDefaults :: [(Key, Text)] -> Config -> Config
+ Conferer.Core: withDefaults :: [(Key, Text)] -> Config -> Config
+ Conferer.Provider.PropertiesFile: lineToKeyValue :: Text -> Maybe (Key, Text)
+ Conferer.Provider.PropertiesFile: mkPropertiesFileProvider :: ProviderCreator
+ Conferer.Provider.PropertiesFile: mkPropertiesFileProvider' :: Text -> ProviderCreator
+ Conferer.Provider.Simple: mkPureMapProvider :: Map Key Text -> Provider
+ Conferer.Types: [defaults] :: Config -> Map Key Text
- Conferer.Types: Config :: [Provider] -> Config
+ Conferer.Types: Config :: [Provider] -> Map Key Text -> Config
Files
- conferer.cabal +4/−2
- src/Conferer.hs +15/−5
- src/Conferer/Core.hs +10/−3
- src/Conferer/Provider/Files.hs +1/−1
- src/Conferer/Provider/PropertiesFile.hs +54/−0
- src/Conferer/Provider/Simple.hs +8/−2
- src/Conferer/Types.hs +3/−0
- test/Conferer/Provider/PropertiesFileSpec.hs +39/−0
conferer.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 45fd44d5d84b2f4cd58f0b44ccd4cea950effce5e344718897c38433efc2764a+-- hash: 998c1dffa6a5fb2effd27e4a50c6b60f419580bc17d495a886912a829575eb93 name: conferer-version: 0.1.0.3+version: 0.1.0.4 synopsis: Configuration management library description: Library to abstract the parsing of many haskell config values from different config sources@@ -34,6 +34,7 @@ Conferer.Provider.Mapping Conferer.Provider.Namespaced Conferer.Provider.Null+ Conferer.Provider.PropertiesFile Conferer.Provider.Simple Conferer.Types other-modules:@@ -59,6 +60,7 @@ Conferer.Provider.MappingSpec Conferer.Provider.NamespacedSpec Conferer.Provider.NullSpec+ Conferer.Provider.PropertiesFileSpec Conferer.Provider.SimpleSpec ConfererSpec Paths_conferer
src/Conferer.hs view
@@ -71,6 +71,7 @@ module Conferer.Types , module Conferer.Core , defaultConfig+ , defaultConfigWithDefaults , Key(..) -- * Providers@@ -80,6 +81,7 @@ , module Conferer.Provider.Mapping , module Conferer.Provider.CLIArgs , module Conferer.Provider.Null+ , module Conferer.Provider.PropertiesFile -- * Re-Exports , (&) ) where@@ -87,22 +89,30 @@ import Data.Text (Text) import Data.Function ((&)) -import Conferer.Core (emptyConfig, addProvider, getFromConfig, getKey, unsafeGetKey, (/.))-import Conferer.Types (Config, Key(..), ProviderCreator, Provider(..), FetchFromConfig)+import Conferer.Core (emptyConfig, addProvider, getFromConfig, getKey, unsafeGetKey, (/.), withDefaults)+import Conferer.Types (Config, Key(..), ProviderCreator, Provider(..), FetchFromConfig(..)) 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 -- | Default config which reads from command line arguments, env vars and--- property files+-- property files defaultConfig :: Text -> IO Config-defaultConfig appName = do- pure emptyConfig+defaultConfig appName =+ defaultConfigWithDefaults appName []++-- | Default config which reads from command line arguments, env vars,+-- property files and some default key/values+defaultConfigWithDefaults :: Text -> [(Key, Text)] -> IO Config+defaultConfigWithDefaults appName configMap =+ pure (emptyConfig & withDefaults configMap) >>= addProvider (mkCLIArgsProvider) >>= addProvider (mkEnvProvider appName)+ >>= addProvider (mkPropertiesFileProvider)
src/Conferer/Core.hs view
@@ -2,8 +2,11 @@ import Data.Text (Text) import qualified Data.Text as Text+import Data.Map (Map)+import qualified Data.Map as Map import Data.Either (either) +import Conferer.Provider.Simple import Conferer.Types -- | Most Basic function to interact directly with a 'Config'. It always returns@@ -11,7 +14,7 @@ -- providers inside the 'Config'. getKey :: Key -> Config -> IO (Either Text Text) getKey k config =- go $ providers config+ go $ providers config ++ [mkPureMapProvider (defaults config)] where go [] = return $ Left ("Key '" `Text.append` keyName k `Text.append` "' was not found") go (provider:providers) = do@@ -36,8 +39,12 @@ -- | The empty configuration, this 'Config' is used as the base for -- most config creating functions. emptyConfig :: Config-emptyConfig = Config []+emptyConfig = Config [] Map.empty +withDefaults :: [(Key, Text)] -> Config -> Config+withDefaults configMap config =+ config { defaults = Map.fromList configMap }+ -- | Instantiate a 'ProviderCreator' using the 'emptyConfig' mkStandaloneProvider :: ProviderCreator -> IO Provider mkStandaloneProvider mkProvider =@@ -50,7 +57,7 @@ addProvider mkProvider config = do newProvider <- mkProvider config return $- Config+ config { providers = providers config ++ [ newProvider ] }
src/Conferer/Provider/Files.hs view
@@ -11,7 +11,7 @@ getFilePathFromEnv :: Config -> String -> IO FilePath getFilePathFromEnv config extension = do- env <- fromRight "dev" <$> fetch "env" config+ env <- fromRight "development" <$> fetch "env" config return $ mconcat [ "config/" , Text.unpack env
+ src/Conferer/Provider/PropertiesFile.hs view
@@ -0,0 +1,54 @@+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 view
@@ -6,6 +6,7 @@ -- utility mkMapProvider , mkMapProvider'+ , mkPureMapProvider ) where import Data.Map (Map)@@ -14,10 +15,15 @@ import Conferer.Types --- | Make a 'Provider' from a 'Map'+-- | Make a 'ProviderCreator' from a 'Map' mkMapProvider' :: Map Key Text -> ProviderCreator mkMapProvider' configMap _config =- return $ Provider+ 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
src/Conferer/Types.hs view
@@ -4,6 +4,8 @@ import Data.String import Data.Text (Text) import qualified Data.Text as Text+import Data.Map (Map)+import qualified Data.Map as Map -- | Core interface for library provided configuration, basically consists of -- getting a 'Key' and informing returning a maybe signaling the value and@@ -28,6 +30,7 @@ data Config = Config { providers :: [Provider]+ , defaults :: Map Key Text } -- | The type for creating a provider given a 'Config', some providers require a
+ test/Conferer/Provider/PropertiesFileSpec.hs view
@@ -0,0 +1,39 @@+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