    {-# LANGUAGE DataKinds              #-}
    {-# LANGUAGE FlexibleContexts       #-}
    {-# LANGUAGE RankNTypes             #-}
    {-# LANGUAGE ScopedTypeVariables    #-}
    {-# LANGUAGE TypeFamilies           #-}
    {-# LANGUAGE TypeOperators          #-}

    -- | @since 0.14.1
    module Servant.Server.Generic (
        AsServerT,
        AsServer,
        genericServe,
        genericServeT,
        genericServeTWithContext,
        genericServer,
        genericServerT
      ) where

    import           Data.Kind
                     (Type)
    import           Data.Proxy
                     (Proxy (..))

    import           Servant.Server
    import           Servant.API.Generic
    import           Servant.Server.Internal

    -- | Transform a record of routes into a WAI 'Application'.
    genericServe
        :: forall routes.
           ( HasServer (ToServantApi routes) '[]
           , GenericServant routes AsServer
           , Server (ToServantApi routes) ~ ToServant routes AsServer
           )
        => routes AsServer -> Application
    genericServe :: forall (routes :: Type -> Type).
    (HasServer (ToServantApi routes) '[],
     GenericServant routes AsServer,
     Server (ToServantApi routes) ~ ToServant routes AsServer) =>
    routes AsServer -> Application
    genericServe = Proxy (ToServantApi routes)
    -> Server (ToServantApi routes) -> Application
    forall {k} (api :: k).
    HasServer api '[] =>
    Proxy api -> Server api -> Application
    serve (Proxy (ToServantApi routes)
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy (ToServantApi routes))  (Server (ToServantApi routes) -> Application)
    -> (routes AsServer -> Server (ToServantApi routes))
    -> routes AsServer
    -> Application
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . routes AsServer -> ToServant routes AsServer
    routes AsServer -> Server (ToServantApi routes)
    forall (routes :: Type -> Type).
    GenericServant routes AsServer =>
    routes AsServer -> ToServant routes AsServer
    genericServer

    -- | Transform a record of routes with custom monad into a WAI 'Application',
    --   by providing a transformation to bring each handler back in the 'Handler'
    --   monad.
    genericServeT
      :: forall (routes :: Type -> Type) (m :: Type -> Type).
         ( GenericServant routes (AsServerT m)
         , GenericServant routes AsApi
         , HasServer (ToServantApi routes) '[]
         , ServerT (ToServantApi routes) m ~ ToServant routes (AsServerT m)
         )
      => (forall a. m a -> Handler a) -- ^ 'hoistServer' argument to come back to 'Handler'
      -> routes (AsServerT m)         -- ^ your record full of request handlers
      -> Application
    genericServeT :: forall (routes :: Type -> Type) (m :: Type -> Type).
    (GenericServant routes (AsServerT m), GenericServant routes AsApi,
     HasServer (ToServantApi routes) '[],
     ServerT (ToServantApi routes) m
     ~ ToServant routes (AsServerT m)) =>
    (forall a. m a -> Handler a) -> routes (AsServerT m) -> Application
    genericServeT forall a. m a -> Handler a
    f routes (AsServerT m)
    server = Proxy (ToServantApi routes)
    -> Server (ToServantApi routes) -> Application
    forall {k} (api :: k).
    HasServer api '[] =>
    Proxy api -> Server api -> Application
    serve Proxy (ToServantApi routes)
    p (Server (ToServantApi routes) -> Application)
    -> Server (ToServantApi routes) -> Application
    forall a b. (a -> b) -> a -> b
    $ Proxy (ToServantApi routes)
    -> (forall a. m a -> Handler a)
    -> ServerT (ToServantApi routes) m
    -> Server (ToServantApi routes)
    forall {k} (api :: k) (m :: Type -> Type) (n :: Type -> Type).
    HasServer api '[] =>
    Proxy api
    -> (forall x. m x -> n x) -> ServerT api m -> ServerT api n
    hoistServer Proxy (ToServantApi routes)
    p m x -> Handler x
    forall a. m a -> Handler a
    f (routes (AsServerT m) -> ToServant routes (AsServerT m)
    forall (routes :: Type -> Type) (m :: Type -> Type).
    GenericServant routes (AsServerT m) =>
    routes (AsServerT m) -> ToServant routes (AsServerT m)
    genericServerT routes (AsServerT m)
    server)
      where
        p :: Proxy (ToServantApi routes)
    p = Proxy routes -> Proxy (ToServantApi routes)
    forall (routes :: Type -> Type).
    GenericServant routes AsApi =>
    Proxy routes -> Proxy (ToServantApi routes)
    genericApi (Proxy routes
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy routes)

    -- | Transform a record of routes with custom monad into a WAI 'Application',
    --   while using the given 'Context' to serve the application (contexts are typically
    --   used by auth-related combinators in servant, e.g to hold auth checks) and the given
    --   transformation to map all the handlers back to the 'Handler' monad.
    genericServeTWithContext
      :: forall (routes :: Type -> Type) (m :: Type -> Type) (ctx :: [Type]).
         ( GenericServant routes (AsServerT m)
         , GenericServant routes AsApi
         , HasServer (ToServantApi routes) ctx
         , HasContextEntry (ctx .++ DefaultErrorFormatters) ErrorFormatters
         , ServerT (ToServantApi routes) m ~ ToServant routes (AsServerT m)
         )
      => (forall a. m a -> Handler a) -- ^ 'hoistServer' argument to come back to 'Handler'
      -> routes (AsServerT m)         -- ^ your record full of request handlers
      -> Context ctx                  -- ^ the 'Context' to serve the application with
      -> Application
    genericServeTWithContext :: forall (routes :: Type -> Type) (m :: Type -> Type)
           (ctx :: [Type]).
    (GenericServant routes (AsServerT m), GenericServant routes AsApi,
     HasServer (ToServantApi routes) ctx,
     HasContextEntry (ctx .++ DefaultErrorFormatters) ErrorFormatters,
     ServerT (ToServantApi routes) m
     ~ ToServant routes (AsServerT m)) =>
    (forall a. m a -> Handler a)
    -> routes (AsServerT m) -> Context ctx -> Application
    genericServeTWithContext forall a. m a -> Handler a
    f routes (AsServerT m)
    server Context ctx
    ctx =
      Proxy (ToServantApi routes)
    -> Context ctx -> Server (ToServantApi routes) -> Application
    forall {k} (api :: k) (context :: [Type]).
    (HasServer api context, ServerContext context) =>
    Proxy api -> Context context -> Server api -> Application
    serveWithContext Proxy (ToServantApi routes)
    p Context ctx
    ctx (Server (ToServantApi routes) -> Application)
    -> Server (ToServantApi routes) -> Application
    forall a b. (a -> b) -> a -> b
    $
      Proxy (ToServantApi routes)
    -> Proxy ctx
    -> (forall a. m a -> Handler a)
    -> ServerT (ToServantApi routes) m
    -> Server (ToServantApi routes)
    forall {k} (api :: k) (context :: [Type]) (m :: Type -> Type)
           (n :: Type -> Type).
    HasServer api context =>
    Proxy api
    -> Proxy context
    -> (forall x. m x -> n x)
    -> ServerT api m
    -> ServerT api n
    forall (m :: Type -> Type) (n :: Type -> Type).
    Proxy (ToServantApi routes)
    -> Proxy ctx
    -> (forall x. m x -> n x)
    -> ServerT (ToServantApi routes) m
    -> ServerT (ToServantApi routes) n
    hoistServerWithContext Proxy (ToServantApi routes)
    p Proxy ctx
    pctx m x -> Handler x
    forall a. m a -> Handler a
    f (routes (AsServerT m) -> ToServant routes (AsServerT m)
    forall (routes :: Type -> Type) (m :: Type -> Type).
    GenericServant routes (AsServerT m) =>
    routes (AsServerT m) -> ToServant routes (AsServerT m)
    genericServerT routes (AsServerT m)
    server)
      where
        p :: Proxy (ToServantApi routes)
    p = Proxy routes -> Proxy (ToServantApi routes)
    forall (routes :: Type -> Type).
    GenericServant routes AsApi =>
    Proxy routes -> Proxy (ToServantApi routes)
    genericApi (Proxy routes
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy routes)
        pctx :: Proxy ctx
    pctx = Proxy ctx
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy ctx

    -- | Transform a record of endpoints into a 'Server'.
    genericServer
        :: GenericServant routes AsServer
        => routes AsServer
        -> ToServant routes AsServer
    genericServer :: forall (routes :: Type -> Type).
    GenericServant routes AsServer =>
    routes AsServer -> ToServant routes AsServer
    genericServer = routes AsServer -> ToServant routes AsServer
    forall {k} (routes :: k -> Type) (mode :: k).
    GenericServant routes mode =>
    routes mode -> ToServant routes mode
    toServant

    -- | Transform a record of endpoints into a @'ServerT' m@.
    --
    --  You can see an example usage of this function
    --  <https://docs.servant.dev/en/stable/cookbook/generic/Generic.html#using-generics-together-with-a-custom-monad in the Servant Cookbook>.
    genericServerT
        :: GenericServant routes (AsServerT m)
        => routes (AsServerT m)
        -> ToServant routes (AsServerT m)
    genericServerT :: forall (routes :: Type -> Type) (m :: Type -> Type).
    GenericServant routes (AsServerT m) =>
    routes (AsServerT m) -> ToServant routes (AsServerT m)
    genericServerT = routes (AsServerT m) -> ToServant routes (AsServerT m)
    forall {k} (routes :: k -> Type) (mode :: k).
    GenericServant routes mode =>
    routes mode -> ToServant routes mode
    toServant