from-env 0.1.1.0 → 0.1.2.0
raw patch · 3 files changed
+49/−1 lines, 3 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ System.Environment.FromEnv: AggregateError :: [FromEnvError] -> FromEnvError
+ System.Environment.FromEnv: instance (System.Environment.FromEnv.FromEnv a, System.Environment.FromEnv.FromEnv b) => System.Environment.FromEnv.FromEnv (a, b)
+ System.Environment.FromEnv: instance (System.Environment.FromEnv.FromEnv a, System.Environment.FromEnv.FromEnv b, System.Environment.FromEnv.FromEnv c) => System.Environment.FromEnv.FromEnv (a, b, c)
Files
- from-env.cabal +1/−1
- src/System/Environment/FromEnv.hs +26/−0
- test/System/Environment/FromEnvSpec.hs +22/−0
from-env.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.4 name: from-env-version: 0.1.1.0+version: 0.1.2.0 synopsis: Provides a generic way to construct values from environment variables.
src/System/Environment/FromEnv.hs view
@@ -23,6 +23,7 @@ import Control.Applicative (liftA2) import Control.Monad.IO.Class (MonadIO, liftIO)+import Data.List (intercalate) import GHC.Generics import System.Environment (lookupEnv) @@ -37,6 +38,28 @@ default fromEnv :: (MonadIO m, Generic a, GFromEnv' (Rep a)) => m (Either FromEnvError a) fromEnv = gFromEnv defaultEnvOpts +instance (FromEnv a, FromEnv b) => FromEnv (a, b) where+ fromEnv = do+ t <- (,) <$> fromEnv <*> fromEnv+ return $ case t of+ (Left e1, Left e2) -> Left $ AggregateError [e1, e2]+ (Left e, Right _) -> Left e+ (Right _, Left e) -> Left e+ (Right a, Right b) -> Right (a, b)++instance (FromEnv a, FromEnv b, FromEnv c) => FromEnv (a, b, c) where+ fromEnv = do+ t <- (,,) <$> fromEnv <*> fromEnv <*> fromEnv+ return $ case t of+ (Left e1, Left e2, Left e3) -> Left $ AggregateError [e1, e2, e3]+ (Left e1, Left e2, Right _) -> Left $ AggregateError [e1, e2]+ (Right _, Left e1, Left e2) -> Left $ AggregateError [e1, e2]+ (Left e1, Right _, Left e2) -> Left $ AggregateError [e1, e2]+ (Left e, Right _, Right _) -> Left e+ (Right _, Left e, Right _) -> Left e+ (Right _, Right _, Left e) -> Left e+ (Right a, Right b, Right c) -> Right (a, b, c)+ -- | Try to convert a field name into an environment variable name. type FieldLabelModifier = String -> String @@ -105,6 +128,8 @@ -- ^ A field was unset in the environment | FailedToParse String String -- ^ Failed to parse a given field from an environment variable+ | AggregateError [FromEnvError]+ -- ^ There was more than one error. deriving Eq instance Show FromEnvError where@@ -112,3 +137,4 @@ "The field " <> fieldName <> " was unset in the environment" show (FailedToParse fieldName envValue) = "Failed to parse the field " <> fieldName <> " from the value " <> envValue+ show (AggregateError errors) = intercalate ", " (map show errors)
test/System/Environment/FromEnvSpec.hs view
@@ -37,6 +37,23 @@ config `shouldSatisfy` isRight unwrapEither config `shouldBe` Config "hello" "world" + describe "the tuple instances" $ do+ it "return a list of errors when more than one value failed to build" $ do+ Left (AggregateError [e1, e2]) <- fromEnv @(Config, StorageConfig)+ e1 `shouldBe` UnsetVariable "CONFIG_DB_URL"+ e2 `shouldBe` UnsetVariable "S3_BUCKET_URL"++ it "return the correct values when setting valid environment variables" $ do+ setEnv "CONFIG_DB_URL" "hello"+ setEnv "CONFIG_API_KEY" "world"+ setEnv "S3_BUCKET_URL" "https://google.com"++ (config, storageConfig) <- unwrapEither <$> fromEnv++ config `shouldBe` Config "hello" "world"+ storageConfig `shouldBe` StorageConfig "https://google.com"++ gFromEnvSpec :: Spec gFromEnvSpec = describe "gFromEnv" $ after_ clearEnvs $ do@@ -50,6 +67,11 @@ data Config = Config { configDbURL :: !String , configApiKey :: !String+ }+ deriving (Eq, Show, Generic, FromEnv)++newtype StorageConfig = StorageConfig+ { s3BucketUrl :: String } deriving (Eq, Show, Generic, FromEnv)