summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Language/GraphQL/Foundation.hs53
1 files changed, 53 insertions, 0 deletions
diff --git a/src/Language/GraphQL/Foundation.hs b/src/Language/GraphQL/Foundation.hs
index 4647a47..4d0d4f3 100644
--- a/src/Language/GraphQL/Foundation.hs
+++ b/src/Language/GraphQL/Foundation.hs
@@ -1,5 +1,58 @@
+{-# 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)