diff --git a/graphql.cabal b/graphql.cabal index b67f4ae..98f4365 100644 --- a/graphql.cabal +++ b/graphql.cabal @@ -38,6 +38,7 @@ library Language.GraphQL.Error Language.GraphQL.Execute Language.GraphQL.Execute.Coerce + Language.GraphQL.Executor Language.GraphQL.Execute.OrderedMap Language.GraphQL.Type Language.GraphQL.Type.In diff --git a/src/Language/GraphQL/Executor.hs b/src/Language/GraphQL/Executor.hs new file mode 100644 index 0000000..97447f5 --- /dev/null +++ b/src/Language/GraphQL/Executor.hs @@ -0,0 +1,82 @@ +{- This Source Code Form is subject to the terms of the Mozilla Public License, + v. 2.0. If a copy of the MPL was not distributed with this file, You can + obtain one at https://mozilla.org/MPL/2.0/. -} + +{-# LANGUAGE LambdaCase #-} + +module Language.GraphQL.Executor + ( Error(..) + , Operation(..) + , QueryError(..) + , Response(..) + , Segment(..) + , executeRequest + ) where + +import qualified Language.GraphQL.AST.Document as Full +import qualified Data.Aeson as Aeson +import Data.Foldable (find) +import qualified Data.Text as Text +import qualified Language.GraphQL.Type.Internal as Type.Internal + +data Segment = Segment String | Index Int + +data Error = Error + { message :: String + , locations :: [Full.Location] + , path :: [Segment] + } + +data Response = Response + { data' :: Aeson.Object + , errors :: [Error] + } + +data QueryError + = OperationNameRequired + | OperationNotFound + +-- operationName selectionSet location +data Operation = Operation + Full.OperationType + (Maybe String) + [Full.VariableDefinition] + Full.SelectionSet + Full.Location + +document :: Full.Document -> [Operation] +document = foldr filterOperation [] + where + filterOperation (Full.ExecutableDefinition executableDefinition) accumulator + | Full.DefinitionOperation operationDefinition' <- executableDefinition = + operationDefinition operationDefinition' : accumulator + filterOperation _ accumulator = accumulator -- Fragment. + +operationDefinition :: Full.OperationDefinition -> Operation +operationDefinition = \case + Full.OperationDefinition operationType operationName variables _ selectionSet operationLocation -> + let maybeOperationName = Text.unpack <$> operationName + in Operation operationType maybeOperationName variables selectionSet operationLocation + Full.SelectionSet selectionSet operationLocation -> + Operation Full.Query Nothing [] selectionSet operationLocation + +executeRequest :: Type.Internal.Schema IO + -> Full.Document + -> Maybe String + -> Aeson.Object + -> Aeson.Object + -> IO Response +executeRequest _schema sourceDocument operationName _variableValues _initialValue = + let transformedDocument = document sourceDocument + _operation = getOperation transformedDocument operationName + in pure $ Response mempty mempty + +getOperation :: [Operation] -> Maybe String -> Either QueryError Operation +getOperation [operation] Nothing = Right operation +getOperation operations (Just givenOperationName) = + maybe (Left OperationNotFound) Right $ find findOperationByName operations + where + findOperationByName (Operation _ (Just operationName) _ _ _) = + givenOperationName == operationName + findOperationByName _ = False +getOperation _ _ = Left OperationNameRequired