yam-web-0.3.2: src/Yam/Web/Swagger.hs
{-# LANGUAGE NoPolyKinds #-}
module Yam.Web.Swagger(
SwaggerConfig(..)
, mkServeWithSwagger
) 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 GHC.TypeLits
import Network.Wai
import Servant
import Servant.Swagger
import Servant.Swagger.UI
import Yam.Web.Internal
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 .:? "type" .!= Classic
<*> v .:? "path" .!= "swagger-ui.html"
<*> v .:? "schema" .!= "swagger.json"
<*> v .:? "enabled" .!= True
<*> v .:? "title" .!= ""
<*> v .:? "version" .!= "1.0.0"
<*> v .:? "name"
<*> v .:? "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, HasServer api context)
=> Proxy api
-> Proxy context
-> Context context
-> Proxy c
-> c
-> [Middleware]
-> SwaggerConfig
-> ServerT api (App c)
-> Application
mkServeWithSwagger proxy pcxt cxt pc c middlewares conf server =
if enabled conf
then reifyGroup conf $ \p -> mkServe' (swagger conf p proxy) p proxy pcxt cxt pc c middlewares server
else mkServe proxy pcxt cxt pc c middlewares 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