module LoadEnv
( loadEnv
, loadEnvFrom
, loadEnvFromAbsolute
) where
import Control.Monad (unless, (<=<))
import Data.Bool (bool)
import Data.Foldable (for_, traverse_)
import Data.List (inits)
import Data.Maybe (isJust)
import LoadEnv.Parse
import System.Directory
(doesFileExist, findFile, getCurrentDirectory, makeAbsolute)
import System.Environment (lookupEnv, setEnv)
import System.FilePath (isRelative, joinPath, splitDirectories)
import Text.Parsec.String (parseFromFile)
loadEnv :: IO ()
loadEnv :: IO ()
loadEnv = FilePath -> IO ()
loadEnvFrom FilePath
".env"
loadEnvFrom :: FilePath -> IO ()
loadEnvFrom :: FilePath -> IO ()
loadEnvFrom FilePath
name = do
Maybe FilePath
mFile <- if FilePath -> Bool
isRelative FilePath
name
then ([FilePath] -> FilePath -> IO (Maybe FilePath))
-> FilePath -> [FilePath] -> IO (Maybe FilePath)
forall a b c. (a -> b -> c) -> b -> a -> c
flip [FilePath] -> FilePath -> IO (Maybe FilePath)
findFile FilePath
name ([FilePath] -> IO (Maybe FilePath))
-> (FilePath -> [FilePath]) -> FilePath -> IO (Maybe FilePath)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> [FilePath]
takeDirectories (FilePath -> IO (Maybe FilePath))
-> IO FilePath -> IO (Maybe FilePath)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO FilePath
getCurrentDirectory
else Maybe FilePath -> Maybe FilePath -> Bool -> Maybe FilePath
forall a. a -> a -> Bool -> a
bool Maybe FilePath
forall a. Maybe a
Nothing (FilePath -> Maybe FilePath
forall a. a -> Maybe a
Just FilePath
name) (Bool -> Maybe FilePath) -> IO Bool -> IO (Maybe FilePath)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> FilePath -> IO Bool
doesFileExist FilePath
name
Maybe FilePath -> (FilePath -> IO ()) -> IO ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ Maybe FilePath
mFile ((FilePath -> IO ()) -> IO ()) -> (FilePath -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \FilePath
file -> do
Either ParseError Environment
result <- Parser Environment
-> FilePath -> IO (Either ParseError Environment)
forall a. Parser a -> FilePath -> IO (Either ParseError a)
parseFromFile Parser Environment
parseEnvironment FilePath
file
(ParseError -> IO ())
-> (Environment -> IO ()) -> Either ParseError Environment -> IO ()
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either ParseError -> IO ()
forall a. Show a => a -> IO ()
print (((FilePath, FilePath) -> IO ()) -> Environment -> IO ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
(a -> f b) -> t a -> f ()
traverse_ (((FilePath, FilePath) -> IO ()) -> Environment -> IO ())
-> ((FilePath, FilePath) -> IO ()) -> Environment -> IO ()
forall a b. (a -> b) -> a -> b
$ (FilePath -> FilePath -> IO ()) -> (FilePath, FilePath) -> IO ()
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry FilePath -> FilePath -> IO ()
defaultEnv) Either ParseError Environment
result
defaultEnv :: String -> String -> IO ()
defaultEnv :: FilePath -> FilePath -> IO ()
defaultEnv FilePath
k FilePath
v = do
Bool
exists <- Maybe FilePath -> Bool
forall a. Maybe a -> Bool
isJust (Maybe FilePath -> Bool) -> IO (Maybe FilePath) -> IO Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> FilePath -> IO (Maybe FilePath)
lookupEnv FilePath
k
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless Bool
exists (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ FilePath -> FilePath -> IO ()
setEnv FilePath
k FilePath
v
loadEnvFromAbsolute :: FilePath -> IO ()
loadEnvFromAbsolute :: FilePath -> IO ()
loadEnvFromAbsolute = FilePath -> IO ()
loadEnvFrom (FilePath -> IO ())
-> (FilePath -> IO FilePath) -> FilePath -> IO ()
forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< FilePath -> IO FilePath
makeAbsolute
takeDirectories :: FilePath -> [FilePath]
takeDirectories :: FilePath -> [FilePath]
takeDirectories = ([FilePath] -> FilePath) -> [[FilePath]] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map [FilePath] -> FilePath
joinPath ([[FilePath]] -> [FilePath])
-> (FilePath -> [[FilePath]]) -> FilePath -> [FilePath]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[FilePath]] -> [[FilePath]]
forall a. [a] -> [a]
reverse ([[FilePath]] -> [[FilePath]])
-> (FilePath -> [[FilePath]]) -> FilePath -> [[FilePath]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> [[FilePath]] -> [[FilePath]]
forall a. Int -> [a] -> [a]
drop Int
1 ([[FilePath]] -> [[FilePath]])
-> (FilePath -> [[FilePath]]) -> FilePath -> [[FilePath]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [FilePath] -> [[FilePath]]
forall a. [a] -> [[a]]
inits ([FilePath] -> [[FilePath]])
-> (FilePath -> [FilePath]) -> FilePath -> [[FilePath]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> [FilePath]
splitDirectories