packages feed

servant-polysemy-0.1.0: example/ServerWithSwagger.hs

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
module Main (main) where

import Control.Lens.Operators
import Data.Swagger (Swagger, description, host, info, license, title, version)
import Data.Text (Text)
import qualified Data.Text as T
import Data.Version (Version, showVersion)
import qualified Paths_servant_polysemy as Paths
import Polysemy
import Polysemy.Error
import Servant
import Servant.Polysemy.Server
import Servant.Swagger (toSwagger)
import Servant.Swagger.UI (SwaggerSchemaUI, swaggerSchemaUIServer)

type MyApi = "api" :> "v1" :> "version" :> Get '[JSON] Version

type SwaggerDocs = "api" :> "v1" :> SwaggerSchemaUI "swagger-ui" "swagger.json"

type MyApiWithSwagger =
  MyApi
  :<|> SwaggerDocs
  :<|> "api" :> "v1" :> Redirect 302 Text -- Redirect /api/v1 to the swagger docs
  :<|> "api" :> Redirect 302 Text -- Redirect /api to the swagger docs
  :<|> Redirect 302 Text -- Redirect / to the swagger docs

myServer :: Member (Embed IO) r => ServerT MyApi (Sem (Error ServerError ': r))
myServer = do
  embed $ putStrLn $ "Returning version " <> showVersion Paths.version
  pure Paths.version

mySwagger :: Swagger
mySwagger = toSwagger (Proxy @MyApi)
  & info.title       .~ "My API"
  & info.version     .~ (T.pack . showVersion) Paths.version
  & info.description ?~ "This is just an example API."
  & info.license     ?~ "Public Domain"
  & host             ?~ "localhost:8080"

mySwaggerServer :: Member (Embed IO) r => ServerT MyApiWithSwagger (Sem (Error ServerError ': r))
mySwaggerServer =
  myServer
  :<|> hoistServerIntoSem @SwaggerDocs (swaggerSchemaUIServer mySwagger)
  :<|> redirect "/api/v1/swagger-ui"
  :<|> redirect "/api/v1/swagger-ui"
  :<|> redirect "/api/v1/swagger-ui"

main :: IO ()
main =
  runWarpServer @MyApiWithSwagger 8080 True mySwaggerServer
    & runM