-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Tools for specifying and parsing configurations -- @package configuration-tools @version 0.2.13 -- | This module contains a Setup.hs script that hooks into the -- cabal build process at the end of the configuration phase and -- generates a module with package information for each component of the -- cabal package. -- -- The modules are created in the autogen build directory where -- also the Path_ module is created by cabal's simple build -- setup. This is usually the directory ./dist/build/autogen. -- -- For a library component the module is named just PkgInfo. For -- all other components the module is named -- PkgInfo_COMPONENT_NAME where COMPONENT_NAME is the -- name of the component with - characters replaced by -- _. -- -- For instance, if a cabal package contains a library and an executable -- that is called my-app, the following modules are created: -- PkgInfo and PkgInfo_my_app. -- --
module Main (main) where import -- Configuration.Utils.Setup
module Main (main) where import qualified -- Configuration.Utils.Setup as ConfTools main :: IO () main = -- defaultMainWithHooks (ConfTools.mkPkgInfoModules simpleUserHooks) --
-- Build-Type: Custom ---- --
-- {-# LANGUAGE OverloadedStrings #-}
-- {-# LANGUAGE FlexibleInstances #-}
--
-- module Main
-- ( main
-- ) where
--
-- import Configuration.Utils
-- import PkgInfo
--
-- instance FromJSON (() -> ()) where parseJSON _ = pure id
--
-- mainInfo :: ProgramInfo ()
-- mainInfo = programInfo "Hello World" (pure id) ()
--
-- main :: IO ()
-- main = runWithPkgInfoConfiguration mainInfo pkgInfo . const $ putStrLn "hello world"
--
--
-- With that the resulting application supports the following additional
-- command line options:
--
--
-- data Setting = Setting
-- { _setA ∷ !Int
-- , _setB ∷ !String
-- }
-- deriving (Show, Read, Eq, Ord, Typeable)
--
-- $(makeLenses ''Setting)
--
-- defaultSetting ∷ Setting
-- defaultSetting = Setting
-- { _setA = 0
-- , _setB = 1
-- }
--
-- instance ToJSON Setting where
-- toJSON setting = object
-- [ "a" .= _setA setting
-- , "b" .= _setB setting
-- ]
--
-- instance FromJSON (Setting → Setting) where
-- parseJSON = withObject "Setting" $ \o → id
-- <$< setA ..: "a" % o
-- <*< setB ..: "b" % o
--
-- instance FromJSON Setting where
-- parseJSON v = parseJSON v <*> pure defaultSetting
--
-- pSetting ∷ MParser Setting
-- pSetting = id
-- <$< setA .:: option auto
-- % short 'a'
-- <> metavar "INT"
-- <> help "set a"
-- <*< setB .:: option auto
-- % short 'b'
-- <> metavar "INT"
-- <> help "set b"
--
-- -- | Use 'Setting' as 'Maybe' in a configuration:
-- --
-- data Config = Config
-- { _maybeSetting ∷ !(Maybe Setting)
-- }
-- deriving (Show, Read, Eq, Ord, Typeable)
--
-- $(makeLenses ''Config)
--
-- defaultConfig ∷ Config
-- defaultConfig = Config
-- { _maybeSetting = defaultSetting
-- }
--
-- instance ToJSON Config where
-- toJSON config = object
-- [ "setting" .= maybeSetting
-- ]
--
-- instance FromJSON (Config → Config) where
-- parseJSON = withObject "Config" $ \o → id
-- <$< maybeSetting %.: "setting" % o
--
-- pConfig ∷ MParser Config
-- pConfig = id
-- <$< maybeSetting %:: (maybeOption defaultSetting
-- <$> pEnableSetting
-- <*> pSetting)
-- where
-- pEnableSetting = boolOption
-- % long "setting-enable"
-- <> value False
-- <> help "Enable configuration flags for setting"
--
maybeOption :: a -> Bool -> (a -> a) -> Maybe a -> Maybe a
instance (FromJSON (a -> a), FromJSON a) => FromJSON (Maybe a -> Maybe a)
-- | Useful operators for defining functions in an applicative context
module Configuration.Utils.Operators
-- | This operator is an alternative for $ with a higher precedence.
-- It is suitable for usage within applicative style code without the
-- need to add parenthesis.
(%) :: (α -> β) -> α -> β
-- | This operator is a UTF-8 version of % which is an alternative
-- for $ with a higher precedence. It is suitable for usage within
-- applicative style code without the need to add parenthesis.
--
-- The hex value of the UTF-8 character × is 0x00d7.
--
-- In VIM type: Ctrl-V u 00d7
--
-- You may also define a key binding by adding something like the
-- following line to your vim configuration file:
--
-- -- iabbrev <buffer> >< × --(×) :: (α -> β) -> α -> β -- | Functional composition for applicative functors. (<*<) :: Applicative φ => φ (β -> γ) -> φ (α -> β) -> φ (α -> γ) -- | Functional composition for applicative functors with its arguments -- flipped. (>*>) :: Applicative φ => φ (α -> β) -> φ (β -> γ) -> φ (α -> γ) -- | Applicative functional composition between a pure function and an -- applicative function. (<$<) :: Functor φ => (β -> γ) -> φ (α -> β) -> φ (α -> γ) -- | Applicative functional composition between a pure function and an -- applicative function with its arguments flipped. (>$>) :: Functor φ => φ (α -> β) -> (β -> γ) -> φ (α -> γ) -- | Functional composition for applicative functors. -- -- This is a rather popular operator. Due to conflicts (for instance with -- the lens package) it may have to be imported qualified. -- | Deprecated: use <*< instead (<.>) :: Applicative φ => φ (β -> γ) -> φ (α -> β) -> φ (α -> γ) -- | For people who like nicely aligned code and do not mind messing with -- editor key-maps: here a version of <.> that uses a -- unicode symbol -- -- The hex value of the UTF-8 character ⊙ is 0x2299. -- -- A convenient VIM key-map is: -- --
-- iabbrev <buffer> ../ ⊙ ---- | Deprecated: use <*< instead (⊙) :: Applicative φ => φ (β -> γ) -> φ (α -> β) -> φ (α -> γ) -- | This module provides tools for defining command line parsers for -- configuration types. -- -- Unlike normal command line parsers the parsers for -- configuration types are expected to yield an update function that -- takes a value and updates the value with the settings from the command -- line. -- -- Assuming that -- --
-- data Auth = Auth
-- { _user ∷ !String
-- , _pwd ∷ !String
-- }
--
-- user ∷ Functor φ ⇒ (String → φ String) → Auth → φ Auth
-- user f s = (\u → s { _user = u }) <$> f (_user s)
--
-- pwd ∷ Functor φ ⇒ (String → φ String) → Auth → φ Auth
-- pwd f s = (\p → s { _pwd = p }) <$> f (_pwd s)
--
-- -- or with lenses and TemplateHaskell just:
-- -- $(makeLenses ''Auth)
--
-- pAuth ∷ MParser Auth
-- pAuth = id
-- <$< user .:: strOption
-- × long "user"
-- ⊕ short 'u'
-- ⊕ help "user name"
-- <*< pwd .:: strOption
-- × long "pwd"
-- ⊕ help "password for user"
--
(.::) :: (Alternative φ, Applicative φ) => Lens' α β -> φ β -> φ (α -> α)
-- | An operator for applying a setter to an option parser that yields a
-- modification function.
--
-- Example usage:
--
--
-- data HttpURL = HttpURL
-- { _auth ∷ !Auth
-- , _domain ∷ !String
-- }
--
-- auth ∷ Functor φ ⇒ (Auth → φ Auth) → HttpURL → φ HttpURL
-- auth f s = (\u → s { _auth = u }) <$> f (_auth s)
--
-- domain ∷ Functor φ ⇒ (String → φ String) → HttpURL → φ HttpURL
-- domain f s = (\u → s { _domain = u }) <$> f (_domain s)
--
-- path ∷ Functor φ ⇒ (String → φ String) → HttpURL → φ HttpURL
-- path f s = (\u → s { _path = u }) <$> f (_path s)
--
-- -- or with lenses and TemplateHaskell just:
-- -- $(makeLenses ''HttpURL)
--
-- pHttpURL ∷ MParser HttpURL
-- pHttpURL = id
-- <$< auth %:: pAuth
-- <*< domain .:: strOption
-- × long "domain"
-- ⊕ short 'd'
-- ⊕ help "HTTP domain"
--
(%::) :: (Alternative φ, Applicative φ) => Lens' α β -> φ (β -> β) -> φ (α -> α)
boolReader :: (Eq a, Show a, FoldCase a, IsString a, IsString e, Monoid e) => a -> Either e Bool
-- | The boolOption is an alternative to switch.
--
-- Using switch with command line parsers that overwrite settings
-- from a configuration file is problematic: the absence of the
-- switch is interpreted as setting the respective configuration
-- value to False. So there is no way to specify on the command
-- line that the value from the configuration file shall be used. Some
-- command line UIs use two different options for those values, for
-- instance --enable-feature and --disable-feature.
-- This option instead expects a Boolean value. Beside that it behaves
-- like any other option.
boolOption :: Mod OptionFields Bool -> Parser Bool
-- | An alternative syntax for boolOption for options with long
-- names.
--
-- Instead of taking a boolean argument the presence of the option acts
-- as a switch to set the respective configuration setting to
-- True. If the option is not present the setting is left
-- unchanged.
--
-- In addition for long option names a respective unset flag is
-- provided. For instance for a flag --verbose there will also
-- be a flag --no-verbose.
--
-- This can still be used with short option names only, but no unset
-- flag would be provided.
boolOption_ :: Mod FlagFields Bool -> Parser Bool
-- | An option parser for flags that are enabled via the flag name prefixed
-- with --enable- and disabled via the flag name prefix
-- --disable-. The prefixes are applied to all long option
-- names. Short option names are parsed unchanged and and cause the flag
-- to be enabled.
--
-- This resembles the style of flags that is used for instances with
-- Cabal.
enableDisableFlag :: Mod FlagFields Bool -> Parser Bool
fileOption :: Mod OptionFields String -> Parser FilePath
eitherReadP :: Text -> ReadP a -> Text -> Either Text a
-- | The distinction between appending on the left and appending on the
-- right is important for monoids that are sensitive to ordering such as
-- List. It is also of relevance for monoids with set semantics
-- with non-extensional equality such as HashMap.
module Configuration.Utils.Monoid
-- | Update a value by appending on the left. Under normal circumstances
-- you'll never use this type directly but only its FromJSON
-- instance. See the leftMonoidalUpdate for an example.
data LeftMonoidalUpdate α
-- | Update a value by appending on the left.
--
--
-- newtype RoutingTable = RoutingTable { _routingTableMap ∷ HashMap T.Text T.Text }
--
-- $(makeLenses ''RoutingTable)
--
-- instance FromJSON (RoutingTable → RoutingTable) where
-- parseJSON = withObject "RoutingTable" $ \o → id
-- <$< routingTableMap . from leftMonoidalUpdate %.: "route_map" % o
--
leftMonoidalUpdate :: Iso (LeftMonoidalUpdate α) (LeftMonoidalUpdate β) α β
-- | This is the same as from leftMonoidalUpdate but doesn't
-- depend on the lens Library.
fromLeftMonoidalUpdate :: Iso α β (LeftMonoidalUpdate α) (LeftMonoidalUpdate β)
-- | Update a value by appending on the left.
--
--
-- newtype RoutingTable = RoutingTable { _routingTableMap ∷ HashMap T.Text T.Text }
--
-- $(makeLenses ''RoutingTable)
--
-- pRoutingTable ∷ MParser RoutingTable
-- pRoutingTable = routingTableMap %:: pLeftMonoidalUpdate pRoute
-- where
-- pRoute = option (eitherReader readRoute)
-- % long "route"
-- <> help "add a route to the routing table; the APIROUTE part must not contain a colon character"
-- <> metavar "APIROUTE:APIURL"
--
-- readRoute s = case break (== ':') s of
-- (a,':':b) → fmapL T.unpack $ do
-- validateNonEmpty "APIROUTE" a
-- validateHttpOrHttpsUrl "APIURL" b
-- return $ HM.singleton (T.pack a) (T.pack b)
-- _ → Left "missing colon between APIROUTE and APIURL"
--
-- fmapL f = either (Left . f) Right
--
pLeftMonoidalUpdate :: Monoid α => Parser α -> MParser α
-- | Update a value by appending on the right. Under normal circumstances
-- you'll never use this type directly but only its FromJSON
-- instance. See the leftMonoidalUpdate for an example.
data RightMonoidalUpdate α
-- | Update a value by appending on the right. See
-- leftMonoidalUpdate for an usage example.
rightMonoidalUpdate :: Iso (RightMonoidalUpdate α) (RightMonoidalUpdate β) α β
-- | This is the same as from rightMonoidalUpdate but doesn't
-- depend on the lens Library.
fromRightMonoidalUpdate :: Iso α β (RightMonoidalUpdate α) (RightMonoidalUpdate β)
-- | Update a value by appending on the right. See
-- pLeftMonoidalUpdate for an usage example.
pRightMonoidalUpdate :: Monoid α => Parser α -> MParser α
instance Monoid α => Monoid (LeftMonoidalUpdate α)
instance Monoid α => Monoid (RightMonoidalUpdate α)
instance (FromJSON α, Monoid α) => FromJSON (RightMonoidalUpdate α -> RightMonoidalUpdate α)
instance (FromJSON α, Monoid α) => FromJSON (LeftMonoidalUpdate α -> LeftMonoidalUpdate α)
-- | This module provides means for defining and using HTTPS certificate
-- validation polices for HTTPS requests.
module Configuration.Utils.Internal.HttpsCertPolicy
data HttpsCertPolicy
HttpsCertPolicy :: !Bool -> !(HashMap ServiceID Fingerprint) -> HttpsCertPolicy
-- | disable certificate validation
_certPolicyInsecure :: HttpsCertPolicy -> !Bool
-- | a whitelist for services with trusted certificates
_certPolicyHostFingerprints :: HttpsCertPolicy -> !(HashMap ServiceID Fingerprint)
certPolicyInsecure :: Lens' HttpsCertPolicy Bool
certPolicyHostFingerprints :: Lens' HttpsCertPolicy (HashMap ServiceID Fingerprint)
defaultHttpsCertPolicy :: HttpsCertPolicy
pHttpsCertPolicy :: Text -> MParser HttpsCertPolicy
-- | Make an HTTP request with a given certificate validation policy.
--
-- NOTE that the HTTP request is strictly loaded into memory.
--
-- NOTE that this implementation opens a new TCP connection for each
-- single request. HTTPS certificates validation results are not cached
-- between different requests.
simpleHttpWithValidationPolicy :: Text -> HttpsCertPolicy -> IO (Response ByteString)
httpWithValidationPolicy :: Request -> HttpsCertPolicy -> IO (Response ByteString)
-- | The Haskell tls library provides only limited means for
-- providing user friendly error messages. In particular we'd like to
-- provide the user with fingerprints of the reject certificate for
-- self-signed certificates. Also we want to provide the user with some
-- guidance what a particular failure may indicate with respect to
-- security of the connection.
--
-- Here we employ a hack for better error handling: Based on the
-- assumption that we initialize a new connection Manager and
-- also a new certificate cache for each request, we write the
-- certificate that is received from the server in the TLS handshake to
-- an IORef. If the handshakes fails later on because the
-- certificate is rejected we can recover the rejected certificate from
-- the IORef.
--
-- What we really want are exceptions that can be consumed
-- programatically. In particular exceptions should include rejected
-- certificates.
newtype VerboseTlsException
VerboseTlsException :: Text -> VerboseTlsException
instance Typeable HttpsCertPolicy
instance Typeable VerboseTlsException
instance Show HttpsCertPolicy
instance Eq HttpsCertPolicy
instance Eq VerboseTlsException
instance Ord VerboseTlsException
instance Exception VerboseTlsException
instance Show VerboseTlsException
-- | This module provides tools for defining configuration file parsers via
-- instances of FromJSON.
--
-- Unlike normal FromJSON instances the parsers for
-- configuration files are expected to yield an update function that
-- takes a value and updates the value with the settings from the
-- configuration file.
--
-- Assuming that
--
--
-- data Auth = Auth
-- { _userId ∷ !Int
-- , _pwd ∷ !String
-- }
--
-- userId ∷ Functor φ ⇒ (Int → φ Int) → Auth → φ Auth
-- userId f s = (\u → s { _userId = u }) <$> f (_userId s)
--
-- pwd ∷ Functor φ ⇒ (String → φ String) → Auth → φ Auth
-- pwd f s = (\p → s { _pwd = p }) <$> f (_pwd s)
--
-- -- or with lenses and TemplateHaskell just:
-- -- $(makeLenses ''Auth)
--
-- instance FromJSON (Auth → Auth) where
-- parseJSON = withObject "Auth" $ \o → id
-- <$< setProperty user "user" p o
-- <*< setProperty pwd "pwd" parseJSON o
-- where
-- p = withText "user" $ \case
-- "alice" → pure (0 ∷ Int)
-- "bob" → pure 1
-- e → fail $ "unrecognized user " ⊕ e
--
setProperty :: Lens' α β -> Text -> (Value -> Parser β) -> Object -> Parser (α -> α)
-- | A variant of the setProperty that uses the default
-- parseJSON method from the FromJSON instance to parse the
-- value of the property. Its usage pattern mimics the usage pattern of
-- the .: operator from the aeson library.
--
--
-- data Auth = Auth
-- { _user ∷ !String
-- , _pwd ∷ !String
-- }
--
-- user ∷ Functor φ ⇒ (String → φ String) → Auth → φ Auth
-- user f s = (\u → s { _user = u }) <$> f (_user s)
--
-- pwd ∷ Functor φ ⇒ (String → φ String) → Auth → φ Auth
-- pwd f s = (\p → s { _pwd = p }) <$> f (_pwd s)
--
-- -- or with lenses and TemplateHaskell just:
-- -- $(makeLenses ''Auth)
--
-- instance FromJSON (Auth → Auth) where
-- parseJSON = withObject "Auth" $ \o → id
-- <$< user ..: "user" × o
-- <*< pwd ..: "pwd" × o
--
(..:) :: FromJSON β => Lens' α β -> Text -> Object -> Parser (α -> α)
-- | This operator requires that a value is explicitly provided in a
-- configuration file, thus preventing the default value from being used.
-- Otherwise this operator does the same as '(..:)'.
(!..:) :: FromJSON β => Lens' α β -> Text -> Object -> Parser (α -> α)
-- | A JSON parser for a function that modifies a property of a given
-- Object and updates a setter with the parsed function.
--
--
-- data HttpURL = HttpURL
-- { _auth ∷ !Auth
-- , _domain ∷ !String
-- }
--
-- auth ∷ Functor φ ⇒ (Auth → φ Auth) → HttpURL → φ HttpURL
-- auth f s = (\u → s { _auth = u }) <$> f (_auth s)
--
-- domain ∷ Functor φ ⇒ (String → φ String) → HttpURL → φ HttpURL
-- domain f s = (\u → s { _domain = u }) <$> f (_domain s)
--
-- path ∷ Functor φ ⇒ (String → φ String) → HttpURL → φ HttpURL
-- path f s = (\u → s { _path = u }) <$> f (_path s)
--
-- -- or with lenses and TemplateHaskell just:
-- -- $(makeLenses ''HttpURL)
--
-- instance FromJSON (HttpURL → HttpURL) where
-- parseJSON = withObject "HttpURL" $ \o → id
-- <$< auth %.: "auth" × o
-- <*< domain ..: "domain" × o
--
updateProperty :: Lens' α β -> Text -> (Value -> Parser (β -> β)) -> Object -> Parser (α -> α)
-- | A variant of updateProperty that used the FromJSON
-- instance for the update function. It mimics the aeson operator
-- .:. It creates a parser that modifies a setter with a parsed
-- function.
--
--
-- data HttpURL = HttpURL
-- { _auth ∷ !Auth
-- , _domain ∷ !String
-- }
--
-- auth ∷ Functor φ ⇒ (Auth → φ Auth) → HttpURL → φ HttpURL
-- auth f s = (\u → s { _auth = u }) <$> f (_auth s)
--
-- domain ∷ Functor φ ⇒ (String → φ String) → HttpURL → φ HttpURL
-- domain f s = (\u → s { _domain = u }) <$> f (_domain s)
--
-- path ∷ Functor φ ⇒ (String → φ String) → HttpURL → φ HttpURL
-- path f s = (\u → s { _path = u }) <$> f (_path s)
--
-- -- or with lenses and TemplateHaskell just:
-- -- $(makeLenses ''HttpURL)
--
-- instance FromJSON (HttpURL → HttpURL) where
-- parseJSON = withObject "HttpURL" $ \o → id
-- <$< auth %.: "auth" × o
-- <*< domain ..: "domain" × o
--
(%.:) :: FromJSON (β -> β) => Lens' α β -> Text -> Object -> Parser (α -> α)
data ConfigFile
ConfigFileRequired :: !Text -> ConfigFile
getConfigFile :: ConfigFile -> !Text
ConfigFileOptional :: !Text -> ConfigFile
getConfigFile :: ConfigFile -> !Text
-- | An internal type for the meta configuration that specifies how
-- the configuration files are loaded and parsed.
data ConfigFilesConfig
ConfigFilesConfig :: !HttpsCertPolicy -> ConfigFilesConfig
_cfcHttpsPolicy :: ConfigFilesConfig -> !HttpsCertPolicy
cfcHttpsPolicy :: Lens' ConfigFilesConfig HttpsCertPolicy
defaultConfigFilesConfig :: ConfigFilesConfig
pConfigFilesConfig :: MParser ConfigFilesConfig
dropAndUncaml :: Int -> String -> String
instance Typeable ConfigFile
instance Typeable ConfigFilesConfig
instance Show ConfigFile
instance Read ConfigFile
instance Eq ConfigFile
instance Ord ConfigFile
instance Show ConfigFilesConfig
instance Eq ConfigFilesConfig
module Configuration.Utils.Internal.ConfigFileReader
parseConfigFiles :: (ConfigFileParser μ, FromJSON (α -> α)) => ConfigFilesConfig -> α -> [ConfigFile] -> μ α
readConfigFile :: (ConfigFileParser μ, FromJSON (α -> α)) => ConfigFilesConfig -> ConfigFile -> μ (α -> α)
data ConfigFileFormat
Yaml :: ConfigFileFormat
Json :: ConfigFileFormat
Other :: ConfigFileFormat
loadLocal :: (Functor μ, MonadIO μ, MonadError Text μ, FromJSON (α -> α)) => ConfigFile -> μ (α -> α)
isRemote :: ConfigFile -> Bool
loadRemote :: (ConfigFileParser μ, FromJSON (α -> α)) => ConfigFilesConfig -> ConfigFile -> μ (α -> α)
yamlMimeType :: IsString s => [s]
-- | Defined in RFC 4627
jsonMimeType :: IsString s => [s]
contentType :: ByteString -> ConfigFileFormat
requestHeaders :: Lens' Request RequestHeaders
instance Typeable ConfigFileFormat
instance Show ConfigFileFormat
instance Read ConfigFileFormat
instance Eq ConfigFileFormat
instance Ord ConfigFileFormat
instance Enum ConfigFileFormat
instance Bounded ConfigFileFormat
instance Generic ConfigFileFormat
instance Datatype D1ConfigFileFormat
instance Constructor C1_0ConfigFileFormat
instance Constructor C1_1ConfigFileFormat
instance Constructor C1_2ConfigFileFormat
instance NFData ConfigFileFormat
-- | This module provides a collection of utilities on top of the packages
-- optparse-applicative, aeson, and yaml, for configuring libraries and
-- applications in a composable way.
--
-- The main feature is the integration of command line option parsing and
-- configuration files.
--
-- The purpose is to make management of configurations easy by providing
-- an idiomatic style of defining and deploying configurations in a
-- modular and composable way.
--
-- -- (info message, detailed info message, version string, license text) ---- -- See the documentation of Configuration.Utils.Setup for a way -- how to generate this information automatically from the package -- description during the build process. type PkgInfo = (String, String, String, String) -- | Run an IO action with a configuration that is obtained by updating the -- given default configuration the values defined via command line -- arguments. -- -- In addition to the options defined by the given options parser the -- following options are recognized: -- --