packages feed

dotenv 0.8.0.7 → 0.9.0.0

raw patch · 17 files changed

+41/−687 lines, 17 filesdep −voiddep −yamldep ~basePVP ok

version bump matches the API change (PVP)

Dependencies removed: void, yaml

Dependency ranges changed: base

API changes (from Hackage documentation)

- Configuration.Dotenv: defaultValidatorMap :: ValidatorMap
- Configuration.Dotenv: loadSafeFile :: MonadIO m => ValidatorMap -> FilePath -> Config -> m [(String, String)]
- Configuration.Dotenv: type ValidatorMap = Map Text (Text -> Bool)

Files

CHANGELOG.md view
@@ -1,4 +1,14 @@ ## MASTER++## Dotenv 0.9.0.0+* Remove `loadSafeFile`. Users must create their own parsers to convert the+read values from `System.Environment` to another data type. Therefore,+`loadSafeFile` won't be needed. We'll remove this functionality to reduce+dependencies.++## Dotenv 0.8.1.0+* Correct bounds for base. GHC support for versions older than 8.0 was dropped.+ ## Dotenv 0.8.0.7 * Allow megaparsec-0.9.0.0 
README.md view
@@ -1,4 +1,4 @@-[![Build Status](https://travis-ci.org/stackbuilders/dotenv-hs.svg?branch=master)](https://travis-ci.org/stackbuilders/dotenv-hs) [![Hackage](https://img.shields.io/hackage/v/dotenv.svg)](http://hackage.haskell.org/package/dotenv)+[![Build Status](https://github.com/stackbuilders/dotenv-hs/actions/workflows/build-and-test.yml/badge.svg)](https://github.com/stackbuilders/dotenv-hs/actions/workflows/build-and-test.yml) [![Hackage](https://img.shields.io/hackage/v/dotenv.svg)](http://hackage.haskell.org/package/dotenv)  # Dotenv files for Haskell @@ -80,46 +80,6 @@ postgres://myusername@localhost/database ``` -### Type checking envs-Env variables are simple strings. However, they can represent other types like-integers, booleans, IP addresses, emails, URIs, and so on. We provide an interface-that performs type checking after loading the envs and before running your application.-If the type-check succeeded the application is executed, otherwise you will get an-error with the types that mismatch.--In order to use this functionality you can use the `loadSafeFile` which takes the same-configuration value as the `loadFile` function. Also, you need to have a `.schema.yml`-in your current directory. This file must have the following structure:--```yaml-- name: DOTENV-  type: bool-  required: true-- name: OTHERENV-  type: bool-- name: PORT-  type: integer-  required: true-- name: TOKEN-  type: text-  required: false-```--It is a list of type and envs. So, in this example, `DOTENV` must have a value-of `true` or `false` otherwise it won't be parsed as a boolean value. And envs-like `PORT` must be any integer. Currently, we are supporting the following types:--- `bool` - Accepts values `false` or `true`-- `integer` - Accepts values of possitive integers-- `text` - Any text--**require** specifies if the env var is obligatory or not. In case you set it to true-but do not provide it, you wil get an exception. When **required** is omited, the default-value is `false`.--**NOTE:** All the variables which are **required** in the `schema.yml` must be defined-in the dotenvs.- ## Configuration  The first argument to `loadFile` specifies the configuration. You cans use@@ -211,29 +171,6 @@ current environment settings. By invoking the program `env` in place of `myprogram` above you can see what the environment will look like after evaluating multiple Dotenv files.--The `--schema FILE` will get the envs configuration from the `FILE`. For instance:--```shell-$ cat .env-PORT=123a-$ cat .schema.yml-- name: PORT-  required: true-  type: integer-```--running `dotenv` will throw:--```shell-$ dotenv -s .schema.yml "echo $PORT"-dotenv: 1:4:-unexpected 'a'-expecting digit or end of input-```--**NOTE:** The flag can be omited when the `.schema.yml` is in the current working-directory. To disable type checking add the flag `--no-schema`.  ## Author 
app/Main.hs view
@@ -3,25 +3,20 @@  module Main where -import Data.Version (showVersion)-#if MIN_VERSION_optparse_applicative(0,13,0)-import Data.Monoid ((<>))+import           Data.Version         (showVersion)+#if !MIN_VERSION_base(4,13,0)+import           Data.Monoid          ((<>)) #endif -import Options.Applicative-import Paths_dotenv (version)+import           Options.Applicative+import           Paths_dotenv         (version) -import Control.Monad (void, unless)+import           Control.Monad        (void) -import Configuration.Dotenv-  (Config(..)-  , loadFile-  , loadSafeFile-  , defaultConfig-  , defaultValidatorMap)+import           Configuration.Dotenv (Config (..), defaultConfig, loadFile) -import System.Process (system)-import System.Exit (exitWith)+import           System.Exit          (exitWith)+import           System.Process       (system)  data Options = Options   { dotenvFiles        :: [String]@@ -29,8 +24,6 @@   , override           :: Bool   , program            :: String   , args               :: [String]-  , schemaFile         :: FilePath-  , disableSchema      :: Bool   } deriving (Show)  main :: IO ()@@ -47,8 +40,6 @@           }    in do      void $ loadFile configDotenv-     unless disableSchema-       (void $ loadSafeFile defaultValidatorMap schemaFile configDotenv)      system (program ++ concatMap (" " ++) args) >>= exitWith        where          opts = info (helper <*> versionOption <*> config)@@ -80,10 +71,3 @@      <*> argument str (metavar "PROGRAM")       <*> many (argument str (metavar "ARG"))--     <*> strOption ( long "schema"-                      <> short 's'-                      <> help "Set the file path for the schema.yml file"-                      <> value ".schema.yml" )--     <*> switch ( long "no-schema" <> help "Omit type checking" )
dotenv.cabal view
@@ -1,5 +1,5 @@ name:                dotenv-version:             0.8.0.7+version:             0.9.0.0 synopsis:            Loads environment variables from dotenv files homepage:            https://github.com/stackbuilders/dotenv-hs description:@@ -49,8 +49,6 @@ data-files:   .dotenv   .dotenv.example-  .scheme.yml-  .dotenv.safe  flag static   description:        Creates static binary.@@ -64,15 +62,14 @@  executable dotenv   main-is:             Main.hs-  build-depends:         base >=4.7 && <5.0+  build-depends:         base >= 4.9 && < 5.0                        , base-compat >= 0.4                        , dotenv-                       , optparse-applicative >=0.11 && < 0.17+                       , optparse-applicative >= 0.11 && < 0.17                        , megaparsec                        , process                        , text-                       , transformers >=0.4 && < 0.6-                       , yaml >= 0.8+                       , transformers >= 0.4 && < 0.6   other-modules: Paths_dotenv    hs-source-dirs:      app@@ -92,12 +89,8 @@                       , Configuration.Dotenv.ParsedVariable                       , Configuration.Dotenv.Text                       , Configuration.Dotenv.Types-                      , Configuration.Dotenv.Scheme-                      , Configuration.Dotenv.Scheme.Helpers-                      , Configuration.Dotenv.Scheme.Parser-                      , Configuration.Dotenv.Scheme.Types -  build-depends:         base >=4.7 && <5.0+  build-depends:         base >= 4.9 && < 5.0                        , base-compat >= 0.4                        , directory                        , megaparsec >= 7.0.1 && < 10.0@@ -106,11 +99,7 @@                        , text                        , transformers >=0.4 && < 0.6                        , exceptions >= 0.8 && < 0.11-                       , yaml >= 0.8 -  if !impl(ghc >= 7.10)-    build-depends:      void         == 0.7.*-   hs-source-dirs:      src   ghc-options:         -Wall   if flag(dev)@@ -132,14 +121,8 @@                        , Configuration.Dotenv.Types                        , Configuration.Dotenv.Parse                        , Configuration.Dotenv.ParsedVariable-                       , Configuration.Dotenv.SchemeSpec-                       , Configuration.Dotenv.Scheme.ParseSpec-                       , Configuration.Dotenv.Scheme-                       , Configuration.Dotenv.Scheme.Helpers-                       , Configuration.Dotenv.Scheme.Parser-                       , Configuration.Dotenv.Scheme.Types -  build-depends:       base >=4.7 && <5.0+  build-depends:       base >= 4.9 && < 5.0                      , base-compat >= 0.4                      , containers                      , dotenv@@ -148,13 +131,11 @@                      , hspec                      , process                      , text-                     , transformers >=0.4 && < 0.6+                     , transformers >= 0.4 && < 0.6                      , exceptions >= 0.8 && < 0.11                      , hspec-megaparsec >= 2.0 && < 3.0-                     , yaml >= 0.8 -  if !impl(ghc >= 7.10)-    build-depends:      void         == 0.7.*+  build-tools:        hspec-discover   >= 2.0 && < 3.0    if flag(dev)     ghc-options:      -Wall -Werror
− spec/Configuration/Dotenv/Scheme/ParseSpec.hs
@@ -1,35 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}--{-# OPTIONS_GHC -fno-warn-orphans #-}--module Configuration.Dotenv.Scheme.ParseSpec (spec) where--import Data.Yaml (decodeFileEither)-import Test.Hspec--import Configuration.Dotenv.Scheme.Types---- | Extract Right from Either----fromRight :: (Show a, Show b) => Either a b -> b-fromRight (Right v) = v-fromRight (Left v) = error ("Left " ++ show v ++ " constructor instead" )---- |----spec :: Spec-spec =-  describe "parse a config env file" $-    it "parses the env config values from a file" $-      let expected :: [Env]-          expected =-            [ Env "DOTENV" (EnvType "bool") True-            , Env "OTHERENV" (EnvType "bool") False-            , Env "PORT" (EnvType "integer") True-            , Env "TOKEN" (EnvType "integer") False-            , Env "URL" (EnvType "text") True-            , Env "TWO" (EnvType "twoLetters") False-            ]-       in do-         actual <- decodeFileEither "spec/fixtures/.scheme.yml"-         fromRight actual `shouldBe` expected
− spec/Configuration/Dotenv/SchemeSpec.hs
@@ -1,84 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}--module Configuration.Dotenv.SchemeSpec (spec) where--import Configuration.Dotenv.Scheme-import Configuration.Dotenv.Scheme.Types-import Control.Exception (evaluate)--import Test.Hspec---- |----spec :: Spec-spec = do-  describe "checkScheme" $ do-    context "when the env configs are unique" $-      it "should succeed the check" $-        let schemeEnvs =-              [ Env "FOO" (EnvType "bool") True-              , Env "BAR" (EnvType "integer") True-              ]-         in checkScheme schemeEnvs `shouldBe` schemeEnvs--    context "when there are duplicated env configs" $-      it "should fail the check" $-        let schemeEnvs =-              [ Env "FOO" (EnvType "bool") True-              , Env "BAR" (EnvType "integer") True-              , Env "FOO" (EnvType "integer") True-              ]-            msg = "Duplicated env variable configuration in schema: FOO"-         in evaluate (checkScheme schemeEnvs) `shouldThrow` errorCall msg--  describe "checkConfig" $-    context "when the envs have the correct type" $ do-      context "when the envs in the dotenvs are defined in the scheme" $ do-        context "when the required envs are defined" $-          it "should succeed the type check" $-            let schemeEnvs =-                    [ Env "FOO" (EnvType "bool") True-                    , Env "BAR" (EnvType "integer") False-                    ]-                dotenvs = [("FOO","True"), ("BAR","123")]-             in checkConfig defaultValidatorMap dotenvs schemeEnvs `shouldReturn` ()--        context "when the not required envs are missing" $-          it "should succeed the type check" $-            let schemeEnvs =-                    [ Env "FOO" (EnvType "bool") True-                    , Env "BAR" (EnvType "integer") False-                    ]-                dotenvs = [("FOO","True")]-             in checkConfig defaultValidatorMap dotenvs schemeEnvs `shouldReturn` ()--        context "when the required envs are missing" $-          it "should fail before the type check" $-            let schemeEnvs =-                    [ Env "FOO" (EnvType "bool") True-                    , Env "BAR" (EnvType "integer") False-                    ]-                dotenvs = [("BAR","123")]-                msg = "The following envs: FOO must be in the dotenvs"-              in checkConfig defaultValidatorMap dotenvs schemeEnvs `shouldThrow` errorCall msg--      context "when there are missing dotenvs in the scheme" $-        it "should fail before type checking" $-          let schemeEnvs =-                  [ Env "FOO" (EnvType "bool") True-                  , Env "BAR" (EnvType "integer") False-                  ]-              dotenvs = [("FOO","True"), ("BAR","123"), ("BAZ","text")]-              msg = "The following envs: BAZ must be in your scheme.yml"-           in checkConfig defaultValidatorMap dotenvs schemeEnvs `shouldThrow` errorCall msg--      context "when there are missing scheme envs in the dotenv vars" $-        it "should fail before type checking" $-          let schemeEnvs =-                  [ Env "FOO" (EnvType "bool") True-                  , Env "BAZ" (EnvType "text") True-                  , Env "BAR" (EnvType "integer") False-                  ]-              dotenvs = [("FOO","True"), ("BAR","123")]-              msg = "The following envs: BAZ must be in the dotenvs"-           in checkConfig defaultValidatorMap dotenvs schemeEnvs `shouldThrow` errorCall msg
spec/Configuration/DotenvSpec.hs view
@@ -1,38 +1,20 @@-{-# LANGUAGE CPP #-}+{-# LANGUAGE CPP               #-} {-# LANGUAGE OverloadedStrings #-}  module Configuration.DotenvSpec (main, spec) where -import Configuration.Dotenv.Types (Config(..))-import Configuration.Dotenv.Environment-  ( getEnvironment-  , lookupEnv-  , setEnv-  , unsetEnv-  )-import Configuration.Dotenv-  ( load-  , loadFile-  , loadSafeFile-  , parseFile-  , onMissingFile-  )+import           Configuration.Dotenv             (load, loadFile,+                                                   onMissingFile, parseFile)+import           Configuration.Dotenv.Environment (getEnvironment, lookupEnv,+                                                   setEnv, unsetEnv)+import           Configuration.Dotenv.Types       (Config (..))  -import Test.Hspec--import System.Process (readCreateProcess, shell)-import Control.Monad (liftM, void)-import Data.Maybe (fromMaybe)-import qualified Data.Text as T-import qualified Data.Map.Lazy as M-#if !MIN_VERSION_base(4,8,0)-import Data.Functor ((<$>))-#endif+import           Test.Hspec -#if !MIN_VERSION_base(4,8,0)-import Control.Applicative ((<$))-#endif+import           Control.Monad                    (liftM, void)+import           Data.Maybe                       (fromMaybe)+import           System.Process                   (readCreateProcess, shell)  main :: IO () main = hspec spec@@ -106,45 +88,6 @@           lookupEnv "DOTENV" `shouldReturn` Just "true"           lookupEnv "UNICODE_TEST" `shouldReturn` Just "Manabí"           lookupEnv "ANOTHER_ENV" `shouldReturn` Just "hello"--  describe "loadSafeFile" $ after_ clearEnvs $-    context "given a custom map" $ do-      context "when the envs are written accordingly to the rules in the map" $-        it "should validate accordingly to the rules in the custom map" $-          let hasTwoLetters text = T.length text == 2-              customMap = M.fromList-                [ ("twoLetters", hasTwoLetters)-                , ("bool", const True)-                , ("text", const True)-                , ("integer", const True)-                ]-              schemaFile = "spec/fixtures/.scheme.yml"-              config = Config ["spec/fixtures/.dotenv.safe"] [] False-              expectedEnvs =-                [ ("DOTENV","true")-                , ("OTHERENV","false")-                , ("PORT","8000")-                , ("URL","http://example.com")-                , ("TWO","xD")-                ]-           in do-             envs <- loadSafeFile customMap schemaFile config-             envs `shouldMatchList` expectedEnvs--      context "when the envs are written in an unexpected way" $-        it "should throw an errorCall" $-          let unexpectedFormat text = T.length text == 3-              customMap = M.fromList-                [ ("twoLetters", unexpectedFormat)-                , ("bool", const True)-                , ("text", const True)-                , ("integer", const True)-                ]-              schemaFile = "spec/fixtures/.scheme.yml"-              config = Config ["spec/fixtures/.dotenv.safe"] [] False-           in void $ loadSafeFile customMap schemaFile config-                `shouldThrow` anyErrorCall-    describe "parseFile" $ after_ clearEnvs $ do     it "returns variables from a file without changing the environment" $ do
− spec/fixtures/.dotenv.safe
@@ -1,5 +0,0 @@-DOTENV=true-OTHERENV=false-PORT=8000-URL=http://example.com-TWO=xD
− spec/fixtures/.scheme.yml
@@ -1,16 +0,0 @@-- name: DOTENV-  type: bool-  required: true-- name: OTHERENV-  type: bool-  required: false-- name: PORT-  type: integer-  required: true-- name: TOKEN-  type: integer-- name: URL-  type: text-  required: true-- name: TWO-  type: twoLetters
src/Configuration/Dotenv.hs view
@@ -16,13 +16,10 @@   -- * Dotenv Load Functions     load   , loadFile-  , loadSafeFile   , parseFile   , onMissingFile   -- * Dotenv Types   , module Configuration.Dotenv.Types-  , ValidatorMap-  , defaultValidatorMap   )  where @@ -30,17 +27,13 @@                                                       setEnv) import           Configuration.Dotenv.Parse          (configParser) import           Configuration.Dotenv.ParsedVariable (interpolateParsedVariables)-import           Configuration.Dotenv.Scheme-import           Configuration.Dotenv.Scheme.Types   (ValidatorMap,-                                                      defaultValidatorMap) import           Configuration.Dotenv.Types          (Config (..),                                                       defaultConfig)-import           Control.Monad                       (liftM, when)+import           Control.Monad                       (liftM) import           Control.Monad.Catch import           Control.Monad.IO.Class              (MonadIO (..)) import           Data.List                           (intersectBy, union,                                                       unionBy)-import           System.Directory                    (doesFileExist) import           System.IO.Error                     (isDoesNotExistError) import           Text.Megaparsec                     (errorBundlePretty, parse) @@ -112,18 +105,3 @@   -> m a               -- ^ Action to perform if file is indeed missing   -> m a onMissingFile f h = catchIf isDoesNotExistError f (const h)---- | @loadSafeFile@ parses the /.scheme.yml/ file and will perform the type checking--- of the environment variables in the /.env/ file.-loadSafeFile-  :: MonadIO m-  => ValidatorMap -- ^ Map with custom validations-  -> FilePath -- ^ Filepath for schema file-  -> Config -- ^ Dotenv configuration-  -> m [(String, String)] -- ^ Environment variables loaded-loadSafeFile mapFormat schemaFile config = do-  envs <- loadFile config-  exists <- liftIO $ doesFileExist schemaFile-  when exists $-    liftIO (readScheme schemaFile >>= checkConfig mapFormat envs . checkScheme)-  return envs
src/Configuration/Dotenv/Environment.hs view
@@ -8,20 +8,10 @@   ) where  #if MIN_VERSION_base(4,11,0)-import System.Environment.Blank (getEnvironment, unsetEnv)+import System.Environment.Blank (getEnvironment, getEnv, unsetEnv) import qualified System.Environment.Blank as Blank #else-#if MIN_VERSION_base(4,7,0)-import System.Environment (getEnvironment, setEnv, unsetEnv)-#else-import System.Environment.Compat (getEnvironment, setEnv, unsetEnv)-#endif-#endif--#if MIN_VERSION_base(4,11,0)-import System.Environment.Blank (getEnv)-#else-import System.Environment (lookupEnv)+import System.Environment (getEnvironment, lookupEnv, setEnv, unsetEnv) #endif  #if MIN_VERSION_base(4,11,0)
src/Configuration/Dotenv/Parse.hs view
@@ -12,18 +12,12 @@ -- information on the dotenv format can be found in the project README and the -- test suite. -{-# LANGUAGE CPP               #-} {-# LANGUAGE OverloadedStrings #-}  module Configuration.Dotenv.Parse (configParser) where  import           Configuration.Dotenv.ParsedVariable-#if MIN_VERSION_base(4,8,0) import           Control.Applicative                 (empty, many, some, (<|>))-#else-import           Control.Applicative                 (empty, many, some, (*>),-                                                      (<$>), (<*), (<*>), (<|>))-#endif import           Control.Monad                       (void) import           Data.Void                           (Void) import           Text.Megaparsec                     (Parsec, anySingle,@@ -121,11 +115,5 @@ -- | Skip line comment and stop before newline character without consuming -- it. skipLineComment :: Parser ()-#if MIN_VERSION_megaparsec(5,1,0) skipLineComment = L.skipLineComment "#"-#else-skipLineComment = p >> void (manyTill anyChar n)-  where p = string "#"-        n = lookAhead (void newline) <|> eof-#endif {-# INLINE skipLineComment #-}
src/Configuration/Dotenv/ParsedVariable.hs view
@@ -9,8 +9,6 @@ -- -- Helpers to interpolate environment variables -{-# LANGUAGE CPP #-}- module Configuration.Dotenv.ParsedVariable (ParsedVariable(..),                                             VarName,                                             VarValue(..),@@ -20,9 +18,6 @@  import           Configuration.Dotenv.Environment (lookupEnv) import           Control.Monad                    (foldM)-#if !MIN_VERSION_base(4,8,0)-import           Data.Functor                     ((<$>))-#endif import           Control.Applicative              ((<|>)) import           System.Process                   (readCreateProcess, shell) 
− src/Configuration/Dotenv/Scheme.hs
@@ -1,70 +0,0 @@--- |--- Module      :  Configuration.Dotenv.Types--- Copyright   :  © 2015–2020 Stack Builders Inc.--- License     :  MIT------ Maintainer  :  Stack Builders <hackage@stackbuilders.com>--- Stability   :  experimental--- Portability :  portable------ Helpers for loadSafeFile--module Configuration.Dotenv.Scheme-  ( checkConfig-  , checkScheme-  , readScheme-  )-  where--import           Control.Monad--import           Data.List-import           Data.Yaml                           (decodeFileEither,-                                                      prettyPrintParseException)--import           Configuration.Dotenv.Scheme.Helpers-import           Configuration.Dotenv.Scheme.Parser-import           Configuration.Dotenv.Scheme.Types--readScheme :: FilePath -> IO [Env]-readScheme schemeFile = do-  eitherEnvConf <- decodeFileEither schemeFile-  case eitherEnvConf of-    Right envConfs -> return envConfs-    Left errorYaml -> error (prettyPrintParseException errorYaml)--checkScheme :: [Env] -> [Env]-checkScheme envConfs =-  case duplicatedConfs of-    []   -> envConfs-    dups -> error (duplicatedConfErrorMsg $ uniqueConfs dups)-  where-    duplicatedConfs  = deleteFirstsBy confEquals envConfs (uniqueConfs envConfs)-    uniqueConfs      = nubBy confEquals-    a `confEquals` b = envName a == envName b--duplicatedConfErrorMsg :: [Env] -> String-duplicatedConfErrorMsg = ("Duplicated env variable configuration in schema: " ++) . showMissingDotenvs--checkConfig-  :: ValidatorMap-  -> [(String, String)]-  -> [Env]-  -> IO ()-checkConfig mapFormat envvars envsWithType =-  let 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 mapFormat valuesAndTypes of-       Left errors -> error (unlines errors)-       _           -> return ()
− src/Configuration/Dotenv/Scheme/Helpers.hs
@@ -1,87 +0,0 @@--- |--- Module      :  Configuration.Dotenv.Types--- Copyright   :  © 2015–2020 Stack Builders Inc.--- License     :  MIT------ Maintainer  :  Stack Builders <hackage@stackbuilders.com>--- Stability   :  experimental--- Portability :  portable------ Helpers for loadSafeFile--{-# LANGUAGE CPP             #-}-{-# LANGUAGE RecordWildCards #-}--module Configuration.Dotenv.Scheme.Helpers-  ( joinEnvs-  , matchValueAndType-  , missingDotenvs-  , missingSchemeEnvs-  , sepWithCommas-  , showMissingDotenvs-  , showMissingSchemeEnvs-  )-  where--#if !MIN_VERSION_base(4,8,0)-import           Control.Applicative               ((<*>))-import           Data.Functor                      ((<$>))-#endif-import           Data.List--import           Configuration.Dotenv.Scheme.Types--matchValueAndType-  :: [(Env, (String, String))]-  -> [(String, EnvType)]-matchValueAndType =-  let getValueAndType (Env{..}, (_, value)) = (value, envType)-   in map getValueAndType--joinEnvs-  :: [Env]-  -> [(String, String)]-  -> [(Env, (String, String))]-joinEnvs =-  let sameName (Env{..}, (name,_)) = envName == name-   in joinBy sameName--joinBy :: ((a,b) -> Bool) -> [a] -> [b] -> [(a,b)]-joinBy p xs ys =-  let cartesianProduct = (,) <$> xs <*> ys-   in filter p cartesianProduct--missingDotenvs-  :: [Env]-  -> [(Env, (String, String))]-  -> [Env]-missingDotenvs =-  let sameName envOne envTwo = envName envOne == envName envTwo-   in missingLeft sameName--missingLeft :: (a -> a -> Bool) -> [a] -> [(a,b)] -> [a]-missingLeft p xs xys =-  let getAllLeft = map fst xys-   in deleteFirstsBy p xs getAllLeft--missingSchemeEnvs-  :: [(String, String)]-  -> [(Env, (String, String))]-  -> [(String, String)]-missingSchemeEnvs =-  let sameName (nameOne,_) (nameTwo,_) = nameOne == nameTwo-   in missingRight sameName--missingRight :: (b -> b -> Bool) -> [b] -> [(a,b)] -> [b]-missingRight p ys xys =-  let getAllRight = map snd xys-   in deleteFirstsBy p ys getAllRight--sepWithCommas :: [String] -> String-sepWithCommas = intercalate ", "--showMissingDotenvs :: [Env] -> String-showMissingDotenvs = sepWithCommas . map envName--showMissingSchemeEnvs :: [(String, String)] -> String-showMissingSchemeEnvs = sepWithCommas . map fst
− src/Configuration/Dotenv/Scheme/Parser.hs
@@ -1,65 +0,0 @@--- |--- Module      :  Configuration.Dotenv.Types--- Copyright   :  © 2015–2020 Stack Builders Inc.--- License     :  MIT------ Maintainer  :  Stack Builders <hackage@stackbuilders.com>--- Stability   :  experimental--- Portability :  portable------ Helpers for loadSafeFile--{-# LANGUAGE CPP                 #-}-{-# LANGUAGE OverloadedStrings   #-}-{-# LANGUAGE ScopedTypeVariables #-}--module Configuration.Dotenv.Scheme.Parser-  ( defaultValidatorMap-  , parseEnvsWithScheme-  , typeValidator-  )-  where--#if !MIN_VERSION_base(4,8,0)-import           Control.Applicative               (pure, (*>))-import           Data.Functor                      ((<$>))-#endif--import           Data.Either--import qualified Data.Map.Lazy                     as ML--import qualified Data.Text                         as T--import           Configuration.Dotenv.Scheme.Types----- |----parseEnvsWithScheme-  :: ValidatorMap -- ^ MapFormat validations-  -> [(String, EnvType)] -- ^ Value and Type-  -> Either [String] ()-parseEnvsWithScheme validatorMap valuesAndTypes =-  let parsedEithers = parseEnvs <$> valuesAndTypes-      parseEnvWith = typeValidator validatorMap-      parseEnvs (val, type') = val `parseEnvWith` type'-    in if all isRight parsedEithers-          then Right ()-          else Left (lefts parsedEithers)---- |----typeValidator-  :: ValidatorMap -- ^ MapFormat validations-  -> String -- ^ Value of the env variable-  -> EnvType -- ^ Type that the env variable should have-  -> Either String ()-typeValidator validatorMap envVal (EnvType type_) =-  let errorMsg = "Couldn't parse " ++ envVal ++ " as " ++ T.unpack type_-   in case ML.lookup type_ validatorMap of-        Nothing -> Left errorMsg-        Just validator ->-          if validator (T.pack envVal)-             then Right ()-             else Left errorMsg
− src/Configuration/Dotenv/Scheme/Types.hs
@@ -1,90 +0,0 @@--- |--- Module      :  Configuration.Dotenv.Types--- Copyright   :  © 2015–2020 Stack Builders Inc.--- License     :  MIT------ Maintainer  :  Stack Builders <hackage@stackbuilders.com>--- Stability   :  experimental--- Portability :  portable------ Types for 'loadSafeFile' (e. g., 'ValidatorMap')--{-# LANGUAGE CPP               #-}-{-# LANGUAGE OverloadedStrings #-}--module Configuration.Dotenv.Scheme.Types where--#if !MIN_VERSION_base(4,8,0)-import           Control.Applicative (pure, (<*>))-import           Data.Functor        ((<$>))-#endif--import           Data.Maybe          (isJust)--import           Data.Map.Lazy       (Map)--import           Data.Yaml--import qualified Data.Map.Lazy       as ML--import           Data.Text           (Text)-import qualified Data.Text           as T--import           Text.Read           (readMaybe)----- |----newtype EnvType = EnvType Text-    deriving (Show, Eq, Ord)---- |----instance FromJSON EnvType where-  parseJSON (String value) = pure (EnvType value)-  parseJSON anyOther       = fail ("Not an object: " ++ show anyOther)---- |----data Env =-  Env-    { envName  :: String-    , envType  :: EnvType-    , required :: Bool-    } deriving (Show, Eq, Ord)---- |----instance FromJSON Env where-  parseJSON (Object m) =-    Env-      <$> m .: "name"-      <*> m .: "type"-      <*> m .:? "required" .!= False-  parseJSON x = fail ("Not an object: " ++ show x)---- | Parameters:------ - __Key:__ Name of the /format/ to check.------ - __Value:__ Function to check if some text meets the condition.----type ValidatorMap = Map Text (Text -> Bool)----- | Default configuration for 'loadSafeFile'. It currently checks:--- @bool@, @integer@, and @text@.----defaultValidatorMap :: ValidatorMap-defaultValidatorMap =-  let booleanValidator :: Text -> Bool-      booleanValidator text = isJust (readMaybe (T.unpack text) :: Maybe Bool)-      integerValidator :: Text -> Bool-      integerValidator text = isJust (readMaybe (T.unpack text) :: Maybe Integer)-      textValidator :: Text -> Bool-      textValidator = const True-   in ML.fromList-        [ ("bool", booleanValidator)-        , ("integer", integerValidator)-        , ("text", textValidator)-        ]