yam-web-0.3.0: src/Yam/Web/Swagger.hs
{-# LANGUAGE NoPolyKinds #-}
module Yam.Web.Swagger(
SwaggerConfig(..)
, mkServeWithSwagger
, YamSettings(..)
, defaultYamSettings
) where
import Control.Lens hiding (Context)
import Data.Aeson
import Data.Aeson.Types (typeMismatch)
import Data.Default
import Data.Maybe
import Data.Reflection
import Data.Swagger
import Data.Text (Text)
import Data.Vault.Lazy
import GHC.TypeLits
import Network.Wai
import Servant
import Servant.Swagger
import Servant.Swagger.UI
import Yam.Web.Internal
import Yam.Web.Middleware
data SwaggerUIType = Classic | Jensoleg deriving Show
data SwaggerConfig = SwaggerConfig
{ uiType :: SwaggerUIType
, uiPath :: String
, apiPath :: String
, enabled :: Bool
, apiTitle :: Text
, apiVersion :: Text
, contractName :: Maybe Text
, contractEmail :: Maybe Text
} deriving Show
instance FromJSON SwaggerUIType where
parseJSON v = go <$> parseJSON v
where go :: Text -> SwaggerUIType
go "default" = Classic
go _ = Jensoleg
instance FromJSON SwaggerConfig where
parseJSON (Object v) = SwaggerConfig
<$> v .:? "ui-type" .!= Classic
<*> v .:? "ui-path" .!= "swagger-ui.html"
<*> v .:? "api-path" .!= "swagger.json"
<*> v .:? "enabled" .!= True
<*> v .:? "api-title" .!= ""
<*> v .:? "api-version" .!= "1.0.0"
<*> v .:? "contract-name"
<*> v .:? "contract-email"
parseJSON invalid = typeMismatch "SwaggerConfig" invalid
instance Default SwaggerConfig where
def = fromJust $ decode "{}"
swagger :: (HasSwagger api) => SwaggerConfig -> Proxy (SwaggerSchemaUI dir schema :<|> api) -> Proxy api -> Server api -> Server (SwaggerSchemaUI dir schema :<|> api)
swagger conf _ proxy api = go (uiType conf) (f conf $ toSwagger proxy) :<|> api
where go Jensoleg = jensolegSwaggerSchemaUIServer
go _ = swaggerSchemaUIServer
f SwaggerConfig{..} s = s
& info.title .~ apiTitle
& info.version .~ apiVersion
& info.contact ?~ Contact contractName Nothing contractEmail
mkServeWithSwagger' :: (HasSwagger api, API api) => Vault -> [Middleware] -> SwaggerConfig -> Proxy api -> ServerT api App -> Application
mkServeWithSwagger' vault middlewares conf proxy server =
if enabled conf
then reifyGroup conf $ \p -> mkServe' (\(p0,s0) -> (p,swagger conf p p0 s0)) vault middlewares proxy server
else mkServe' id vault middlewares proxy server
reifyGroup :: SwaggerConfig -> (forall d s. (KnownSymbol d ,KnownSymbol s)=> Proxy (SwaggerSchemaUI d s :<|> api) -> r) -> r
reifyGroup SwaggerConfig{..} f = reifySymbol uiPath $ \pd -> reifySymbol apiPath $ \ps -> f $ group pd ps
group :: Proxy dir -> Proxy schema -> Proxy (SwaggerSchemaUI dir schema :<|> api)
group _ _ = Proxy
data YamSettings = YamSettings
{ vault :: Vault
, middlewares :: [Middleware]
, swaggers :: SwaggerConfig
}
defaultYamSettings :: IO YamSettings
defaultYamSettings = do
lm <- stdLoggerMiddleware
return $ YamSettings empty [lm] def
mkServeWithSwagger :: (HasSwagger api, API api) => YamSettings -> Proxy api -> ServerT api App -> Application
mkServeWithSwagger YamSettings{..} = mkServeWithSwagger' vault middlewares swaggers