{-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE TypeSynonymInstances #-} module Yam( start , App , YamConfig(..) , DataSourceProvider , DataSourceConfig(..) , showText , throwServant , runDb , selectValue ) where import Control.Exception (throw) import Control.Monad.Except import Control.Monad.Logger.CallStack import Control.Monad.Reader import Network.Wai import Network.Wai.Handler.Warp (run) import Yam.Config import Yam.DataSource import Yam.Util import Yam.Web.Swagger type AppM m = ReaderT (YamConfig, Maybe DataSource) (LoggingT m) type App = AppM IO throwServant :: ServantErr -> App a throwServant = lift . throw runDb :: DB App a -> App a runDb a = do (_, ds) <- ask case ds of Nothing -> do logError "DataSource not found" throwServant err401 Just d -> runDB d a start :: (HasSwagger api, HasServer api '[YamConfig]) => YamConfig -> Proxy api -> ServerT api App -> [Middleware] -> Maybe DataSourceProvider -> App a -> LoggingT IO () start conf@YamConfig{..} proxy server middleWares newDs appa = let cxt = (conf :. EmptyContext) in do logInfo "Start Service..." runLogger <- askLoggerIO tryRunDb newDs datasource runLogger $ \ds -> do _ <- runLoggingT (runReaderT appa (conf,ds)) runLogger run port $ foldr (.) id middleWares $ serveWithContextAndSwagger swagger proxy cxt $ hoistServerWithContext proxy (Proxy :: Proxy '[YamConfig]) (go runLogger ds) server where go :: LogFunc -> Maybe DataSource -> App a -> Handler a go r ds a = liftIO $ (`runLoggingT` r) $ runReaderT a (conf, ds) tryRunDb (Just d) ds r a = do logInfo "Initialize Datasource..." liftIO $ runInDB r d ds (a.Just) tryRunDb _ _ _ a = liftIO $ a Nothing