{-# LANGUAGE DataKinds #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TemplateHaskell #-} module Data.Morpheus.Execution.Document.Encode ( deriveEncode ) where import Data.Text (unpack) import Data.Typeable (Typeable) import Language.Haskell.TH -- -- MORPHEUS import Data.Morpheus.Execution.Server.Encode (Encode (..), ObjectResolvers (..)) import Data.Morpheus.Types.GQLType (TRUE) import Data.Morpheus.Types.Internal.Data (DataField (..), isSubscription) import Data.Morpheus.Types.Internal.DataD (ConsD (..), GQLTypeD (..), TypeD (..)) import Data.Morpheus.Types.Internal.TH (applyT, instanceHeadMultiT, typeT) import Data.Morpheus.Types.Internal.Validation (ResolveT) import Data.Morpheus.Types.Internal.Value (Value) import Data.Morpheus.Types.Resolver -- @Subscription: -- -- instance (Monad m, Typeable m) => ObjectResolvers 'True ( (SubResolver m e c)) (SubResolveT m e c Value) where -- objectResolvers _ ( x y) = [("newAddress", encode x), ("newUser", encode y)] -- -- @Object: -- -- instance (Monad m, Typeable m) => ObjectResolvers 'True ( (Resolver m)) (ResolveT m Value) where -- objectResolvers _ ( x y) = [("field1", encode x), ("field2", encode y)] -- -- deriveEncode :: GQLTypeD -> Q [Dec] deriveEncode GQLTypeD {typeKindD, typeD = TypeD {tName, tCons = [ConsD {cFields}]}} = pure <$> instanceD (cxt constrains) appHead methods where result = appT resultMonad (conT ''Value) where resultMonad | isSubscription typeKindD = typeT ''SubResolveT ["m", "e", "c"] -- (SubResolveT m e c Value) | otherwise = typeT ''ResolveT ["m"] -- (ResolveT m Value) mainType = applyT (mkName tName) [mainTypeArg] -- defines ( (SubResolver m e c)) or ( (Resolver m)) where mainTypeArg | isSubscription typeKindD = typeT ''SubResolver ["m", "e", "c"] -- (SubResolver m e c) | otherwise = typeT ''Resolver ["m"] -- (Resolver m) ----------------------------------------------------------------------------------------- -- defines Constraint: (Typeable m, Monad m) constrains = [typeT ''Monad ["m"], typeT ''Typeable ["m"]] ------------------------------------------------------------------- -- defines: instance => ObjectResolvers ('TRUE) ( (ResolveT m)) (ResolveT m value) where appHead = instanceHeadMultiT ''ObjectResolvers (conT ''TRUE) [mainType, result] ------------------------------------------------------------------ -- defines: objectResolvers = [("field1",encode field1),("field2",encode field2), ...] methods = [funD 'objectResolvers [clause argsE (normalB body) []]] where argsE = [varP (mkName "_"), conP (mkName tName) (map (varP . mkName) varNames)] body = listE $ map decodeVar varNames decodeVar name = [|(name, encode $(varName))|] where varName = varE $ mkName name varNames = map (unpack . fieldName) cFields deriveEncode _ = pure []