servant-checked-exceptions 0.2.0.0 → 0.3.0.0
raw patch · 4 files changed
+70/−25 lines, 4 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Servant.Checked.Exceptions.Internal.Servant.Client: instance forall k (es :: [GHC.Types.*]) e (api :: k). Servant.Client.HasClient (Servant.Checked.Exceptions.Internal.Servant.API.Throwing (Servant.Checked.Exceptions.Internal.Util.Snoc es e) Servant.API.Sub.:> api) => Servant.Client.HasClient (Servant.Checked.Exceptions.Internal.Servant.API.Throwing es Servant.API.Sub.:> (Servant.Checked.Exceptions.Internal.Servant.API.Throws e Servant.API.Sub.:> api))
- Servant.Checked.Exceptions.Internal.Servant.Server: instance forall k (es :: [GHC.Types.*]) e (api :: k) (context :: [*]). Servant.Server.Internal.HasServer (Servant.Checked.Exceptions.Internal.Servant.API.Throwing (Servant.Checked.Exceptions.Internal.Util.Snoc es e) Servant.API.Sub.:> api) context => Servant.Server.Internal.HasServer (Servant.Checked.Exceptions.Internal.Servant.API.Throwing es Servant.API.Sub.:> (Servant.Checked.Exceptions.Internal.Servant.API.Throws e Servant.API.Sub.:> api)) context
+ Servant.Checked.Exceptions.Internal.Servant.Client: instance Servant.Client.HasClient ((Servant.Checked.Exceptions.Internal.Servant.API.Throwing es Servant.API.Sub.:> api1) Servant.API.Alternative.:<|> (Servant.Checked.Exceptions.Internal.Servant.API.Throwing es Servant.API.Sub.:> api2)) => Servant.Client.HasClient (Servant.Checked.Exceptions.Internal.Servant.API.Throwing es Servant.API.Sub.:> (api1 Servant.API.Alternative.:<|> api2))
+ Servant.Checked.Exceptions.Internal.Servant.Client: instance forall k k1 (es :: [GHC.Types.*]) (api :: k1) (apis :: k). Servant.Client.HasClient (Servant.Checked.Exceptions.Internal.Servant.API.ThrowingNonterminal (Servant.Checked.Exceptions.Internal.Servant.API.Throwing es Servant.API.Sub.:> (api Servant.API.Sub.:> apis))) => Servant.Client.HasClient (Servant.Checked.Exceptions.Internal.Servant.API.Throwing es Servant.API.Sub.:> (api Servant.API.Sub.:> apis))
+ Servant.Checked.Exceptions.Internal.Servant.Server: instance Servant.Server.Internal.HasServer ((Servant.Checked.Exceptions.Internal.Servant.API.Throwing es Servant.API.Sub.:> api1) Servant.API.Alternative.:<|> (Servant.Checked.Exceptions.Internal.Servant.API.Throwing es Servant.API.Sub.:> api2)) context => Servant.Server.Internal.HasServer (Servant.Checked.Exceptions.Internal.Servant.API.Throwing es Servant.API.Sub.:> (api1 Servant.API.Alternative.:<|> api2)) context
+ Servant.Checked.Exceptions.Internal.Servant.Server: instance forall k k1 (es :: [GHC.Types.*]) (api :: k1) (apis :: k) (context :: [*]). Servant.Server.Internal.HasServer (Servant.Checked.Exceptions.Internal.Servant.API.ThrowingNonterminal (Servant.Checked.Exceptions.Internal.Servant.API.Throwing es Servant.API.Sub.:> (api Servant.API.Sub.:> apis))) context => Servant.Server.Internal.HasServer (Servant.Checked.Exceptions.Internal.Servant.API.Throwing es Servant.API.Sub.:> (api Servant.API.Sub.:> apis)) context
Files
- servant-checked-exceptions.cabal +1/−1
- src/Servant/Checked/Exceptions/Internal/Servant/API.hs +16/−1
- src/Servant/Checked/Exceptions/Internal/Servant/Client.hs +27/−12
- src/Servant/Checked/Exceptions/Internal/Servant/Server.hs +26/−11
servant-checked-exceptions.cabal view
@@ -1,5 +1,5 @@ name: servant-checked-exceptions-version: 0.2.0.0+version: 0.3.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
src/Servant/Checked/Exceptions/Internal/Servant/API.hs view
@@ -1,5 +1,7 @@ {-# LANGUAGE DataKinds #-}-{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-} {- | Module : Servant.Checked.Exceptions.Internal.Servant.API@@ -16,6 +18,10 @@ module Servant.Checked.Exceptions.Internal.Servant.API where +import Servant.API ((:>))++import Servant.Checked.Exceptions.Internal.Util (Snoc)+ -- | 'Throws' is used in Servant API definitions and signifies that an API will -- throw the given error. --@@ -28,3 +34,12 @@ -- | This is used internally and should not be used by end-users. data Throwing (e :: [*])++-- | Used by the 'HasServer' and 'HasClient' instances for+-- @'Throwing' es ':>' api ':>' apis@ to detect @'Throwing' es@ followed+-- immediately by @'Throws' e@.+type family ThrowingNonterminal api where+ ThrowingNonterminal (Throwing es :> Throws e :> api) =+ Throwing (Snoc es e) :> api+ ThrowingNonterminal (Throwing es :> c :> api) =+ c :> Throwing es :> api
src/Servant/Checked/Exceptions/Internal/Servant/Client.hs view
@@ -27,14 +27,13 @@ module Servant.Checked.Exceptions.Internal.Servant.Client where import Data.Proxy (Proxy(Proxy))-import Servant.API (Verb, (:>))+import Servant.API (Verb, (:>), (:<|>)) import Servant.Client (HasClient(clientWithRoute, Client)) import Servant.Common.Req (Req) import Servant.Checked.Exceptions.Internal.Envelope (Envelope) import Servant.Checked.Exceptions.Internal.Servant.API- (Throws, Throwing)-import Servant.Checked.Exceptions.Internal.Util (Snoc)+ (Throws, Throwing, ThrowingNonterminal) -- TODO: Make sure to also account for when headers are being used. @@ -63,17 +62,33 @@ clientWithRoute Proxy = clientWithRoute (Proxy :: Proxy (Verb method status ctypes (Envelope es a))) +-- | When @'Throwing' es@ comes before ':<|>', push @'Throwing' es@ into each+-- branch of the API.+instance HasClient ((Throwing es :> api1) :<|> (Throwing es :> api2)) =>+ HasClient (Throwing es :> (api1 :<|> api2)) where++ type Client (Throwing es :> (api1 :<|> api2)) =+ Client ((Throwing es :> api1) :<|> (Throwing es :> api2))++ clientWithRoute+ :: Proxy (Throwing es :> (api1 :<|> api2))+ -> Req+ -> Client ((Throwing es :> api1) :<|> (Throwing es :> api2))+ clientWithRoute _ =+ clientWithRoute (Proxy :: Proxy ((Throwing es :> api1) :<|> (Throwing es :> api2)))+ -- | When a @'Throws' e@ comes immediately after a @'Throwing' es@, 'Snoc' the--- @e@ onto the @es@.-instance (HasClient (Throwing (Snoc es e) :> api)) =>- HasClient (Throwing es :> Throws e :> api) where+-- @e@ onto the @es@. Otherwise, if @'Throws' e@ comes before any other+-- combinator, push it down so it is closer to the 'Verb'.+instance HasClient (ThrowingNonterminal (Throwing es :> api :> apis)) =>+ HasClient (Throwing es :> api :> apis) where - type Client (Throwing es :> Throws e :> api) =- Client (Throwing (Snoc es e) :> api)+ type Client (Throwing es :> api :> apis) =+ Client (ThrowingNonterminal (Throwing es :> api :> apis)) clientWithRoute- :: Proxy (Throwing es :> Throws e :> api)+ :: Proxy (Throwing es :> api :> apis) -> Req- -> Client (Throwing (Snoc es e) :> api)- clientWithRoute Proxy =- clientWithRoute (Proxy :: Proxy (Throwing (Snoc es e) :> api))+ -> Client (ThrowingNonterminal (Throwing es :> api :> apis))+ clientWithRoute _ =+ clientWithRoute (Proxy :: Proxy (ThrowingNonterminal (Throwing es :> api :> apis)))
src/Servant/Checked/Exceptions/Internal/Servant/Server.hs view
@@ -30,12 +30,11 @@ import Servant.Server.Internal.Router (Router) import Servant.Server.Internal.RoutingApplication (Delayed) import Servant- (Context, Handler, HasServer(..), ServerT, Verb, (:>))+ (Context, Handler, HasServer(..), ServerT, Verb, (:>), (:<|>)) import Servant.Checked.Exceptions.Internal.Envelope (Envelope) import Servant.Checked.Exceptions.Internal.Servant.API- (Throws, Throwing)-import Servant.Checked.Exceptions.Internal.Util (Snoc)+ (Throws, Throwing, ThrowingNonterminal) -- TODO: Make sure to also account for when headers are being used. @@ -68,17 +67,33 @@ -> Router env route _ = route (Proxy :: Proxy (Verb method status ctypes (Envelope es a))) +-- | When @'Throwing' es@ comes before ':<|>', push @'Throwing' es@ into each+-- branch of the API.+instance HasServer ((Throwing es :> api1) :<|> (Throwing es :> api2)) context =>+ HasServer (Throwing es :> (api1 :<|> api2)) context where++ type ServerT (Throwing es :> (api1 :<|> api2)) m =+ ServerT ((Throwing es :> api1) :<|> (Throwing es :> api2)) m++ route+ :: Proxy (Throwing es :> (api1 :<|> api2))+ -> Context context+ -> Delayed env (ServerT ((Throwing es :> api1) :<|> (Throwing es :> api2)) Handler)+ -> Router env+ route _ = route (Proxy :: Proxy ((Throwing es :> api1) :<|> (Throwing es :> api2)))+ -- | When a @'Throws' e@ comes immediately after a @'Throwing' es@, 'Snoc' the--- @e@ onto the @es@.-instance (HasServer (Throwing (Snoc es e) :> api) context) =>- HasServer (Throwing es :> Throws e :> api) context where+-- @e@ onto the @es@. Otherwise, if @'Throws' e@ comes before any other+-- combinator, push it down so it is closer to the 'Verb'.+instance HasServer (ThrowingNonterminal (Throwing es :> api :> apis)) context =>+ HasServer (Throwing es :> api :> apis) context where - type ServerT (Throwing es :> Throws e :> api) m =- ServerT (Throwing (Snoc es e) :> api) m+ type ServerT (Throwing es :> api :> apis) m =+ ServerT (ThrowingNonterminal (Throwing es :> api :> apis)) m route- :: Proxy (Throwing es :> Throws e :> api)+ :: Proxy (Throwing es :> api :> apis) -> Context context- -> Delayed env (ServerT (Throwing (Snoc es e) :> api) Handler)+ -> Delayed env (ServerT (ThrowingNonterminal (Throwing es :> api :> apis)) Handler) -> Router env- route _ = route (Proxy :: Proxy (Throwing (Snoc es e) :> api))+ route _ = route (Proxy :: Proxy (ThrowingNonterminal (Throwing es :> api :> apis)))