{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE FlexibleContexts #-}
module Conferer.Core where
import Data.Text (Text)
import qualified Data.Text as Text
import Data.Map (Map)
import qualified Data.Map as Map
import Data.Maybe (fromMaybe)
import Data.Typeable (Typeable, Proxy(..), typeRep)
import Control.Exception (try, throw, throwIO, evaluate)
import Conferer.Source.Simple
import Conferer.Types
getKey :: Key -> Config -> IO (Maybe Text)
getKey k config =
go $ sources config ++ [mkPureMapSource (defaults config)]
where
go [] = return Nothing
go (source:sources) = do
res <- getKeyInSource source k
case res of
Just t -> return $ Just t
Nothing -> go sources
getFromConfig :: forall a. (Typeable a, FromConfig a, DefaultConfig a) => Key -> Config -> IO a
getFromConfig key config =
getFromConfigWithDefault key config configDef
getFromRootConfig :: forall a. (Typeable a, FromConfig a, DefaultConfig a) => Config -> IO a
getFromRootConfig config =
getFromConfig "" config
getFromConfigWithDefault :: forall a. (Typeable a, FromConfig a) => Key -> Config -> a -> IO a
getFromConfigWithDefault key config configDefault =
safeGetFromConfigWithDefault key config configDefault
>>= \case
Just value -> do
evaluate value
Nothing ->
throwIO $ FailedToFetchError key (typeRep (Proxy :: Proxy a))
safeGetFromConfig :: forall a. (Typeable a, FromConfig a, DefaultConfig a) => Key -> Config -> IO (Maybe a)
safeGetFromConfig key config =
safeGetFromConfigWithDefault key config configDef
safeGetFromConfigWithDefault :: forall a. (Typeable a, FromConfig a) => Key -> Config -> a -> IO (Maybe a)
safeGetFromConfigWithDefault key config configDefault = do
totalValue <- evaluate =<< fetchFromConfig key config
case totalValue of
Just value -> do
Just <$> evaluate value
Nothing -> do
result :: Either FailedToFetchError a <- try . (evaluate =<<) . updateFromConfig key config $ configDefault
case result of
Right a -> Just <$> evaluate a
Left e -> return Nothing
(/.) :: Key -> Key -> Key
parent /. child = Path (unKey parent ++ unKey child)
emptyConfig :: Config
emptyConfig = Config [] Map.empty
withDefaults :: [(Key, Text)] -> Config -> Config
withDefaults configMap config =
config { defaults = Map.fromList configMap }
mkStandaloneSource :: SourceCreator -> IO Source
mkStandaloneSource mkSource =
mkSource emptyConfig
addSource :: SourceCreator -> Config -> IO Config
addSource mkSource config = do
newSource <- mkSource config
return $
config
{ sources = sources config ++ [ newSource ]
}
unsafeGetKey :: Key -> Config -> IO Text
unsafeGetKey key config =
fromMaybe (throw $ FailedToFetchError key (typeRep (Proxy :: Proxy Text)))
<$> getKey key config