mirror of
https://github.com/Airsequel/AirGQL.git
synced 2025-07-08 11:09:32 +02:00
194 lines
4.9 KiB
Haskell
194 lines
4.9 KiB
Haskell
-- Necessary for servant-docs instances
|
|
{-# OPTIONS_GHC -Wno-orphans #-}
|
|
{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}
|
|
|
|
module Server.Server (platformAPI, platformApp)
|
|
where
|
|
|
|
import Protolude (
|
|
Int,
|
|
Monoid (mempty),
|
|
Proxy (Proxy),
|
|
($),
|
|
)
|
|
import Protolude qualified as P
|
|
|
|
import Data.Aeson (Object, Value, object)
|
|
import Data.Aeson.KeyMap qualified as KeyMap
|
|
import Data.ByteString.Lazy qualified as BL
|
|
import Data.Text (Text)
|
|
import Data.Text qualified as T
|
|
import Network.Wai (Application)
|
|
import Network.Wai.Parse (
|
|
defaultParseRequestBodyOptions,
|
|
setMaxRequestFilesSize,
|
|
setMaxRequestNumFiles,
|
|
)
|
|
import Servant (Context (EmptyContext, (:.)), NoContent)
|
|
import Servant.API (
|
|
Capture,
|
|
Get,
|
|
JSON,
|
|
PlainText,
|
|
Post,
|
|
ReqBody,
|
|
(:<|>) ((:<|>)),
|
|
(:>),
|
|
)
|
|
import Servant.Docs (
|
|
DocCapture (DocCapture),
|
|
ToCapture (toCapture),
|
|
ToSample,
|
|
singleSample,
|
|
toSamples,
|
|
)
|
|
import Servant.HTML.Blaze (HTML)
|
|
import Servant.Multipart (
|
|
MultipartData (MultipartData),
|
|
MultipartOptions (generalOptions),
|
|
Tmp,
|
|
ToMultipartSample (toMultipartSamples),
|
|
defaultMultipartOptions,
|
|
)
|
|
import Servant.Server (Server)
|
|
import Servant.Server qualified as Servant
|
|
import Text.Blaze.Internal (MarkupM)
|
|
|
|
import AirGQL.Config (Config (maxDbSize), defaultConfig)
|
|
import AirGQL.ExternalAppContext (ExternalAppContext)
|
|
import AirGQL.Lib (SQLPost)
|
|
import AirGQL.Servant.Database (
|
|
apiDatabaseSchemaGetHandler,
|
|
apiDatabaseVacuumPostHandler,
|
|
)
|
|
import AirGQL.Servant.GraphQL (
|
|
gqlQueryGetHandler,
|
|
gqlQueryPostHandler,
|
|
playgroundDefaultQueryHandler,
|
|
readOnlyGqlPostHandler,
|
|
writeOnlyGqlPostHandler,
|
|
)
|
|
import AirGQL.Servant.SqlQuery (sqlQueryPostHandler)
|
|
import AirGQL.Types.SchemaConf (SchemaConf (pragmaConf), defaultSchemaConf)
|
|
import AirGQL.Types.SqlQueryPostResult (SqlQueryPostResult)
|
|
import AirGQL.Types.Types (GQLPost)
|
|
|
|
|
|
{- FOURMOLU_DISABLE -}
|
|
-- ATTENTION: Order of handlers matters!
|
|
type PlatformAPI =
|
|
-- gqlQueryGetHandler
|
|
-- Redirect to GraphiQL playground
|
|
"graphql" :> Get '[HTML] NoContent
|
|
|
|
-- gqlQueryPostHandler
|
|
:<|> "graphql"
|
|
:> ReqBody '[JSON] GQLPost
|
|
:> Post '[JSON] Object
|
|
|
|
-- writeOnlyGqlPostHandler
|
|
:<|> "readonly" :> "graphql"
|
|
:> ReqBody '[JSON] GQLPost
|
|
:> Post '[JSON] Object
|
|
|
|
-- writeOnlyGqlPostHandler
|
|
:<|> "writeonly" :> "graphql"
|
|
:> ReqBody '[JSON] GQLPost
|
|
:> Post '[JSON] Object
|
|
|
|
-- playgroundDefaultQueryHandler
|
|
:<|> "playground" :> "default-query"
|
|
:> Get '[PlainText] Text
|
|
|
|
-- apiDatabaseSchemaGetHandler
|
|
:<|> "schema" :> Get '[PlainText] Text
|
|
|
|
-- apiDatabaseVacuumPostHandler
|
|
:<|> "vacuum" :> Post '[JSON] Object
|
|
|
|
-- sqlQueryPostHandler
|
|
:<|> "sql"
|
|
:> ReqBody '[JSON] SQLPost
|
|
:> Post '[JSON] SqlQueryPostResult
|
|
|
|
{- FOURMOLU_ENABLE -}
|
|
|
|
|
|
-- | Instances for automatic documentation generation via servant-docs
|
|
instance ToSample (MultipartData Tmp) where
|
|
toSamples _ = singleSample $ MultipartData mempty mempty
|
|
|
|
|
|
instance ToMultipartSample Tmp (MultipartData Tmp) where
|
|
toMultipartSamples _ = []
|
|
|
|
|
|
instance ToSample Value where
|
|
toSamples _ = singleSample $ object []
|
|
|
|
|
|
instance ToSample (KeyMap.KeyMap Value) where
|
|
toSamples _ = singleSample $ KeyMap.fromList []
|
|
|
|
|
|
instance ToSample (MarkupM ()) where
|
|
toSamples _ = singleSample mempty
|
|
|
|
|
|
instance ToSample BL.ByteString where
|
|
toSamples _ = singleSample mempty
|
|
|
|
|
|
instance ToSample Text where
|
|
toSamples _ = singleSample mempty
|
|
|
|
|
|
instance ToSample P.ByteString where
|
|
toSamples _ = singleSample mempty
|
|
|
|
|
|
instance ToCapture (Capture "readonlyId" Text) where
|
|
toCapture _ = DocCapture "readonlyId" "Read-only ID of the database"
|
|
|
|
|
|
instance ToCapture (Capture "dbId" Text) where
|
|
toCapture _ = DocCapture "dbId" "ID of the database to be served"
|
|
|
|
|
|
platformAPI :: Proxy PlatformAPI
|
|
platformAPI = Proxy
|
|
|
|
|
|
platformServer :: ExternalAppContext -> P.FilePath -> Server PlatformAPI
|
|
platformServer ctx filePath = do
|
|
let dbPath = T.pack filePath
|
|
gqlQueryGetHandler dbPath
|
|
:<|> gqlQueryPostHandler defaultSchemaConf dbPath
|
|
:<|> readOnlyGqlPostHandler dbPath
|
|
:<|> writeOnlyGqlPostHandler dbPath
|
|
:<|> playgroundDefaultQueryHandler dbPath
|
|
:<|> apiDatabaseSchemaGetHandler ctx dbPath
|
|
:<|> apiDatabaseVacuumPostHandler dbPath
|
|
:<|> sqlQueryPostHandler defaultSchemaConf.pragmaConf dbPath
|
|
|
|
|
|
platformApp :: ExternalAppContext -> P.FilePath -> Application
|
|
platformApp ctx filePath = do
|
|
let
|
|
maxFileSizeInByte :: Int = defaultConfig.maxDbSize
|
|
|
|
multipartOpts :: MultipartOptions Tmp
|
|
multipartOpts =
|
|
(defaultMultipartOptions (Proxy :: Proxy Tmp))
|
|
{ generalOptions =
|
|
setMaxRequestNumFiles 1 $
|
|
setMaxRequestFilesSize
|
|
(P.fromIntegral maxFileSizeInByte)
|
|
defaultParseRequestBodyOptions
|
|
}
|
|
|
|
context :: Context '[MultipartOptions Tmp]
|
|
context =
|
|
multipartOpts :. EmptyContext
|
|
|
|
Servant.serveWithContext platformAPI context $ platformServer ctx filePath
|