module Network.API.Builder.API (
API
, APIT
, execAPI
, runAPI
, runRoute
, sendRoute
, routeResponse
, routeRequest
, liftEither
, liftManager
, liftBuilder
, liftState
, name
, baseURL
, customizeRoute
, customizeRequest ) where
import Network.API.Builder.Builder
import Network.API.Builder.Error
import Network.API.Builder.Receive
import Network.API.Builder.Routes
import Network.API.Builder.Send
import Data.Bifunctor
import Control.Exception
import Control.Monad.IO.Class (MonadIO, liftIO)
import Control.Monad.Trans.Class (lift)
import Control.Monad.Trans.Either
import Control.Monad.Trans.Reader
import Control.Monad.Trans.State
import Data.ByteString.Lazy (ByteString)
import Data.Text (Text)
import Network.HTTP.Conduit
type API s e a = APIT s e IO a
type APIT s e m a = EitherT (APIError e) (ReaderT Manager (StateT Builder (StateT s m))) a
liftEither :: Monad m => EitherT (APIError e) (ReaderT Manager (StateT Builder (StateT s m))) a -> APIT s e m a
liftEither = id
liftManager :: Monad m => ReaderT Manager (StateT Builder (StateT s m)) a -> APIT s e m a
liftManager = lift
liftBuilder :: Monad m => StateT Builder (StateT s m) a -> APIT s e m a
liftBuilder = lift . lift
liftState :: Monad m => StateT s m a -> APIT s e m a
liftState = lift . lift . lift
execAPI :: MonadIO m
=> Builder
-> s
-> APIT s e m a
-> m (Either (APIError e) a)
execAPI b s api = do
m <- liftIO $ newManager conduitManagerSettings
(res, _, _) <- runAPI b m s api
liftIO $ closeManager m
return res
runAPI :: MonadIO m
=> Builder
-> Manager
-> s
-> APIT s e m a
-> m (Either (APIError e) a, Builder, s)
runAPI b m s api = do
((res, b'), s') <- runStateT (runStateT (runReaderT (runEitherT api) m) b) s
return (res, b', s')
runRoute :: (Receivable a, ErrorReceivable e, MonadIO m) => Route -> APIT s e m a
runRoute = sendRoute ()
routeResponse :: (MonadIO m, ErrorReceivable e) => Route -> APIT s e m (Response ByteString)
routeResponse = sendRoute ()
eitherOr :: Maybe a -> b -> Either b a
a `eitherOr` b =
case a of
Just x -> Right x
Nothing -> Left b
sendRoute :: (MonadIO m, Sendable t, ErrorReceivable e, Receivable r) => t -> Route -> APIT s e m r
sendRoute s r = do
builder <- liftBuilder get
manager <- liftManager ask
req <- hoistEither $ send builder r s `eitherOr` InvalidURLError
response <- liftIO $ try $ httpLbs req manager
res <- hoistEither $ first HTTPError response
hoistEither $ receive res
routeRequest :: Builder -> Route -> Maybe Request
routeRequest b route = send b route ()
name :: Monad m => Text -> APIT s e m ()
name t = liftBuilder $ modify (\b -> b { _name = t })
baseURL :: Monad m => Text -> APIT s e m ()
baseURL t = liftBuilder $ modify (\b -> b { _baseURL = t })
customizeRoute :: Monad m => (Route -> Route) -> APIT s e m ()
customizeRoute f = liftBuilder $ modify (\b -> b { _customizeRoute = f })
customizeRequest :: Monad m => (Request -> Request) -> APIT s e m ()
customizeRequest f = liftBuilder $ modify (\b -> b { _customizeRequest = f })