module Amazonka.Send
  ( send,
    sendEither,
    paginate,
    paginateEither,
    await,
    awaitEither,
    sendUnsigned,
    sendUnsignedEither,
  )
where

import Amazonka.Core (AWSPager, AWSRequest, AWSResponse, Error)
import Amazonka.Env (Env, Env' (..))
import qualified Amazonka.HTTP as HTTP
import qualified Amazonka.Pager as Pager
import Amazonka.Prelude
import qualified Amazonka.Waiter as Waiter
import qualified Control.Exception as Exception
import Data.Conduit (ConduitM)
import qualified Data.Conduit as Conduit
import Data.Typeable (Typeable)
import qualified Network.HTTP.Client as Client

-- | Send a request, returning the associated response if successful.
--
-- See 'send'.
sendEither ::
  ( MonadResource m,
    AWSRequest a,
    Typeable a,
    Typeable (AWSResponse a)
  ) =>
  Env ->
  a ->
  m (Either Error (AWSResponse a))
sendEither :: forall (m :: * -> *) a.
(MonadResource m, AWSRequest a, Typeable a,
 Typeable (AWSResponse a)) =>
Env -> a -> m (Either Error (AWSResponse a))
sendEither Env
env =
  forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second forall body. Response body -> body
Client.responseBody) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *) a (withAuth :: * -> *).
(MonadResource m, AWSRequest a, Typeable a,
 Typeable (AWSResponse a), Foldable withAuth) =>
Env' withAuth
-> a -> m (Either Error (ClientResponse (AWSResponse a)))
HTTP.retryRequest Env
env

-- | Send a request, returning the associated response if successful.
--
-- Errors are thrown in 'IO'.
--
-- See 'sendEither'.
send ::
  ( MonadResource m,
    AWSRequest a,
    Typeable a,
    Typeable (AWSResponse a)
  ) =>
  Env ->
  a ->
  m (AWSResponse a)
send :: forall (m :: * -> *) a.
(MonadResource m, AWSRequest a, Typeable a,
 Typeable (AWSResponse a)) =>
Env -> a -> m (AWSResponse a)
send Env
env =
  forall (m :: * -> *) a.
(MonadResource m, AWSRequest a, Typeable a,
 Typeable (AWSResponse a)) =>
Env -> a -> m (Either Error (AWSResponse a))
sendEither Env
env 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

-- | Make a request without signing it. You will almost never need to
-- do this, but some authentication methods
-- (e.g. @sts:AssumeRoleWithWebIdentity@ and @sso:GetRoleCredentials@)
-- require you to exchange a token using an unsigned
-- request. Amazonka's support for these authentication methods calls
-- 'sendUnsigned', and we re-export these functions in case you need
-- to support similar authentication methods in your code.
--
-- See 'sendUnsigned'.
sendUnsignedEither ::
  ( MonadResource m,
    AWSRequest a,
    Typeable a,
    Typeable (AWSResponse a)
  ) =>
  Env' withAuth ->
  a ->
  m (Either Error (AWSResponse a))
sendUnsignedEither :: forall (m :: * -> *) a (withAuth :: * -> *).
(MonadResource m, AWSRequest a, Typeable a,
 Typeable (AWSResponse a)) =>
Env' withAuth -> a -> m (Either Error (AWSResponse a))
sendUnsignedEither Env' withAuth
env =
  forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second forall body. Response body -> body
Client.responseBody) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *) a (withAuth :: * -> *).
(MonadResource m, AWSRequest a, Typeable a,
 Typeable (AWSResponse a), Foldable withAuth) =>
Env' withAuth
-> a -> m (Either Error (ClientResponse (AWSResponse a)))
HTTP.retryRequest (Env' withAuth
env {$sel:auth:Env :: Proxy Auth
auth = forall {k} (t :: k). Proxy t
Proxy})

-- | Make an unsigned request, returning the associated response if successful.
--
-- Errors are thrown in 'IO'.
--
-- See 'sendUnsignedEither'.
sendUnsigned ::
  ( MonadResource m,
    AWSRequest a,
    Typeable a,
    Typeable (AWSResponse a)
  ) =>
  Env' withAuth ->
  a ->
  m (AWSResponse a)
sendUnsigned :: forall (m :: * -> *) a (withAuth :: * -> *).
(MonadResource m, AWSRequest a, Typeable a,
 Typeable (AWSResponse a)) =>
Env' withAuth -> a -> m (AWSResponse a)
sendUnsigned Env' withAuth
env =
  forall (m :: * -> *) a (withAuth :: * -> *).
(MonadResource m, AWSRequest a, Typeable a,
 Typeable (AWSResponse a)) =>
Env' withAuth -> a -> m (Either Error (AWSResponse a))
sendUnsignedEither Env' withAuth
env 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

-- | Repeatedly send a request, automatically setting markers and performing pagination.
--
-- Exits on the first encountered error.
--
-- See 'paginate'.
paginateEither ::
  ( MonadResource m,
    AWSPager a,
    Typeable a,
    Typeable (AWSResponse a)
  ) =>
  Env ->
  a ->
  ConduitM () (AWSResponse a) m (Either Error ())
paginateEither :: forall (m :: * -> *) a.
(MonadResource m, AWSPager a, Typeable a,
 Typeable (AWSResponse a)) =>
Env -> a -> ConduitM () (AWSResponse a) m (Either Error ())
paginateEither Env
env = a -> ConduitT () (AWSResponse a) m (Either Error ())
go
  where
    go :: a -> ConduitT () (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.
(MonadResource m, AWSRequest a, Typeable a,
 Typeable (AWSResponse a)) =>
Env -> a -> m (Either Error (AWSResponse a))
sendEither Env
env 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 () (AWSResponse a) m (Either Error ())
go (forall a. AWSPager a => a -> AWSResponse a -> Maybe a
Pager.page a
rq AWSResponse a
rs)

-- | Repeatedly send a request, automatically setting markers and performing pagination.
-- Exits on the first encountered error.
--
-- Errors are thrown in 'IO'.
--
-- See 'paginateEither'.
paginate ::
  ( MonadResource m,
    AWSPager a,
    Typeable a,
    Typeable (AWSResponse a)
  ) =>
  Env ->
  a ->
  ConduitM () (AWSResponse a) m ()
paginate :: forall (m :: * -> *) a.
(MonadResource m, AWSPager a, Typeable a,
 Typeable (AWSResponse a)) =>
Env -> a -> ConduitM () (AWSResponse a) m ()
paginate Env
env =
  forall (m :: * -> *) a.
(MonadResource m, AWSPager a, Typeable a,
 Typeable (AWSResponse a)) =>
Env -> a -> ConduitM () (AWSResponse a) m (Either Error ())
paginateEither Env
env 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

-- | Poll the API with the supplied request until a specific 'Wait' condition
-- is fulfilled.
--
-- See 'await'.
awaitEither ::
  ( MonadResource m,
    AWSRequest a,
    Typeable a
  ) =>
  Env ->
  Waiter.Wait a ->
  a ->
  m (Either Error Waiter.Accept)
awaitEither :: forall (m :: * -> *) a.
(MonadResource m, AWSRequest a, Typeable a) =>
Env -> Wait a -> a -> m (Either Error Accept)
awaitEither = forall (m :: * -> *) a (withAuth :: * -> *).
(MonadResource m, AWSRequest a, Typeable a, Foldable withAuth) =>
Env' withAuth -> Wait a -> a -> m (Either Error Accept)
HTTP.awaitRequest

-- | Poll the API with the supplied request until a specific 'Wait' condition
-- is fulfilled.
--
-- Errors are thrown in 'IO'.
--
-- See 'awaitEither'.
await ::
  ( MonadResource m,
    AWSRequest a,
    Typeable a
  ) =>
  Env ->
  Waiter.Wait a ->
  a ->
  m Waiter.Accept
await :: forall (m :: * -> *) a.
(MonadResource m, AWSRequest a, Typeable a) =>
Env -> Wait a -> a -> m Accept
await Env
env Wait a
wait =
  forall (m :: * -> *) a.
(MonadResource m, AWSRequest a, Typeable a) =>
Env -> Wait a -> a -> m (Either Error Accept)
awaitEither Env
env 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