{-# LANGUAGE NoImplicitPrelude #-} module System.Etc.Internal.Resolver.Env (resolveEnv, resolveEnvPure) where import RIO import qualified RIO.HashMap as HashMap import qualified RIO.Set as Set import qualified RIO.Text as Text import System.Environment (getEnvironment) import Control.Arrow ((***)) import qualified Data.Aeson as JSON import qualified System.Etc.Internal.Spec.Types as Spec import System.Etc.Internal.Types resolveEnvVarSource :: (Text -> Maybe Text) -> Bool -> Spec.ConfigSources cmd -> Maybe ConfigSource resolveEnvVarSource lookupEnv sensitive specSources = let toEnvSource varname envValue = envValue & JSON.String & boolToValue sensitive & 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 _ sensitive sources -> let updateConfig = do envSource <- resolveEnvVarSource lookupEnv sensitive 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