{-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE OverloadedStrings #-} module System.Etc.Internal.Resolver.Env (resolveEnv, resolveEnvPure) where import Protolude import System.Environment (getEnvironment) import Control.Arrow ((***)) import qualified Data.Aeson as JSON import qualified Data.HashMap.Strict as HashMap import qualified Data.Set as Set import qualified Data.Text as Text import qualified System.Etc.Internal.Spec.Types as Spec import System.Etc.Internal.Types resolveEnvVarSource :: (Text -> Maybe Text) -> Spec.ConfigSources cmd -> Maybe ConfigSource resolveEnvVarSource lookupEnv specSources = let toEnvSource varname envValue = envValue & JSON.String & Env varname in do varname <- Spec.envVar specSources toEnvSource varname <$> lookupEnv varname buildEnvVarResolver :: (Text -> Maybe Text) -> Spec.ConfigSpec cmd -> Maybe ConfigValue buildEnvVarResolver lookupEnv spec = let resolverReducer :: Text -> Spec.ConfigValue cmd -> Maybe ConfigValue -> Maybe ConfigValue resolverReducer specKey specValue mConfig = case specValue of Spec.ConfigValue _ sources -> let updateConfig = do envSource <- resolveEnvVarSource lookupEnv sources writeInSubConfig specKey (ConfigValue $ Set.singleton envSource) <$> mConfig in updateConfig <|> mConfig Spec.SubConfig specConfigMap -> let mSubConfig = specConfigMap & HashMap.foldrWithKey resolverReducer (Just emptySubConfig) & filterMaybe isEmptySubConfig updateConfig = writeInSubConfig specKey <$> mSubConfig <*> mConfig in updateConfig <|> mConfig in Spec.specConfigValues spec & HashMap.foldrWithKey resolverReducer (Just emptySubConfig) & filterMaybe isEmptySubConfig {-| Gathers all OS Environment Variable values (@env@ entries) from the @etc/spec@ entries inside a @ConfigSpec@. This version of the function gathers the input from a list of tuples rather than the OS. -} resolveEnvPure :: Spec.ConfigSpec cmd -- ^ ConfigSpec -> [(Text, Text)] -- ^ Environment Variable tuples -> Config -- ^ returns Configuration Map with Environment Variables values filled in resolveEnvPure spec envMap0 = let envMap = HashMap.fromList envMap0 lookupEnv key = HashMap.lookup key envMap in maybe (Config emptySubConfig) Config (buildEnvVarResolver lookupEnv spec) {-| Gathers all OS Environment Variable values (@env@ entries) from the @etc/spec@ entries inside a @ConfigSpec@. -} resolveEnv :: Spec.ConfigSpec cmd -- ^ Config Spec -> IO Config -- ^ returns Configuration Map with Environment Variables values filled in resolveEnv spec = let getEnvironmentTxt = map (Text.pack *** Text.pack) <$> getEnvironment in resolveEnvPure spec <$> getEnvironmentTxt