packages feed

servant-checked-exceptions 2.1.0.0 → 2.2.0.0

raw patch · 3 files changed

+175/−3 lines, 3 filesdep ~basedep ~servantdep ~servant-checked-exceptions-corenew-component:exe:servant-checked-exceptions-example-envelopetPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base, servant, servant-checked-exceptions-core, servant-server, world-peace

API changes (from Hackage documentation)

Files

CHANGELOG.md view
@@ -1,3 +1,20 @@+## 2.2.0.0++*   Add the `EnvelopeT` monad transformer. [#32]++*   Add a few combinators for `Envelope`:++        - `envelopeRemove`+        - `envelopeHandle`+        - `relaxEnvelope`+        - `liftA2Envelope`+        - `bindEnvelope`++    [#32]++*   Add an example of using `EnvelopeT` in+    `servant-checked-exceptions/example/EnvelopeT.hs`. [#32]+ ## 2.1.0.0  *   Add support for servant-0.16 and remove support for all previous version of
+ example/EnvelopeT.hs view
@@ -0,0 +1,133 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE EmptyCase #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE InstanceSigs #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UndecidableInstances #-}++-- | This example is very similar to @./Server.hs@, but it is making use of+-- 'EnvelopeT' instead of just 'Envelope'.++module Main where++import Control.Monad.IO.Class (MonadIO(liftIO))+import Data.Char (toLower)+import Data.Proxy (Proxy(Proxy))+import Network.Wai (Application)+import Network.Wai.Handler.Warp (run)+import Servant (Handler, (:<|>)((:<|>)), ServerT, serve)++import Servant.Checked.Exceptions+  ( Envelope+  , EnvelopeT+  , IsMember+  , pureErrEnvelope+  , pureSuccEnvelope+  , relaxEnvT+  , runEnvelopeT+  , throwErrEnvT+  )++import Api+  ( Api+  , BadSearchTermErr(BadSearchTermErr)+  , IncorrectCapitalization(IncorrectCapitalization)+  , SearchQuery(SearchQuery)+  , SearchResponse+  , port+  )++-- | This is our server root for the 'ServerT' for 'Api'.  We only have two+-- handlers, 'postStrictSearch' and 'postLaxSearch'.+serverRoot :: ServerT Api Handler+serverRoot = postStrictSearch :<|> postLaxSearch :<|> postNoErrSearch++-- | This is the handler for 'Api.ApiStrictSearch'.+postStrictSearch+  :: SearchQuery+  -> Handler (Envelope '[BadSearchTermErr, IncorrectCapitalization] SearchResponse)+postStrictSearch query =+  runEnvelopeT $ do+    res <- checkQueryInDb query+    relaxEnvT $ doubleCheckCapitalization query+    doubleCheckCapitalizationGeneral query+    pure res++-- | Check that the input 'SearchQuery' is in the DB.  (The DB is just a list+-- of greetings.)+--+-- If the input 'SearchQuery' is in the DB, return the string @"greeting"@.+-- Otherwise, throw an envelope error 'BadSearchTermErr'.+--+-- Note that this function says that it might also return an+-- 'IncorrectCapitalization' error, but it doesn't actually.  This is just for+-- demonstration.+--+-- Also note that our underlying Monad here is 'Handler'.+checkQueryInDb+  :: SearchQuery+  -> EnvelopeT '[BadSearchTermErr, IncorrectCapitalization] Handler SearchResponse+checkQueryInDb (SearchQuery query) = do+  liftIO $ putStrLn "querying DB..."+  let lowerQuery = fmap toLower query+  case lowerQuery `elem` ["hello", "goodbye", "goodnight"] of+    True -> pure "greeting"+    False -> throwErrEnvT BadSearchTermErr++-- | Check the first letter of 'SearchQuery' to make sure that it is lowercase.+--+-- If it is not lowercase, throw 'IncorrectCapitalization'.+--+-- Note that 'relaxEnvT' needs to be called on the result of this to use it in+-- do notation with the above 'checkQueryInDb'.  This is because the result of+-- this is technically a different monad than the result of 'checkQueryInDb',+-- because the error types are different.+--+-- Also note that since we only use 'MonadIO' for this, our underlying monad is+-- polymorphic.  We don't specialize it to 'Handler'.+doubleCheckCapitalization+  :: MonadIO m => SearchQuery -> EnvelopeT '[IncorrectCapitalization] m ()+doubleCheckCapitalization (SearchQuery []) = liftIO $ putStrLn "search query empty"+doubleCheckCapitalization (SearchQuery (q:query)) =+  if toLower q == q+    then pure ()+    else throwErrEnvT IncorrectCapitalization++-- | This is just like 'doubleCheckCapitalization' above, but we use the+-- 'IsMember' constraint to make this function more general.  In+-- 'postStrictSearch', you can see that we don't have to call 'relaxEnvT' when+-- using this function.+doubleCheckCapitalizationGeneral+  :: IsMember IncorrectCapitalization es => SearchQuery -> EnvelopeT es Handler ()+doubleCheckCapitalizationGeneral _ = throwErrEnvT IncorrectCapitalization++-- | This doesn't do anything interesting.+--+-- See 'postLaxSearch' in @./Server.hs@ for an example using 'Envelope'.+postLaxSearch+  :: SearchQuery+  -> Handler (Envelope '[BadSearchTermErr] SearchResponse)+postLaxSearch _ = pureSuccEnvelope "good"++-- | This doesn't do anything interesting.+--+-- See 'postNoErrSearch' in @./Server.hs@ for an example using 'Envelope'.+postNoErrSearch :: SearchQuery -> Handler (Envelope '[] SearchResponse)+postNoErrSearch (SearchQuery _) = pureSuccEnvelope "good"++-- | Create a WAI 'Application'.+app :: Application+app = serve (Proxy :: Proxy Api) serverRoot++-- | Run the WAI 'Application' using 'run' on the port defined by 'port'.+main :: IO ()+main = run port app
servant-checked-exceptions.cabal view
@@ -1,5 +1,5 @@ name:                servant-checked-exceptions-version:             2.1.0.0+version:             2.2.0.0 synopsis:            Checked exceptions for Servant APIs. description:         Please see <https://github.com/cdepillabout/servant-checked-exceptions#readme README.md>. homepage:            https://github.com/cdepillabout/servant-checked-exceptions@@ -30,12 +30,12 @@                      , bytestring                      , http-types                      , servant >= 0.16-                     , servant-checked-exceptions-core+                     , servant-checked-exceptions-core >= 2.2.0.0                      , servant-client >= 0.16                      , servant-client-core >= 0.16                      , servant-server >= 0.16                      , wai-                     , world-peace+                     , world-peace >= 1.0.0.0   default-language:    Haskell2010   ghc-options:         -Wall -fwarn-incomplete-uni-patterns -fwarn-incomplete-record-updates -fwarn-monomorphism-restriction   other-extensions:    QuasiQuotes@@ -65,6 +65,28 @@  executable servant-checked-exceptions-example-server   main-is:             Server.hs+  other-modules:       Api+  hs-source-dirs:      example+  build-depends:       base+                     , aeson+                     , http-api-data+                     , http-types+                     , servant+                     , servant-checked-exceptions+                     , servant-server+                     , text+                     , wai+                     , warp+  default-language:    Haskell2010+  ghc-options:         -Wall -threaded -rtsopts -with-rtsopts=-N++  if flag(buildexample)+    buildable:         True+  else+    buildable:         False++executable servant-checked-exceptions-example-envelopet+  main-is:             EnvelopeT.hs   other-modules:       Api   hs-source-dirs:      example   build-depends:       base