module Control.Monad.AWS
  ( MonadAWS (..)
  , send
  , paginate
  , paginateEither
  , await

    -- * Concrete transformers
  , EnvT
  , runEnvT
  , MockT
  , runMockT
  ) where

import Amazonka.Prelude

import Amazonka.Core (AWSPager, AWSRequest, AWSResponse, Error)
import qualified Amazonka.Pager as Pager
import qualified Amazonka.Waiter as Waiter
import qualified Control.Exception as Exception
import Control.Monad.AWS.Class
import Control.Monad.AWS.EnvT
import Control.Monad.AWS.MockT
import Data.Conduit (ConduitM)
import qualified Data.Conduit as Conduit
import Data.Typeable (Typeable)

-- | Version of 'Amazonka.send' built on our 'sendEither'
--
-- @since 0.1.0.0
send
  :: ( MonadIO m
     , MonadAWS m
     , AWSRequest a
     , Typeable a
     , Typeable (AWSResponse a)
     )
  => a
  -> m (AWSResponse a)
send :: forall (m :: * -> *) a.
(MonadIO m, MonadAWS m, AWSRequest a, Typeable a,
 Typeable (AWSResponse a)) =>
a -> m (AWSResponse a)
send = forall (m :: * -> *) a.
(MonadAWS m, AWSRequest a, Typeable a, Typeable (AWSResponse a)) =>
a -> m (Either Error (AWSResponse a))
sendEither forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> forall (m :: * -> *) a. MonadIO m => Either Error a -> m a
hoistEither

-- | Version of 'Amazonka.paginateEither' built on our 'sendEither'
--
-- @since 0.1.0.0
paginateEither
  :: (MonadAWS m, AWSPager a, Typeable a, Typeable (AWSResponse a))
  => a
  -> ConduitM () (AWSResponse a) m (Either Error ())
paginateEither :: forall (m :: * -> *) a.
(MonadAWS m, AWSPager a, Typeable a, Typeable (AWSResponse a)) =>
a -> ConduitM () (AWSResponse a) m (Either Error ())
paginateEither = forall {m :: * -> *} {a} {i}.
(MonadAWS m, Typeable a, Typeable (AWSResponse a), AWSPager a) =>
a -> ConduitT i (AWSResponse a) m (Either Error ())
go
 where
  go :: a -> ConduitT i (AWSResponse a) m (Either Error ())
go a
rq =
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (forall (m :: * -> *) a.
(MonadAWS m, AWSRequest a, Typeable a, Typeable (AWSResponse a)) =>
a -> m (Either Error (AWSResponse a))
sendEither a
rq) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
      Left Error
err -> forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall a b. a -> Either a b
Left Error
err)
      Right AWSResponse a
rs -> do
        forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
Conduit.yield AWSResponse a
rs
        forall b a. b -> (a -> b) -> Maybe a -> b
maybe (forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall a b. b -> Either a b
Right ())) a -> ConduitT i (AWSResponse a) m (Either Error ())
go (forall a. AWSPager a => a -> AWSResponse a -> Maybe a
Pager.page a
rq AWSResponse a
rs)

-- | Version of 'Amazonka.paginate' built on our 'paginateEither'
--
-- @since 0.1.0.0
paginate
  :: ( MonadIO m
     , MonadAWS m
     , AWSPager a
     , Typeable a
     , Typeable (AWSResponse a)
     )
  => a
  -> ConduitM () (AWSResponse a) m ()
paginate :: forall (m :: * -> *) a.
(MonadIO m, MonadAWS m, AWSPager a, Typeable a,
 Typeable (AWSResponse a)) =>
a -> ConduitM () (AWSResponse a) m ()
paginate =
  forall (m :: * -> *) a.
(MonadAWS m, AWSPager a, Typeable a, Typeable (AWSResponse a)) =>
a -> ConduitM () (AWSResponse a) m (Either Error ())
paginateEither forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> forall (m :: * -> *) a. MonadIO m => Either Error a -> m a
hoistEither

-- | Version of 'Amazonka.await' built on our 'awaitEither'
--
-- @since 0.1.0.0
await
  :: (MonadIO m, MonadAWS m, AWSRequest a, Typeable a)
  => Waiter.Wait a
  -> a
  -> m Waiter.Accept
await :: forall (m :: * -> *) a.
(MonadIO m, MonadAWS m, AWSRequest a, Typeable a) =>
Wait a -> a -> m Accept
await Wait a
wait = forall (m :: * -> *) a.
(MonadAWS m, AWSRequest a, Typeable a) =>
Wait a -> a -> m (Either Error Accept)
awaitEither Wait a
wait forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> forall (m :: * -> *) a. MonadIO m => Either Error a -> m a
hoistEither

hoistEither :: MonadIO m => Either Error a -> m a
hoistEither :: forall (m :: * -> *) a. MonadIO m => Either Error a -> m a
hoistEither = forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall e a. Exception e => e -> IO a
Exception.throwIO) forall (f :: * -> *) a. Applicative f => a -> f a
pure