module Configuration.Dotenv.Scheme
( checkConfig
, loadSafeFile
, runSchemaChecker
)
where
import Control.Monad
import Control.Monad.IO.Class (MonadIO(..))
import Data.Yaml (decodeFileEither, prettyPrintParseException)
import Text.Megaparsec
import System.Directory (doesFileExist)
import Configuration.Dotenv (loadFile)
import Configuration.Dotenv.Types (Config(..))
import Configuration.Dotenv.Scheme.Helpers
import Configuration.Dotenv.Scheme.Parser
import Configuration.Dotenv.Scheme.Types
loadSafeFile
:: MonadIO m
=> FilePath
-> Config
-> m [(String, String)]
loadSafeFile schemaFile config = do
envs <- loadFile config
liftIO (readScheme schemaFile >>= checkConfig envs)
return envs
readScheme :: FilePath -> IO [Env]
readScheme schemeFile = do
eitherEnvConf <- decodeFileEither schemeFile
case eitherEnvConf of
Right envConfs -> return envConfs
Left errorYaml -> error (prettyPrintParseException errorYaml)
checkConfig
:: [(String, String)]
-> [Env]
-> IO ()
checkConfig envvars envsWithType =
let prettyParsedErrors = unlines . fmap parseErrorTextPretty
envsTypeAndValue = joinEnvs envsWithType envvars
valuesAndTypes = matchValueAndType envsTypeAndValue
dotenvsMissing = filter required (missingDotenvs envsWithType envsTypeAndValue)
schemeEnvsMissing = missingSchemeEnvs envvars envsTypeAndValue
in do
unless (null dotenvsMissing)
(error $ "The following envs: "
++ showMissingDotenvs dotenvsMissing
++ " must be in the dotenvs")
unless (null schemeEnvsMissing)
(error $ "The following envs: "
++ showMissingSchemeEnvs schemeEnvsMissing
++ " must be in your scheme.yml")
case parseEnvsWithScheme valuesAndTypes of
Left errors -> error (prettyParsedErrors errors)
_ -> return ()
runSchemaChecker
:: FilePath
-> Config
-> IO ()
runSchemaChecker schemeFile config = do
exists <- doesFileExist schemeFile
when exists
(void $ loadSafeFile schemeFile config)