graphql/src/Language/GraphQL/Execute.hs

63 lines
2.5 KiB
Haskell
Raw Normal View History

2020-07-11 06:34:10 +02:00
{-# LANGUAGE OverloadedStrings #-}
-- | This module provides functions to execute a @GraphQL@ request.
2019-07-14 05:58:05 +02:00
module Language.GraphQL.Execute
( execute
, module Language.GraphQL.Execute.Coerce
2019-07-14 05:58:05 +02:00
) where
import Data.HashMap.Strict (HashMap)
import Data.Sequence (Seq(..))
2019-07-25 07:37:36 +02:00
import Data.Text (Text)
import Language.GraphQL.AST.Document (Document, Name)
2020-05-21 10:20:59 +02:00
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
2020-06-13 07:20:19 +02:00
import qualified Language.GraphQL.Type.Definition as Definition
import qualified Language.GraphQL.Type.Out as Out
2020-05-14 09:17:14 +02:00
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.
2019-07-25 07:37:36 +02:00
--
-- Returns the result of the query against the schema wrapped in a /data/
-- field, or errors wrapped in an /errors/ field.
execute :: (Monad 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 operationName subs document =
case Transform.document schema operationName subs document of
Left queryError -> pure
$ Right
$ singleError
$ Transform.queryError queryError
Right transformed -> executeRequest transformed
executeRequest :: (Monad m, Serialize a)
=> Transform.Document m
-> m (Either (ResponseEventStream m a) (Response a))
executeRequest (Transform.Document types' rootObjectType operation)
| (Transform.Query _ fields) <- operation =
Right <$> executeOperation types' rootObjectType fields
| (Transform.Mutation _ fields) <- operation =
Right <$> executeOperation types' rootObjectType fields
| (Transform.Subscription _ fields) <- operation
= either (Right . singleError) Left
<$> Subscribe.subscribe types' rootObjectType fields
-- This is actually executeMutation, but we don't distinguish between queries
-- and mutations yet.
executeOperation :: (Monad m, Serialize a)
=> HashMap Name (Type m)
-> Out.ObjectType m
-> Seq (Transform.Selection m)
-> m (Response a)
executeOperation types' objectType fields =
2020-06-13 07:20:19 +02:00
runCollectErrs types' $ executeSelectionSet Definition.Null objectType fields