{-# LANGUAGE OverloadedStrings #-}

-- | This module provides functions to execute a @GraphQL@ request.
module Language.GraphQL.Execute
    ( execute
    , module Language.GraphQL.Execute.Coerce
    ) where

import Control.Monad.Catch (MonadCatch)
import Data.HashMap.Strict (HashMap)
import Data.Sequence (Seq(..))
import Data.Text (Text)
import Language.GraphQL.AST.Document (Document, Name)
import Language.GraphQL.Execute.Coerce
import Language.GraphQL.Execute.Execution
import qualified Language.GraphQL.Execute.Transform as Transform
import qualified Language.GraphQL.Execute.Subscribe as Subscribe
import Language.GraphQL.Error
import qualified Language.GraphQL.Type.Definition as Definition
import qualified Language.GraphQL.Type.Out as Out
import Language.GraphQL.Type.Schema

-- | The substitution is applied to the document, and the resolvers are applied
-- to the resulting fields. The operation name can be used if the document
-- defines multiple root operations.
--
-- Returns the result of the query against the schema wrapped in a /data/
-- field, or errors wrapped in an /errors/ field.
execute :: (MonadCatch m, VariableValue a, Serialize b)
    => Schema m -- ^ Resolvers.
    -> Maybe Text -- ^ Operation name.
    -> HashMap Name a -- ^ Variable substitution function.
    -> Document -- @GraphQL@ document.
    -> m (Either (ResponseEventStream m b) (Response b))
execute :: Schema m
-> Maybe Text
-> HashMap Text a
-> Document
-> m (Either (ResponseEventStream m b) (Response b))
execute schema' :: Schema m
schema' operationName :: Maybe Text
operationName subs :: HashMap Text a
subs document :: Document
document =
    case Schema m
-> Maybe Text
-> HashMap Text a
-> Document
-> Either QueryError (Document m)
forall a (m :: * -> *).
VariableValue a =>
Schema m
-> Maybe Text
-> HashMap Text a
-> Document
-> Either QueryError (Document m)
Transform.document Schema m
schema' Maybe Text
operationName HashMap Text a
subs Document
document of
        Left queryError :: QueryError
queryError -> Either (ResponseEventStream m b) (Response b)
-> m (Either (ResponseEventStream m b) (Response b))
forall (f :: * -> *) a. Applicative f => a -> f a
pure
            (Either (ResponseEventStream m b) (Response b)
 -> m (Either (ResponseEventStream m b) (Response b)))
-> Either (ResponseEventStream m b) (Response b)
-> m (Either (ResponseEventStream m b) (Response b))
forall a b. (a -> b) -> a -> b
$ Response b -> Either (ResponseEventStream m b) (Response b)
forall a b. b -> Either a b
Right
            (Response b -> Either (ResponseEventStream m b) (Response b))
-> Response b -> Either (ResponseEventStream m b) (Response b)
forall a b. (a -> b) -> a -> b
$ Text -> Response b
forall a. Serialize a => Text -> Response a
singleError
            (Text -> Response b) -> Text -> Response b
forall a b. (a -> b) -> a -> b
$ QueryError -> Text
Transform.queryError QueryError
queryError
        Right transformed :: Document m
transformed -> Document m -> m (Either (ResponseEventStream m b) (Response b))
forall (m :: * -> *) a.
(MonadCatch m, Serialize a) =>
Document m -> m (Either (ResponseEventStream m a) (Response a))
executeRequest Document m
transformed

executeRequest :: (MonadCatch m, Serialize a)
    => Transform.Document m
    -> m (Either (ResponseEventStream m a) (Response a))
executeRequest :: Document m -> m (Either (ResponseEventStream m a) (Response a))
executeRequest (Transform.Document types' :: HashMap Text (Type m)
types' rootObjectType :: ObjectType m
rootObjectType operation :: Operation m
operation)
    | (Transform.Query _ fields :: Seq (Selection m)
fields) <- Operation m
operation =
        Response a -> Either (ResponseEventStream m a) (Response a)
forall a b. b -> Either a b
Right (Response a -> Either (ResponseEventStream m a) (Response a))
-> m (Response a)
-> m (Either (ResponseEventStream m a) (Response a))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> HashMap Text (Type m)
-> ObjectType m -> Seq (Selection m) -> m (Response a)
forall (m :: * -> *) a.
(MonadCatch m, Serialize a) =>
HashMap Text (Type m)
-> ObjectType m -> Seq (Selection m) -> m (Response a)
executeOperation HashMap Text (Type m)
types' ObjectType m
rootObjectType Seq (Selection m)
fields
    | (Transform.Mutation _ fields :: Seq (Selection m)
fields) <- Operation m
operation =
        Response a -> Either (ResponseEventStream m a) (Response a)
forall a b. b -> Either a b
Right (Response a -> Either (ResponseEventStream m a) (Response a))
-> m (Response a)
-> m (Either (ResponseEventStream m a) (Response a))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> HashMap Text (Type m)
-> ObjectType m -> Seq (Selection m) -> m (Response a)
forall (m :: * -> *) a.
(MonadCatch m, Serialize a) =>
HashMap Text (Type m)
-> ObjectType m -> Seq (Selection m) -> m (Response a)
executeOperation HashMap Text (Type m)
types' ObjectType m
rootObjectType Seq (Selection m)
fields
    | (Transform.Subscription _ fields :: Seq (Selection m)
fields) <- Operation m
operation
        = (Text -> Either (ResponseEventStream m a) (Response a))
-> (ResponseEventStream m a
    -> Either (ResponseEventStream m a) (Response a))
-> Either Text (ResponseEventStream m a)
-> Either (ResponseEventStream m a) (Response a)
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (Response a -> Either (ResponseEventStream m a) (Response a)
forall a b. b -> Either a b
Right (Response a -> Either (ResponseEventStream m a) (Response a))
-> (Text -> Response a)
-> Text
-> Either (ResponseEventStream m a) (Response a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Response a
forall a. Serialize a => Text -> Response a
singleError) ResponseEventStream m a
-> Either (ResponseEventStream m a) (Response a)
forall a b. a -> Either a b
Left
        (Either Text (ResponseEventStream m a)
 -> Either (ResponseEventStream m a) (Response a))
-> m (Either Text (ResponseEventStream m a))
-> m (Either (ResponseEventStream m a) (Response a))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> HashMap Text (Type m)
-> ObjectType m
-> Seq (Selection m)
-> m (Either Text (ResponseEventStream m a))
forall (m :: * -> *) a.
(MonadCatch m, Serialize a) =>
HashMap Text (Type m)
-> ObjectType m
-> Seq (Selection m)
-> m (Either Text (ResponseEventStream m a))
Subscribe.subscribe HashMap Text (Type m)
types' ObjectType m
rootObjectType Seq (Selection m)
fields

-- This is actually executeMutation, but we don't distinguish between queries
-- and mutations yet.
executeOperation :: (MonadCatch m, Serialize a)
    => HashMap Name (Type m)
    -> Out.ObjectType m
    -> Seq (Transform.Selection m)
    -> m (Response a)
executeOperation :: HashMap Text (Type m)
-> ObjectType m -> Seq (Selection m) -> m (Response a)
executeOperation types' :: HashMap Text (Type m)
types' objectType :: ObjectType m
objectType fields :: Seq (Selection m)
fields =
    HashMap Text (Type m) -> CollectErrsT m a -> m (Response a)
forall (m :: * -> *) a.
(Monad m, Serialize a) =>
HashMap Text (Type m) -> CollectErrsT m a -> m (Response a)
runCollectErrs HashMap Text (Type m)
types' (CollectErrsT m a -> m (Response a))
-> CollectErrsT m a -> m (Response a)
forall a b. (a -> b) -> a -> b
$ Value -> ObjectType m -> Seq (Selection m) -> CollectErrsT m a
forall (m :: * -> *) a.
(MonadCatch m, Serialize a) =>
Value -> ObjectType m -> Seq (Selection m) -> CollectErrsT m a
executeSelectionSet Value
Definition.Null ObjectType m
objectType Seq (Selection m)
fields