{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE NoImplicitPrelude #-}

-- | GQL Types
module Data.Morpheus.Types
  ( GQLType (KIND, description, getDescriptions, typeOptions, getDirectives, defaultValues),
    EncodeScalar (..),
    EncodeWrapper (..),
    DecodeScalar (..),
    DecodeWrapper (..),
    GQLRequest (..),
    GQLResponse (..),
    ID (..),
    ScalarValue (..),
    RootResolver (..),
    constRes,
    constMutRes,
    Undefined,
    Resolver,
    QUERY,
    MUTATION,
    SUBSCRIPTION,
    lift,
    liftEither,
    failRes,
    WithOperation,
    publish,
    subscribe,
    unsafeInternalContext,
    ResolverContext (..),
    ResolverO,
    ComposedResolver,
    ResolverQ,
    ResolverM,
    ResolverS,
    ResolveQ,
    ResolveM,
    ResolveS,
    Res,
    MutRes,
    SubRes,
    IORes,
    IOMutRes,
    IOSubRes,
    SubscriptionField,
    App,
    RenderGQL,
    render,
    TypeGuard (..),
    Arg (..),
    NamedResolvers (..),

    -- * GQLType naming configuration
    GQLTypeOptions,
    defaultTypeOptions,
    fieldLabelModifier,
    constructorTagModifier,
    typeNameModifier,
    defaultRootResolver,
  )
where

import Control.Monad.Except (MonadError (..))
import Data.Morpheus.App
  ( App,
  )
import Data.Morpheus.App.Internal.Resolving
  ( PushEvents (..),
    Resolver,
    ResolverContext (..),
    SubscriptionField,
    WithOperation,
    pushEvents,
    subscribe,
    unsafeInternalContext,
  )
import Data.Morpheus.Core
  ( RenderGQL,
    render,
  )
import Data.Morpheus.NamedResolvers
  ( NamedResolverT (..),
    ResolveNamed (..),
  )
import Data.Morpheus.Server.Types.GQLType
  ( GQLType (..),
    GQLTypeOptions (..),
    defaultTypeOptions,
  )
import Data.Morpheus.Server.Types.Types
  ( Arg (..),
    TypeGuard (..),
    Undefined (..),
  )
import Data.Morpheus.Types.GQLScalar
  ( DecodeScalar (..),
    EncodeScalar (..),
  )
import Data.Morpheus.Types.GQLWrapper
  ( DecodeWrapper (..),
    EncodeWrapper (..),
  )
import Data.Morpheus.Types.ID (ID (..))
import Data.Morpheus.Types.IO
  ( GQLRequest (..),
    GQLResponse (..),
  )
import Data.Morpheus.Types.Internal.AST
  ( GQLError,
    MUTATION,
    QUERY,
    SUBSCRIPTION,
    ScalarValue (..),
  )
import Relude hiding (Undefined)

class FlexibleResolver (f :: Type -> Type) (a :: k) where
  type Flexible (m :: Type -> Type) a :: Type
  type Composed (m :: Type -> Type) f a :: Type

instance FlexibleResolver f (a :: Type) where
  type Flexible m a = m a
  type Composed m f a = m (f a)

instance FlexibleResolver f (a :: (Type -> Type) -> Type) where
  type Flexible m a = m (a m)
  type Composed m f a = m (f (a m))

type ResolverO o e m a =
  (WithOperation o) =>
  Flexible (Resolver o e m) a

type ComposedResolver o e m f a =
  (WithOperation o) =>
  Composed (Resolver o e m) f a

type ResolverQ e m a = Flexible (Resolver QUERY e m) a

type ResolverM e m a = Flexible (Resolver MUTATION e m) a

type ResolverS e m a = Flexible (Resolver SUBSCRIPTION e m) a

{-# DEPRECATED Res "use ResolverQ" #-}

type Res = Resolver QUERY

{-# DEPRECATED MutRes "use ResolverM" #-}

type MutRes = Resolver MUTATION

{-# DEPRECATED SubRes "use ResolverS" #-}

type SubRes = Resolver SUBSCRIPTION

{-# DEPRECATED IORes "use ResolverQ" #-}

type IORes e = Res e IO

{-# DEPRECATED IOMutRes "use ResolverM" #-}

type IOMutRes e = MutRes e IO

{-# DEPRECATED IOSubRes "use ResolverS" #-}

type IOSubRes e = SubRes e IO

{-# DEPRECATED ResolveQ "use ResolverQ" #-}

type ResolveQ e m a = ResolverQ e m a

{-# DEPRECATED ResolveM "use ResolverM" #-}

type ResolveM e m a = ResolverM e m a

{-# DEPRECATED ResolveS "use ResolverS" #-}

type ResolveS e m a = ResolverS e m a

publish :: Monad m => [e] -> Resolver MUTATION e m ()
publish :: forall (m :: * -> *) e. Monad m => [e] -> Resolver MUTATION e m ()
publish = forall e (m :: * -> *). PushEvents e m => [e] -> m ()
pushEvents

constRes :: (WithOperation o, Monad m) => b -> a -> Resolver o e m b
constRes :: forall (o :: OperationType) (m :: * -> *) b a e.
(WithOperation o, Monad m) =>
b -> a -> Resolver o e m b
constRes = forall a b. a -> b -> a
const forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a. Applicative f => a -> f a
pure

constMutRes :: Monad m => [e] -> a -> args -> ResolverM e m a
constMutRes :: forall (m :: * -> *) e a args.
Monad m =>
[e] -> a -> args -> ResolverM e m a
constMutRes [e]
events a
v = forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ do
  forall (m :: * -> *) e. Monad m => [e] -> Resolver MUTATION e m ()
publish [e]
events
  forall (f :: * -> *) a. Applicative f => a -> f a
pure a
v

{-# DEPRECATED failRes "use \"fail\" from \"MonadFail\"" #-}
failRes ::
  ( Monad m,
    WithOperation o
  ) =>
  String ->
  Resolver o e m a
failRes :: forall (m :: * -> *) (o :: OperationType) e a.
(Monad m, WithOperation o) =>
String -> Resolver o e m a
failRes = forall (m :: * -> *) a. MonadFail m => String -> m a
fail

liftEither :: (MonadTrans t, Monad (t m), MonadError GQLError (t m)) => Monad m => m (Either String a) -> t m a
liftEither :: forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad (t m), MonadError GQLError (t m), Monad m) =>
m (Either String a) -> t m a
liftEither m (Either String a)
x = forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m (Either String a)
x forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. IsString a => String -> a
fromString) forall (f :: * -> *) a. Applicative f => a -> f a
pure

-- | GraphQL Root resolver, also the interpreter generates a GQL schema from it.
--  'queryResolver' is required, 'mutationResolver' and 'subscriptionResolver' are optional,
--  if your schema does not supports __mutation__ or __subscription__ , you can use __()__ for it.
data
  RootResolver
    (m :: Type -> Type)
    event
    (query :: (Type -> Type) -> Type)
    (mutation :: (Type -> Type) -> Type)
    (subscription :: (Type -> Type) -> Type) = RootResolver
  { forall (m :: * -> *) event (query :: (* -> *) -> *)
       (mutation :: (* -> *) -> *) (subscription :: (* -> *) -> *).
RootResolver m event query mutation subscription
-> query (Resolver QUERY event m)
queryResolver :: query (Resolver QUERY event m),
    forall (m :: * -> *) event (query :: (* -> *) -> *)
       (mutation :: (* -> *) -> *) (subscription :: (* -> *) -> *).
RootResolver m event query mutation subscription
-> mutation (Resolver MUTATION event m)
mutationResolver :: mutation (Resolver MUTATION event m),
    forall (m :: * -> *) event (query :: (* -> *) -> *)
       (mutation :: (* -> *) -> *) (subscription :: (* -> *) -> *).
RootResolver m event query mutation subscription
-> subscription (Resolver SUBSCRIPTION event m)
subscriptionResolver :: subscription (Resolver SUBSCRIPTION event m)
  }

defaultRootResolver :: RootResolver m event Undefined Undefined Undefined
defaultRootResolver :: forall (m :: * -> *) event.
RootResolver m event Undefined Undefined Undefined
defaultRootResolver =
  RootResolver
    { queryResolver :: Undefined (Resolver QUERY event m)
queryResolver = forall (m :: * -> *). Bool -> Undefined m
Undefined Bool
False,
      mutationResolver :: Undefined (Resolver MUTATION event m)
mutationResolver = forall (m :: * -> *). Bool -> Undefined m
Undefined Bool
False,
      subscriptionResolver :: Undefined (Resolver SUBSCRIPTION event m)
subscriptionResolver = forall (m :: * -> *). Bool -> Undefined m
Undefined Bool
False
    }

data
  NamedResolvers
    (m :: Type -> Type)
    event
    (qu :: (Type -> Type) -> Type)
    (mu :: (Type -> Type) -> Type)
    (su :: (Type -> Type) -> Type)
  = ( ResolveNamed
        (Resolver QUERY event m)
        (qu (NamedResolverT (Resolver QUERY event m)))
    ) =>
    NamedResolvers