morpheus-graphql-0.3.0: examples/Sophisticated/API.hs
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
module Sophisticated.API
( gqlRoot
, Channel
, Content
) where
import Data.Map (Map)
import qualified Data.Map as M (fromList)
import Data.Set (Set)
import qualified Data.Set as S (fromList)
import Data.Text (Text, pack)
import Data.Typeable (Typeable)
import GHC.Generics (Generic)
-- MORPHEUS
import Data.Morpheus.Document (importGQLDocumentWithNamespace)
import Data.Morpheus.Kind (INPUT_UNION, OBJECT, SCALAR)
import Data.Morpheus.Types (Event (..), GQLRootResolver (..), GQLScalar (..), GQLType (..), ID, IOMutRes,
IORes, IOSubRes, Resolver, ScalarValue (..), SubResolver (..), constRes,
mutResolver, resolver)
$(importGQLDocumentWithNamespace "examples/Sophisticated/api.gql")
type AIntText = A (Int, Text)
type AText = A Text
type SetInt = Set Int
type MapTextInt = Map Text Int
data Animal
= CAT Cat
| DOG Dog
| BIRD Bird
deriving (Show, Generic)
instance GQLType Animal where
type KIND Animal = INPUT_UNION
data Euro =
Euro Int
Int
deriving (Show, Generic)
instance GQLType Euro where
type KIND Euro = SCALAR
instance GQLScalar Euro where
parseValue _ = pure (Euro 1 0)
serialize (Euro x y) = Int (x * 100 + y)
instance Typeable a => GQLType (A a) where
type KIND (A a) = OBJECT
newtype A a = A
{ wrappedA :: a
} deriving (Generic)
data Channel
= UPDATE_USER
| UPDATE_ADDRESS
deriving (Show, Eq, Ord)
data Content = Update
{ contentID :: Int
, contentMessage :: Text
}
type MutRes = IOMutRes Channel Content
type SubRes = IOSubRes Channel Content
gqlRoot :: GQLRootResolver IO Channel Content (Query IORes) (Mutation MutRes) (Subscription SubRes)
gqlRoot = GQLRootResolver {queryResolver, mutationResolver, subscriptionResolver}
where
queryResolver =
return
Query
{ queryUser = const $ resolver fetchUser
, queryAnimal = \QueryAnimalArgs {queryAnimalArgsAnimal} -> return (pack $ show queryAnimalArgsAnimal)
, querySet = constRes $ S.fromList [1, 2]
, queryMap = constRes $ M.fromList [("robin", 1), ("carl", 2)]
, queryWrapped1 = constRes $ A (0, "")
, queryWrapped2 = constRes $ A ""
}
-------------------------------------------------------------
mutationResolver = return Mutation {mutationCreateAddress, mutationCreateUser}
where
mutationCreateUser _ =
mutResolver
[Event [UPDATE_USER] (Update {contentID = 12, contentMessage = "some message for user"})]
fetchUser
--mutationCreateAddress :: () -> MutRes (Address MutRes)
mutationCreateAddress _ =
mutResolver
[Event [UPDATE_ADDRESS] (Update {contentID = 10, contentMessage = "message for address"})]
(fetchAddress (Euro 1 0))
----------------------------------------------------------------
subscriptionResolver = return Subscription {subscriptionNewAddress, subscriptionNewUser}
where
subscriptionNewUser () = SubResolver {subChannels = [UPDATE_USER], subResolver}
where
subResolver (Event _ Update {}) = resolver fetchUser
subscriptionNewAddress () = SubResolver {subChannels = [UPDATE_ADDRESS], subResolver}
where
subResolver (Event _ Update {contentID}) = resolver $ fetchAddress (Euro contentID 0)
fetchAddress :: Monad m => Euro -> m (Either String (Address (Resolver m)))
fetchAddress _ =
return $ Right Address {addressCity = constRes "", addressStreet = constRes "", addressHouseNumber = constRes 0}
fetchUser :: Monad m => m (Either String (User (Resolver m)))
fetchUser =
return $
Right $
User
{ userName = constRes "George"
, userEmail = constRes "George@email.com"
, userAddress = const resolveAddress
, userOffice = resolveOffice
, userHome = constRes HH
, userEntity = constRes $ MyUnionUser unionUser
}
where
unionAddress =
Address {addressCity = constRes "Hamburg", addressStreet = constRes "Street", addressHouseNumber = constRes 20}
-- Office
resolveOffice _officeArgs = resolver $ fetchAddress (Euro 1 1)
resolveAddress = resolver $ fetchAddress (Euro 1 0)
unionUser =
User
{ userName = constRes "David"
, userEmail = constRes "David@email.com"
, userAddress = const resolveAddress
, userOffice = resolveOffice
, userHome = constRes BLN
, userEntity = const $ return $ MyUnionAddress unionAddress
}