{-# 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
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, destructRecord, instanceHeadMultiT, typeT)
import Data.Morpheus.Types.Internal.Validation (ResolveT)
import Data.Morpheus.Types.Internal.Value (Value)
import Data.Morpheus.Types.Resolver
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"]
| otherwise = typeT ''ResolveT ["m"]
mainType = applyT (mkName tName) [mainTypeArg]
where
mainTypeArg
| isSubscription typeKindD = typeT ''SubResolver ["m", "e", "c"]
| otherwise = typeT ''Resolver ["m"]
constrains = [typeT ''Monad ["m"], typeT ''Typeable ["m"]]
appHead = instanceHeadMultiT ''ObjectResolvers (conT ''TRUE) [mainType, result]
methods = [funD 'objectResolvers [clause argsE (normalB body) []]]
where
argsE = [varP (mkName "_"), destructRecord tName varNames]
body = listE $ map decodeVar varNames
decodeVar name = [|(name, encode $(varName))|]
where
varName = varE $ mkName name
varNames = map (unpack . fieldName) cFields
deriveEncode _ = pure []