-- | Plugins to handle exceptions
module Mig.Extra.Plugin.Exception (
  handleRespError,
) where

import Control.Exception (Exception)
import Control.Monad.Catch (MonadCatch, try)
import Control.Monad.IO.Class

import Mig.Core

{-| Catches the run-time exceptions and converts them to responses.
This way of using errors is not recommended. Better use response of the type @RespOr@.
-}
handleRespError ::
  forall a b m.
  (MonadIO m, MonadCatch m, Exception a, IsResp b) =>
  (a -> m b) ->
  Plugin m
handleRespError :: forall a b (m :: * -> *).
(MonadIO m, MonadCatch m, Exception a, IsResp b) =>
(a -> m b) -> Plugin m
handleRespError a -> m b
handle = forall (m :: * -> *). MonadIO m => PluginFun m -> Plugin m
fromPluginFun forall a b. (a -> b) -> a -> b
$ \ServerFun m
f -> \Request
req -> do
  Either a (Maybe Response)
eResult <- forall (m :: * -> *) e a.
(MonadCatch m, Exception e) =>
m a -> m (Either e a)
try @m @a (ServerFun m
f Request
req)
  case Either a (Maybe Response)
eResult of
    Right Maybe Response
res -> forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe Response
res
    Left a
err -> forall a. a -> Maybe a
Just forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. IsResp a => a -> Response
toResponse forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a -> m b
handle a
err