morpheus-graphql-0.2.0: src/Data/Morpheus/Execution/Server/Interpreter.hs
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RankNTypes #-}
module Data.Morpheus.Execution.Server.Interpreter
( Interpreter(..)
) where
import Data.Aeson (encode)
import Data.ByteString (ByteString)
import qualified Data.ByteString.Lazy.Char8 as LB (ByteString, fromStrict, toStrict)
import Data.Text (Text)
import qualified Data.Text.Lazy as LT (Text, fromStrict, toStrict)
import Data.Text.Lazy.Encoding (decodeUtf8, encodeUtf8)
-- MORPHEUS
import Data.Morpheus.Execution.Server.Resolve (RootResCon, byteStringIO, statefulResolver,
statelessResolver, streamResolver)
import Data.Morpheus.Execution.Subscription.ClientRegister (GQLState)
import Data.Morpheus.Types.Internal.Stream (ResponseStream)
import Data.Morpheus.Types.IO (GQLRequest, GQLResponse)
import Data.Morpheus.Types.Resolver (GQLRootResolver (..))
-- | main query processor and resolver
-- possible versions of interpreter
--
-- 1. with effect and state: where 'GQLState' is State Monad of subscriptions
--
-- @
-- k :: GQLState -> a -> IO a
-- @
--
-- 2. without effect and state: stateless query processor without any effect,
-- if you don't need any subscription use this one , is simple and fast
--
-- @
-- k :: a -> IO a
-- -- or
-- k :: GQLRequest -> IO GQLResponse
-- @
class Interpreter k m e c where
interpreter ::
Monad m
=> (RootResCon m e c que mut sub) =>
GQLRootResolver m e c que mut sub -> k
{-
simple HTTP stateless Interpreter without side effects
-}
type StateLess m a = a -> m a
instance Interpreter (GQLRequest -> m GQLResponse) m e c where
interpreter = statelessResolver
instance Interpreter (StateLess m LB.ByteString) m e c where
interpreter root = byteStringIO (statelessResolver root)
instance Interpreter (StateLess m LT.Text) m e c where
interpreter root request =
decodeUtf8 <$> interpreter root (encodeUtf8 request)
instance Interpreter (StateLess m ByteString) m e c where
interpreter root request =
LB.toStrict <$> interpreter root (LB.fromStrict request)
instance Interpreter (StateLess m Text) m e c where
interpreter root request =
LT.toStrict <$> interpreter root (LT.fromStrict request)
{-
HTTP Interpreter with state and side effects, every mutation will
trigger subscriptions in shared `GQLState`
-}
type WSPub m e c a = GQLState m e c -> a -> m a
instance Interpreter (WSPub IO e c LB.ByteString) IO e c where
interpreter root state =
statefulResolver state (byteStringIO (streamResolver root))
instance Interpreter (WSPub IO e c LT.Text) IO e c where
interpreter root state request =
decodeUtf8 <$> interpreter root state (encodeUtf8 request)
instance Interpreter (WSPub IO e c ByteString) IO e c where
interpreter root state request =
LB.toStrict <$> interpreter root state (LB.fromStrict request)
instance Interpreter (WSPub IO e c Text) IO e c where
interpreter root state request =
LT.toStrict <$> interpreter root state (LT.fromStrict request)
{-
WebSocket Interpreter without state and side effects, mutations and subscription will return Actions
that will be executed in WebSocket server
-}
type WSSub m e c a = a -> ResponseStream m e c a
instance Interpreter (GQLRequest -> ResponseStream m e c LB.ByteString) m e c where
interpreter root request = encode <$> streamResolver root request
instance Interpreter (WSSub m e c LB.ByteString) m e c where
interpreter root = byteStringIO (streamResolver root)
instance Interpreter (WSSub m e c LT.Text) m e c where
interpreter root request =
decodeUtf8 <$> interpreter root (encodeUtf8 request)
instance Interpreter (WSSub m e c ByteString) m e c where
interpreter root request =
LB.toStrict <$> interpreter root (LB.fromStrict request)
instance Interpreter (WSSub m e c Text) m e c where
interpreter root request =
LT.toStrict <$> interpreter root (LT.fromStrict request)