morpheus-graphql-0.21.0: src/Data/Morpheus/Server/TH/Declare/GQLDirective.hs
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TemplateHaskellQuotes #-}
{-# LANGUAGE NoImplicitPrelude #-}
module Data.Morpheus.Server.TH.Declare.GQLDirective
( deriveGQLDirective,
)
where
import Data.Morpheus.CodeGen.Internal.AST
( ServerConstructorDefinition (..),
ServerTypeDefinition (..),
TypeName,
)
import Data.Morpheus.CodeGen.Internal.TH
( apply,
applyVars,
typeInstanceDec,
)
import Data.Morpheus.Server.TH.Utils
( ServerDec,
mkTypeableConstraints,
)
import Data.Morpheus.Server.Types.Directives
( GQLDirective (..),
)
import Data.Morpheus.Types.Internal.AST
( DirectiveLocation (..),
)
import Language.Haskell.TH
( Dec,
Name,
Q,
Type (..),
instanceD,
)
import Relude hiding (Type, toString)
noVars :: [Name]
noVars = []
deriveGQLDirective :: ServerTypeDefinition -> ServerDec [Dec]
deriveGQLDirective DirectiveTypeDefinition {..} = do
let constrains = mkTypeableConstraints noVars
let tName = constructorName directiveConstructor
let typeSignature = apply ''GQLDirective [applyVars tName noVars]
methods <- defineMethods (constructorName directiveConstructor) directiveLocations
gqlTypeDeclaration <- lift (instanceD constrains typeSignature methods)
pure [gqlTypeDeclaration]
deriveGQLDirective _ = pure []
defineMethods :: TypeName -> [DirectiveLocation] -> ServerDec [Q Dec]
defineMethods tName locations = do
let currentType = applyVars tName noVars
let inst = typeInstanceDec ''DIRECTIVE_LOCATIONS currentType (promotedList locations)
pure [pure inst]
locationName :: DirectiveLocation -> Name
locationName QUERY = 'QUERY
locationName MUTATION = 'MUTATION
locationName SUBSCRIPTION = 'SUBSCRIPTION
locationName FIELD = 'FIELD
locationName FRAGMENT_DEFINITION = 'FRAGMENT_DEFINITION
locationName FRAGMENT_SPREAD = 'FRAGMENT_SPREAD
locationName INLINE_FRAGMENT = 'INLINE_FRAGMENT
locationName SCHEMA = 'SCHEMA
locationName SCALAR = 'SCALAR
locationName OBJECT = 'OBJECT
locationName FIELD_DEFINITION = 'FIELD_DEFINITION
locationName ARGUMENT_DEFINITION = 'ARGUMENT_DEFINITION
locationName INTERFACE = 'INTERFACE
locationName UNION = 'UNION
locationName ENUM = 'ENUM
locationName ENUM_VALUE = 'ENUM_VALUE
locationName INPUT_OBJECT = 'INPUT_OBJECT
locationName INPUT_FIELD_DEFINITION = 'INPUT_FIELD_DEFINITION
promotedList :: [DirectiveLocation] -> Type
promotedList =
foldr
(AppT . AppT PromotedConsT . PromotedT . locationName)
PromotedNilT