{-# LANGUAGE DataKinds #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE TemplateHaskell #-} module Data.Morpheus.Execution.Document.GQLType ( deriveGQLType ) where import Data.Text ( pack , unpack ) import Language.Haskell.TH import Data.Semigroup ( (<>) ) -- -- MORPHEUS import Data.Morpheus.Execution.Internal.Declare ( tyConArgs ) import Data.Morpheus.Kind ( ENUM , INPUT_OBJECT , INPUT_UNION , OBJECT , SCALAR , UNION , WRAPPER ) import Data.Morpheus.Types.GQLType ( GQLType(..) , TRUE ) import Data.Morpheus.Types.Internal.AST ( DataTypeKind(..) , Meta(..) , isObject , isSchemaTypeName , GQLTypeD(..) , TypeD(..) ) import Data.Morpheus.Types.Internal.TH ( instanceHeadT , typeT , typeInstanceDec , instanceProxyFunD ) import Data.Typeable ( Typeable ) genTypeName :: String -> String genTypeName ('S' : name) | isSchemaTypeName (pack name) = name genTypeName name = name deriveGQLType :: GQLTypeD -> Q [Dec] deriveGQLType GQLTypeD { typeD = TypeD { tName, tMeta }, typeKindD } = pure <$> instanceD (cxt constrains) iHead (functions <> typeFamilies) where functions = map instanceProxyFunD [ ('__typeName , [|pack (genTypeName tName)|]) , ('description, descriptionValue) ] where descriptionValue = case tMeta >>= metaDescription of Nothing -> [| Nothing |] Just x -> [| Just (pack desc)|] where desc = unpack x ------------------------------------------------- typeArgs = tyConArgs typeKindD ---------------------------------------------- iHead = instanceHeadT ''GQLType tName typeArgs headSig = typeT (mkName tName) typeArgs ----------------------------------------------- constrains = map conTypeable typeArgs where conTypeable name = typeT ''Typeable [name] ----------------------------------------------- typeFamilies | isObject typeKindD = [deriveCUSTOM, deriveKind] | otherwise = [deriveKind] where deriveCUSTOM = do typeN <- headSig pure $ typeInstanceDec ''CUSTOM typeN (ConT ''TRUE) --------------------------------------------------------------- deriveKind = do typeN <- headSig pure $ typeInstanceDec ''KIND typeN (ConT $ toKIND typeKindD) --------------------------------- toKIND KindScalar = ''SCALAR toKIND KindEnum = ''ENUM toKIND (KindObject _) = ''OBJECT toKIND KindUnion = ''UNION toKIND KindInputObject = ''INPUT_OBJECT toKIND KindList = ''WRAPPER toKIND KindNonNull = ''WRAPPER toKIND KindInputUnion = ''INPUT_UNION