{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE NoImplicitPrelude #-}

module Data.Morpheus.Server.TH.Declare
  ( runDeclare,
  )
where

import Data.Morpheus.CodeGen.Internal.AST
  ( CodeGenConfig (..),
    ServerTypeDefinition,
  )
import Data.Morpheus.Server.TH.Declare.GQLType
  ( deriveGQLType,
  )
import Data.Morpheus.Server.TH.Declare.Type
  ( declareType,
  )
import Data.Morpheus.Server.TH.Utils (ServerDec)
import Language.Haskell.TH
import Relude

runDeclare :: Declare a => CodeGenConfig -> a -> Q [Dec]
runDeclare :: CodeGenConfig -> a -> Q [Dec]
runDeclare CodeGenConfig
ctx a
a = ReaderT CodeGenConfig Q [Dec] -> CodeGenConfig -> Q [Dec]
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT (a -> ReaderT CodeGenConfig Q [Dec]
forall a. Declare a => a -> ReaderT CodeGenConfig Q [Dec]
declare a
a) CodeGenConfig
ctx

class Declare a where
  declare :: a -> ServerDec [Dec]

instance Declare a => Declare [a] where
  declare :: [a] -> ReaderT CodeGenConfig Q [Dec]
declare = ([[Dec]] -> [Dec])
-> ReaderT CodeGenConfig Q [[Dec]] -> ReaderT CodeGenConfig Q [Dec]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [[Dec]] -> [Dec]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat (ReaderT CodeGenConfig Q [[Dec]] -> ReaderT CodeGenConfig Q [Dec])
-> ([a] -> ReaderT CodeGenConfig Q [[Dec]])
-> [a]
-> ReaderT CodeGenConfig Q [Dec]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> ReaderT CodeGenConfig Q [Dec])
-> [a] -> ReaderT CodeGenConfig Q [[Dec]]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse a -> ReaderT CodeGenConfig Q [Dec]
forall a. Declare a => a -> ReaderT CodeGenConfig Q [Dec]
declare

instance Declare ServerTypeDefinition where
  declare :: ServerTypeDefinition -> ReaderT CodeGenConfig Q [Dec]
declare ServerTypeDefinition
typeDef = (ServerTypeDefinition -> [Dec]
declareType ServerTypeDefinition
typeDef [Dec] -> [Dec] -> [Dec]
forall a. Semigroup a => a -> a -> a
<>) ([Dec] -> [Dec])
-> ReaderT CodeGenConfig Q [Dec] -> ReaderT CodeGenConfig Q [Dec]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ServerTypeDefinition -> ReaderT CodeGenConfig Q [Dec]
deriveGQLType ServerTypeDefinition
typeDef