packages feed

effectful-config-file 0.1.1.1 → 0.1.2.0

raw patch · 8 files changed

+59/−4 lines, 8 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Data.Error.Config: ConfigNotFound :: Text -> ConfigNotFound
+ Data.Error.Config: instance GHC.Classes.Eq Data.Error.Config.ConfigNotFound
+ Data.Error.Config: instance GHC.Internal.Show.Show Data.Error.Config.ConfigNotFound
+ Data.Error.Config: newtype ConfigNotFound
+ Effectful.Config: requireConfigValue :: forall (es :: [Effect]) c a. (IOE :> es, Config c :> es, Log :> es, Secrets :> es, Error ConfigNotFound :> es, ConfigParse a, Show a) => Text -> ALens' c (ConfigValue a) -> Eff es a

Files

CHANGELOG.md view
@@ -1,3 +1,9 @@+## [1.2.0](https://github.com/haskell-github-trust/effectful-config-file/compare/1.1.1...1.2.0) (2026-10-26)++### Features++* add `requireConfigValue` helper ([8ba0c9e](https://github.com/haskell-github-trust/effectful-config-file/commit/8ba0c9e9e09ac829f3e64f44ae519d81c137312b))+ ## [1.1.1](https://github.com/haskell-github-trust/effectful-config-file/compare/1.1.0...1.1.1) (2026-10-25)  ## [1.1.0](https://github.com/haskell-github-trust/effectful-config-file/compare/1.0.2...1.1.0) (2026-10-25)
effectful-config-file.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack  name:           effectful-config-file-version:        0.1.1.1+version:        0.1.2.0 synopsis:       Config-file effect for effectful description:    Config-file parser and utilities to use in conjunction with effectful category:       Configuration
src/Data/Config.hs view
@@ -7,6 +7,8 @@ {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeOperators #-} +-- | Configuration values that can be literals or references to+-- environment variables, files or secrets, and their TOML decoding. module Data.Config (   ConfigParse (..),   ConfigFetch (..),
src/Data/Error/Config.hs view
@@ -1,8 +1,11 @@+-- | Configuration decoding errors. module Data.Error.Config (   ConfigError (..),+  ConfigNotFound (..), ) where  import Data.List (intercalate)+import Data.Text (Text) import Toml (DecodeError, prettyDecodeError)  -- | Errors raised while decoding a TOML configuration.@@ -18,3 +21,9 @@  instance Show ConfigError where   show (ConfigError es) = "config error: " <> intercalate "; " (map prettyDecodeError es)++-- | A configuration value whose @env://@ or @file://@ source is absent.+--+-- @since 0.1.2.0+newtype ConfigNotFound = ConfigNotFound Text+  deriving (Eq, Show)
src/Effectful/Config.hs view
@@ -5,18 +5,21 @@ {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeOperators #-} +-- | Effect to read a TOML configuration and lazily resolve its values. module Effectful.Config (   Config,   getConfig,   getConfigValue,   readConfig,   readConfig',+  requireConfigValue, ) where  import Control.Concurrent.MVar (MVar, modifyMVar, readMVar)+import Control.Exception (IOException) import Control.Lens (ALens', cloneLens, (&), (.~), (^.)) import Data.Config (ConfigFetch (fetch), ConfigParse, ConfigValue (..))-import Data.Error.Config (ConfigError (..))+import Data.Error.Config (ConfigError (..), ConfigNotFound (..)) import Data.Text (Text) import qualified Data.Text as T (pack) import qualified Data.Text.IO as T (readFile)@@ -24,6 +27,7 @@ import Effectful.Config.Log (Log, logWarn) import Effectful.Config.Secrets (Secrets) import Effectful.Error.Static (Error, throwError)+import Effectful.Exception (catch) import Effectful.Reader.Static (Reader, ask) import OpenTelemetry.Trace.Core (   addAttribute,@@ -78,6 +82,24 @@               [ printf "tried to get raw config value from (%s)" (show v)               , "this should be impossible and is most likely a bug in your ConfigFetch instance"               ]++-- | 'getConfigValue', raising t'ConfigNotFound' when an @env://@ or @file://@+-- source is absent instead of letting the 'IOException' escape.+--+-- @since 0.1.2.0+requireConfigValue+  :: IOE :> es+  => Config c :> es+  => Log :> es+  => Secrets :> es+  => Error ConfigNotFound :> es+  => ConfigParse a+  => Show a+  => Text+  -> ALens' c (ConfigValue a)+  -> Eff es a+requireConfigValue name lens =+  getConfigValue lens `catch` \(_ :: IOException) -> throwError (ConfigNotFound name)  -- | Decode a configuration from TOML text. Warnings are ignored. --
src/Effectful/Config/Log.hs view
@@ -4,6 +4,7 @@ {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} +-- | Minimal logging effect used by the configuration library. module Effectful.Config.Log (   Log,   runLog,
src/Effectful/Config/Secrets.hs view
@@ -4,6 +4,7 @@ {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} +-- | Effect to resolve secrets referenced by configuration values. module Effectful.Config.Secrets (   Secrets (..),   getSecret,
test/Effectful/ConfigSpec.hs view
@@ -13,11 +13,11 @@ import Control.Lens (makeLenses, (^.)) import Data.Bifunctor (Bifunctor (..), first) import Data.Config (ConfigValue (..), withSection)-import Data.Error.Config (ConfigError (..))+import Data.Error.Config (ConfigError (..), ConfigNotFound (..)) import Data.Text (Text) import qualified Data.Text as T (isInfixOf, pack, unlines, unpack) import Effectful (runEff)-import Effectful.Config (getConfigValue, readConfig, readConfig')+import Effectful.Config (getConfigValue, readConfig, readConfig', requireConfigValue) import Effectful.Config.Log (runLog) import Effectful.Config.Secrets (SecretsError, runSecretsError) import Effectful.Error.Static (runErrorNoCallStack)@@ -216,6 +216,20 @@        cfg <- timeout 1000000 (readMVar p)       cfg `shouldBe` Just (FileConfig (File "/nonexistent"))++  describe "requireConfigValue" $ do+    it "throws ConfigNotFound on a missing file" $ do+      p <- newMVar (FileConfig (File "/nonexistent"))+      result <-+        runEff+          . runErrorNoCallStack @ConfigNotFound+          . runErrorNoCallStack @SecretsError+          . runSecretsError+          . runLog silentLog+          . runReader p+          $ requireConfigValue "file_val" file_val++      result `shouldBe` Left (ConfigNotFound "file_val")    describe "readConfig' OTel logging" $ do     it "emits parse warnings as OTel log records" $ withSystemTempFile "effectful-config" $ \path h -> do