{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE RecordWildCards #-} module Language.GraphQL.Foundation ( module Language.GraphQL.Serialize , graphql ) where import Language.GraphQL.Serialize import Control.Monad.Catch (MonadCatch) import qualified Data.Aeson as Aeson import qualified Data.Aeson.Types as Aeson import Data.HashMap.Strict (HashMap) import qualified Data.Aeson.KeyMap as KeyMap import Data.Maybe (catMaybes) import qualified Data.Sequence as Seq import Data.Text (Text) import Data.Vector (Vector) import qualified Data.Vector as Vector import qualified Language.GraphQL as GraphQL import Language.GraphQL.AST import Language.GraphQL.Error import Language.GraphQL.Type.Schema (Schema) import Data.Bifunctor (Bifunctor(..)) -- | If the text parses correctly as a @GraphQL@ query the query is -- executed using the given 'Schema'. graphql :: MonadCatch m => Schema m -- ^ Resolvers. -> Text -- ^ Text representing a @GraphQL@ request document. -> m (Either (ResponseEventStream m Aeson.Value) Aeson.Object) -- ^ Response. graphql schema = fmap (bimap stream formatResponse) . GraphQL.graphql schema mempty (mempty :: HashMap Name JSON) where stream :: ResponseEventStream m JSON -> ResponseEventStream m Aeson.Value stream = undefined formatResponse :: Response JSON -> Aeson.Object formatResponse Response{ errors, data' = JSON json } = let dataResponse = KeyMap.singleton "data" json in case errors of Seq.Empty -> dataResponse _ -> flip (KeyMap.insert "errors") dataResponse $ Aeson.Array $ foldr fromError mempty errors fromError :: Error -> Vector Aeson.Value -> Vector Aeson.Value fromError Error{..} = Vector.cons $ Aeson.object $ catMaybes [ Just ("message", Aeson.String message) , toMaybe fromLocation "locations" locations , toMaybe fromPath "path" path ] fromPath (Segment segment) = Aeson.String segment fromPath (Index index) = Aeson.toJSON index fromLocation Location{..} = Aeson.object [ ("line", Aeson.toJSON line) , ("column", Aeson.toJSON column) ] toMaybe _ _ [] = Nothing toMaybe f key xs = Just (key, Aeson.listValue f xs)