{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
module Servant.Swagger.UI.Core (
SwaggerSchemaUI,
SwaggerSchemaUI',
SwaggerUiHtml(..),
swaggerSchemaUIServerImpl,
Handler,
) where
import Data.ByteString (ByteString)
import Data.Swagger (Swagger)
import GHC.TypeLits (KnownSymbol, Symbol, symbolVal)
import Network.Wai.Application.Static (embeddedSettings, staticApp)
import Servant
import Servant.HTML.Blaze (HTML)
import Text.Blaze (ToMarkup (..))
import qualified Data.Text as T
type SwaggerSchemaUI (dir :: Symbol) (schema :: Symbol) =
SwaggerSchemaUI' dir (schema :> Get '[JSON] Swagger)
type SwaggerSchemaUI' (dir :: Symbol) (api :: *) =
api
:<|> dir :>
( Get '[HTML] (SwaggerUiHtml dir api)
:<|> "index.html" :> Get '[HTML] (SwaggerUiHtml dir api)
:<|> Raw
)
data SwaggerUiHtml (dir :: Symbol) (api :: *) = SwaggerUiHtml T.Text
instance (KnownSymbol dir, HasLink api, Link ~ MkLink api Link, IsElem api api)
=> ToMarkup (SwaggerUiHtml dir api)
where
toMarkup (SwaggerUiHtml template) = preEscapedToMarkup
$ T.replace "SERVANT_SWAGGER_UI_SCHEMA" schema
$ T.replace "SERVANT_SWAGGER_UI_DIR" dir
$ template
where
schema = T.pack $ uriPath . linkURI $ safeLink proxyApi proxyApi
dir = T.pack $ symbolVal (Proxy :: Proxy dir)
proxyApi = Proxy :: Proxy api
swaggerSchemaUIServerImpl
:: (Server api ~ Handler Swagger)
=> T.Text -> [(FilePath, ByteString)]
-> Swagger -> Server (SwaggerSchemaUI' dir api)
swaggerSchemaUIServerImpl indexTemplate files swagger = return swagger
:<|> return (SwaggerUiHtml indexTemplate)
:<|> return (SwaggerUiHtml indexTemplate)
:<|> rest
where
rest = Tagged $ staticApp $ embeddedSettings files