{-# LANGUAGE DataKinds #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE NoImplicitPrelude #-}

module Data.Morpheus.Client.Build
  ( defineQuery,
  )
where

--
-- MORPHEUS
import Data.Morpheus.Client.Declare.Client
  ( declareClient,
  )
import Data.Morpheus.Client.Internal.Types
  ( ClientDefinition (..),
  )
import Data.Morpheus.Client.Transform.Selection
  ( toClientDefinition,
  )
import Data.Morpheus.Core
  ( Config (..),
    VALIDATION_MODE (..),
    validateRequest,
  )
import Data.Morpheus.Error
  ( gqlWarnings,
    renderGQLErrors,
  )
import Data.Morpheus.Internal.Ext
  ( GQLResult,
    Result (..),
  )
import Data.Morpheus.Types.Internal.AST
  ( ExecutableDocument (..),
    Operation (..),
    Schema,
    VALID,
  )
import Language.Haskell.TH
import Relude

defineQuery :: IO (GQLResult (Schema VALID)) -> (ExecutableDocument, String) -> Q [Dec]
defineQuery :: IO (GQLResult (Schema VALID))
-> (ExecutableDocument, String) -> Q [Dec]
defineQuery IO (GQLResult (Schema VALID))
ioSchema (ExecutableDocument
query, String
src) = do
  GQLResult (Schema VALID)
schema <- IO (GQLResult (Schema VALID)) -> Q (GQLResult (Schema VALID))
forall a. IO a -> Q a
runIO IO (GQLResult (Schema VALID))
ioSchema
  case GQLResult (Schema VALID)
schema GQLResult (Schema VALID)
-> (Schema VALID -> Result GQLError ClientDefinition)
-> Result GQLError ClientDefinition
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Schema VALID
-> ExecutableDocument -> Result GQLError ClientDefinition
`validateWith` ExecutableDocument
query) of
    Failure NonEmpty GQLError
errors -> String -> Q [Dec]
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (NonEmpty GQLError -> String
renderGQLErrors NonEmpty GQLError
errors)
    Success
      { ClientDefinition
result :: forall err a. Result err a -> a
result :: ClientDefinition
result,
        [GQLError]
warnings :: forall err a. Result err a -> [err]
warnings :: [GQLError]
warnings
      } -> [GQLError] -> Q ()
gqlWarnings [GQLError]
warnings Q () -> Q [Dec] -> Q [Dec]
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> String -> ClientDefinition -> Q [Dec]
declareClient String
src ClientDefinition
result

validateWith :: Schema VALID -> ExecutableDocument -> GQLResult ClientDefinition
validateWith :: Schema VALID
-> ExecutableDocument -> Result GQLError ClientDefinition
validateWith
  Schema VALID
schema
  rawRequest :: ExecutableDocument
rawRequest@ExecutableDocument
    { $sel:operation:ExecutableDocument :: ExecutableDocument -> Operation RAW
operation = Operation {VariableDefinitions RAW
operationArguments :: forall (s :: Stage). Operation s -> VariableDefinitions s
operationArguments :: VariableDefinitions RAW
operationArguments}
    } = do
    Operation VALID
validOperation <- Config
-> Schema VALID
-> ExecutableDocument
-> GQLResult (Operation VALID)
validateRequest Config :: Bool -> VALIDATION_MODE -> Config
Config {debug :: Bool
debug = Bool
False, validationMode :: VALIDATION_MODE
validationMode = VALIDATION_MODE
WITHOUT_VARIABLES} Schema VALID
schema ExecutableDocument
rawRequest
    Schema VALID
-> VariableDefinitions RAW
-> Operation VALID
-> Result GQLError ClientDefinition
toClientDefinition
      Schema VALID
schema
      VariableDefinitions RAW
operationArguments
      Operation VALID
validOperation