{-# LANGUAGE CPP #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE NoImplicitPrelude #-}

-- |  GraphQL Wai Server Applications
module Data.Morpheus.Server
  ( httpPlayground,
    compileTimeSchemaValidation,
    printSchema,
    RootResolverConstraint,
    interpreter,
    debugInterpreter,
    App,
    deriveApp,
    runApp,
    withDebugger,
    disableIntrospection,
  )
where

import Data.ByteString.Lazy.Char8
  ( ByteString,
    pack,
  )
import Data.Morpheus.App
  ( App (..),
    MapAPI,
    disableIntrospection,
    runApp,
    withDebugger,
  )
import Data.Morpheus.App.Internal.Resolving
  ( resultOr,
  )
import Data.Morpheus.Core
  ( render,
  )
import Data.Morpheus.Server.Deriving.App
  ( RootResolverConstraint,
    deriveApp,
    deriveSchema,
  )
import Data.Morpheus.Server.Deriving.Schema
  ( compileTimeSchemaValidation,
  )
import Data.Morpheus.Server.Playground
  ( httpPlayground,
  )
import Data.Morpheus.Server.Resolvers (RootResolver)
import Relude hiding (ByteString)

-- | Generates schema.gql file from 'RootResolver'
printSchema ::
  (RootResolverConstraint m event query mut sub) =>
  proxy (RootResolver m event query mut sub) ->
  ByteString
printSchema :: forall (m :: * -> *) event (query :: (* -> *) -> *)
       (mut :: (* -> *) -> *) (sub :: (* -> *) -> *) (proxy :: * -> *).
RootResolverConstraint m event query mut sub =>
proxy (RootResolver m event query mut sub) -> ByteString
printSchema =
  (NonEmpty GQLError -> ByteString)
-> (Schema CONST -> ByteString)
-> Result GQLError (Schema CONST)
-> ByteString
forall err a' a.
(NonEmpty err -> a') -> (a -> a') -> Result err a -> a'
resultOr ([Char] -> ByteString
pack ([Char] -> ByteString)
-> (NonEmpty GQLError -> [Char]) -> NonEmpty GQLError -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NonEmpty GQLError -> [Char]
forall b a. (Show a, IsString b) => a -> b
show) Schema CONST -> ByteString
forall a. RenderGQL a => a -> ByteString
render
    (Result GQLError (Schema CONST) -> ByteString)
-> (proxy (RootResolver m event query mut sub)
    -> Result GQLError (Schema CONST))
-> proxy (RootResolver m event query mut sub)
-> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. proxy (RootResolver m event query mut sub)
-> Result GQLError (Schema CONST)
forall {k1} {k2} {k3}
       (root :: k1
                -> k2
                -> ((* -> *) -> *)
                -> ((* -> *) -> *)
                -> ((* -> *) -> *)
                -> k3)
       (f :: k3 -> *) (m :: k1) (e :: k2) (qu :: (* -> *) -> *)
       (mu :: (* -> *) -> *) (su :: (* -> *) -> *).
SCHEMA qu mu su =>
f (root m e qu mu su) -> Result GQLError (Schema CONST)
deriveSchema

-- | main query processor and resolver
interpreter ::
  (MapAPI a b, RootResolverConstraint m e query mut sub) =>
  RootResolver m e query mut sub ->
  a ->
  m b
interpreter :: forall a b (m :: * -> *) e (query :: (* -> *) -> *)
       (mut :: (* -> *) -> *) (sub :: (* -> *) -> *).
(MapAPI a b, RootResolverConstraint m e query mut sub) =>
RootResolver m e query mut sub -> a -> m b
interpreter = App e m -> a -> m b
forall a b (m :: * -> *) e.
(MapAPI a b, Monad m) =>
App e m -> a -> m b
runApp (App e m -> a -> m b)
-> (RootResolver m e query mut sub -> App e m)
-> RootResolver m e query mut sub
-> a
-> m b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RootResolver m e query mut sub -> App e m
forall (f :: (* -> *)
             -> * -> ((* -> *) -> *) -> ((* -> *) -> *) -> ((* -> *) -> *) -> *)
       (m :: * -> *) event (qu :: (* -> *) -> *) (mu :: (* -> *) -> *)
       (su :: (* -> *) -> *).
DeriveApp f m event qu mu su =>
f m event qu mu su -> App event m
deriveApp

debugInterpreter ::
  (MapAPI a b, RootResolverConstraint m e query mut sub) =>
  RootResolver m e query mut sub ->
  a ->
  m b
debugInterpreter :: forall a b (m :: * -> *) e (query :: (* -> *) -> *)
       (mut :: (* -> *) -> *) (sub :: (* -> *) -> *).
(MapAPI a b, RootResolverConstraint m e query mut sub) =>
RootResolver m e query mut sub -> a -> m b
debugInterpreter = App e m -> a -> m b
forall a b (m :: * -> *) e.
(MapAPI a b, Monad m) =>
App e m -> a -> m b
runApp (App e m -> a -> m b)
-> (RootResolver m e query mut sub -> App e m)
-> RootResolver m e query mut sub
-> a
-> m b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. App e m -> App e m
forall e (m :: * -> *). App e m -> App e m
withDebugger (App e m -> App e m)
-> (RootResolver m e query mut sub -> App e m)
-> RootResolver m e query mut sub
-> App e m
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RootResolver m e query mut sub -> App e m
forall (f :: (* -> *)
             -> * -> ((* -> *) -> *) -> ((* -> *) -> *) -> ((* -> *) -> *) -> *)
       (m :: * -> *) event (qu :: (* -> *) -> *) (mu :: (* -> *) -> *)
       (su :: (* -> *) -> *).
DeriveApp f m event qu mu su =>
f m event qu mu su -> App event m
deriveApp