{-# LANGUAGE ConstrainedClassMethods #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE TemplateHaskellQuotes #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE NoImplicitPrelude #-} module Data.Morpheus.Client.Declare.Fetch ( declareFetch, ) where import Data.Morpheus.Client.Fetch (Fetch (..)) import Data.Morpheus.Client.Internal.Types ( FetchDefinition (..), TypeNameTH (..), ) import Data.Morpheus.CodeGen.Internal.TH ( applyCons, toCon, typeInstanceDec, ) import qualified Data.Text as T import Language.Haskell.TH ( Dec, Q, Type, clause, cxt, funD, instanceD, normalB, ) import Relude hiding (ByteString, Type) declareFetch :: Text -> FetchDefinition -> Q [Dec] declareFetch :: Text -> FetchDefinition -> Q [Dec] declareFetch Text query FetchDefinition {Maybe TypeNameTH clientArgumentsTypeName :: FetchDefinition -> Maybe TypeNameTH clientArgumentsTypeName :: Maybe TypeNameTH clientArgumentsTypeName, TypeNameTH rootTypeName :: FetchDefinition -> TypeNameTH rootTypeName :: TypeNameTH rootTypeName} = Dec -> [Dec] forall (f :: * -> *) a. Applicative f => a -> f a pure (Dec -> [Dec]) -> Q Dec -> Q [Dec] forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> CxtQ -> TypeQ -> [Q Dec] -> Q Dec instanceD ([TypeQ] -> CxtQ cxt []) TypeQ iHead [Q Dec] methods where queryString :: String queryString = Text -> String T.unpack Text query typeName :: TypeName typeName = TypeNameTH -> TypeName typename TypeNameTH rootTypeName iHead :: TypeQ iHead = Name -> [TypeName] -> TypeQ forall con cons. (ToName con, ToName cons) => con -> [cons] -> TypeQ applyCons ''Fetch [TypeName typeName] methods :: [Q Dec] methods = [ Name -> [ClauseQ] -> Q Dec funD 'fetch [[PatQ] -> BodyQ -> [Q Dec] -> ClauseQ clause [] (ExpQ -> BodyQ normalB [|__fetch queryString typeName|]) []], Dec -> Q Dec forall (f :: * -> *) a. Applicative f => a -> f a pure (Dec -> Q Dec) -> Dec -> Q Dec forall a b. (a -> b) -> a -> b $ Name -> Type -> Type -> Dec typeInstanceDec ''Args (TypeName -> Type forall a b. ToCon a b => a -> b toCon TypeName typeName) (Maybe TypeNameTH -> Type argumentType Maybe TypeNameTH clientArgumentsTypeName) ] argumentType :: Maybe TypeNameTH -> Type argumentType :: Maybe TypeNameTH -> Type argumentType Maybe TypeNameTH Nothing = String -> Type forall a b. ToCon a b => a -> b toCon (String "()" :: String) argumentType (Just TypeNameTH clientTypeName) = TypeName -> Type forall a b. ToCon a b => a -> b toCon (TypeNameTH -> TypeName typename TypeNameTH clientTypeName)