summaryrefslogtreecommitdiff
path: root/server/Main.hs
blob: 04a201067bf419e2d51a08fb4d2dc7b73e1a2278 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
{-# LANGUAGE DataKinds         #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes        #-}
{-# LANGUAGE TypeApplications  #-}
{-# LANGUAGE TypeFamilies      #-}
{-# LANGUAGE TypeOperators     #-}


-- | simple server offering linting "as a service"
module Main where

import           Universum

import           Cli.Extras                           (CliConfig,
                                                       mkDefaultCliConfig,
                                                       runCli)
import qualified Data.ByteString.Lazy.Char8           as C8
import           Data.UUID                            (UUID)
import           Handlers                             (App, adminOverviewImpl,
                                                        statusImpl,
                                                       )
import           HtmlOrphans                          ()
import           Network.Wai.Handler.Warp             (defaultSettings,
                                                       runSettings, setPort)
import           Network.Wai.Middleware.Gzip          (def)
import           Network.Wai.Middleware.RequestLogger (OutputFormat (..),
                                                       RequestLoggerSettings (..),
                                                       mkRequestLogger)
import           Servant                              (Application, Capture,
                                                       Get, Handler,
                                                       HasServer (ServerT),
                                                       JSON, NoContent, Post,
                                                       Raw, ReqBody,
                                                       ServerError (errBody),
                                                       err500, hoistServer,
                                                       serve, throwError,
                                                       type (:<|>) (..),
                                                       type (:>))
import           Servant.HTML.Lucid                   (HTML)
import           Servant.Server.StaticFiles           (serveDirectoryWebApp)
import           Server                               (AdminOverview,
                                                       Config (..), JobStatus,
                                                       RemoteRef (..),
                                                       ServerState,
                                                       defaultState, loadConfig, verbose, port, orgs, Org (orgEntrypoint, orgRepos))


-- | Main API type
type API format =
       -- "submit" :> ReqBody '[JSON] RemoteRef :> Post '[format] UUID
       "status" :> Capture "jobid" UUID :> Get '[format] JobStatus
  -- :<|> "relint" :> Capture "jobid" UUID :> Get '[format] NoContent
  :<|> "admin" :> "overview" :> Get '[format] AdminOverview

type Routes =
   "api" :> API JSON
  :<|> "status" :> Capture "jobid" UUID :> Get '[HTML] JobStatus
  :<|> "admin" :> "overview" :> Get '[HTML] AdminOverview
  :<|> Raw

-- | API's implementation
jsonAPI :: Config True -> MVar ServerState -> ServerT (API JSON) App
jsonAPI config state =
  -- submitImpl config state
       statusImpl state
  -- :<|> relintImpl config state
  :<|> adminOverviewImpl state

server :: Config True -> MVar ServerState -> ServerT Routes App
server config state =
  jsonAPI config state
  :<|> statusImpl state
  :<|> adminOverviewImpl state
  :<|> serveDirectoryWebApp "./static"

-- | make an application; convert any cli errors into a 500
app :: CliConfig -> Config True -> MVar ServerState -> Application
app cliconfig config =
  serve api . hoistServer api conv . server config
  where api = Proxy @Routes
        conv :: App a -> Handler a
        conv m = do
          res <- runCli cliconfig m
          case res of
            Right a  -> pure a
            Left err -> throwError (err500 { errBody = C8.pack (show err) })


main :: IO ()
main = do
  config <- loadConfig "./config.toml"
  state <- newMVar defaultState
  -- TODO: i really don't like all this cli logging stuff, replace it with
  -- fast-logger at some point …
  cliconfig <- liftIO $ mkDefaultCliConfig ["-v" | view verbose config]
  loggerMiddleware <- mkRequestLogger
    $ def { outputFormat = Detailed (view verbose config) }

  -- print (keys $ view orgs config)
  print (map orgEntrypoint $ view orgs config)
  print (map orgRepos $ view orgs config)

  let warpsettings =
       setPort (view port config)
       defaultSettings

  runSettings warpsettings
    . loggerMiddleware
    $ app cliconfig config state