169 lines
6.0 KiB
Haskell
169 lines
6.0 KiB
Haskell
{-# LANGUAGE ExplicitForAll #-}
|
|
{-# LANGUAGE PatternSynonyms #-}
|
|
{-# LANGUAGE ViewPatterns #-}
|
|
|
|
-- | Output types and values.
|
|
--
|
|
-- This module is intended to be imported qualified, to avoid name clashes
|
|
-- with 'Language.GraphQL.Type.In'.
|
|
module Language.GraphQL.Type.Out
|
|
( Field(..)
|
|
, InterfaceType(..)
|
|
, ObjectType(..)
|
|
, Resolver(..)
|
|
, Type(..)
|
|
, UnionType(..)
|
|
, isNonNullType
|
|
, pattern EnumBaseType
|
|
, pattern InterfaceBaseType
|
|
, pattern ListBaseType
|
|
, pattern ObjectBaseType
|
|
, pattern ScalarBaseType
|
|
, pattern UnionBaseType
|
|
) where
|
|
|
|
import Data.HashMap.Strict (HashMap)
|
|
import Data.Text (Text)
|
|
import Language.GraphQL.AST (Name)
|
|
import Language.GraphQL.Trans
|
|
import Language.GraphQL.Type.Definition
|
|
import qualified Language.GraphQL.Type.In as In
|
|
|
|
-- | Resolves a 'Field' into an @Aeson.@'Data.Aeson.Types.Object' with error
|
|
-- information (if an error has occurred). @m@ is an arbitrary monad, usually
|
|
-- 'IO'.
|
|
--
|
|
-- Resolving a field can result in a leaf value or an object, which is
|
|
-- represented as a list of nested resolvers, used to resolve the fields of that
|
|
-- object.
|
|
data Resolver m = Resolver (Field m) (ActionT m Value)
|
|
|
|
-- | Object type definition.
|
|
--
|
|
-- Almost all of the GraphQL types you define will be object types. Object
|
|
-- types have a name, but most importantly describe their fields.
|
|
data ObjectType m = ObjectType
|
|
Name (Maybe Text) [InterfaceType m] (HashMap Name (Resolver m))
|
|
|
|
instance forall a. Eq (ObjectType a) where
|
|
(ObjectType this _ _ _) == (ObjectType that _ _ _) = this == that
|
|
|
|
-- | Interface Type Definition.
|
|
--
|
|
-- When a field can return one of a heterogeneous set of types, a Interface type
|
|
-- is used to describe what types are possible, and what fields are in common
|
|
-- across all types.
|
|
data InterfaceType m = InterfaceType
|
|
Name (Maybe Text) [InterfaceType m] (HashMap Name (Field m))
|
|
|
|
instance forall a. Eq (InterfaceType a) where
|
|
(InterfaceType this _ _ _) == (InterfaceType that _ _ _) = this == that
|
|
|
|
-- | Union Type Definition.
|
|
--
|
|
-- When a field can return one of a heterogeneous set of types, a Union type is
|
|
-- used to describe what types are possible.
|
|
data UnionType m = UnionType Name (Maybe Text) [ObjectType m]
|
|
|
|
instance forall a. Eq (UnionType a) where
|
|
(UnionType this _ _) == (UnionType that _ _) = this == that
|
|
|
|
-- | Output object field definition.
|
|
data Field m = Field
|
|
(Maybe Text) -- ^ Description.
|
|
(Type m) -- ^ Field type.
|
|
(HashMap Name In.Argument) -- ^ Arguments.
|
|
|
|
-- | These types may be used as output types as the result of fields.
|
|
--
|
|
-- GraphQL distinguishes between "wrapping" and "named" types. Each wrapping
|
|
-- type can wrap other wrapping or named types. Wrapping types are lists and
|
|
-- Non-Null types (named types are nullable by default).
|
|
data Type m
|
|
= NamedScalarType ScalarType
|
|
| NamedEnumType EnumType
|
|
| NamedObjectType (ObjectType m)
|
|
| NamedInterfaceType (InterfaceType m)
|
|
| NamedUnionType (UnionType m)
|
|
| ListType (Type m)
|
|
| NonNullScalarType ScalarType
|
|
| NonNullEnumType EnumType
|
|
| NonNullObjectType (ObjectType m)
|
|
| NonNullInterfaceType (InterfaceType m)
|
|
| NonNullUnionType (UnionType m)
|
|
| NonNullListType (Type m)
|
|
deriving Eq
|
|
|
|
-- | Matches either 'NamedScalarType' or 'NonNullScalarType'.
|
|
pattern ScalarBaseType :: forall m. ScalarType -> Type m
|
|
pattern ScalarBaseType scalarType <- (isScalarType -> Just scalarType)
|
|
|
|
-- | Matches either 'NamedEnumType' or 'NonNullEnumType'.
|
|
pattern EnumBaseType :: forall m. EnumType -> Type m
|
|
pattern EnumBaseType enumType <- (isEnumType -> Just enumType)
|
|
|
|
-- | Matches either 'NamedObjectType' or 'NonNullObjectType'.
|
|
pattern ObjectBaseType :: forall m. ObjectType m -> Type m
|
|
pattern ObjectBaseType objectType <- (isObjectType -> Just objectType)
|
|
|
|
-- | Matches either 'NamedInterfaceType' or 'NonNullInterfaceType'.
|
|
pattern InterfaceBaseType :: forall m. InterfaceType m -> Type m
|
|
pattern InterfaceBaseType interfaceType <-
|
|
(isInterfaceType -> Just interfaceType)
|
|
|
|
-- | Matches either 'NamedUnionType' or 'NonNullUnionType'.
|
|
pattern UnionBaseType :: forall m. UnionType m -> Type m
|
|
pattern UnionBaseType unionType <- (isUnionType -> Just unionType)
|
|
|
|
-- | Matches either 'ListType' or 'NonNullListType'.
|
|
pattern ListBaseType :: forall m. Type m -> Type m
|
|
pattern ListBaseType listType <- (isListType -> Just listType)
|
|
|
|
{-# COMPLETE ScalarBaseType
|
|
, EnumBaseType
|
|
, ObjectBaseType
|
|
, ListBaseType
|
|
, InterfaceBaseType
|
|
, UnionBaseType
|
|
#-}
|
|
|
|
isScalarType :: forall m. Type m -> Maybe ScalarType
|
|
isScalarType (NamedScalarType outputType) = Just outputType
|
|
isScalarType (NonNullScalarType outputType) = Just outputType
|
|
isScalarType _ = Nothing
|
|
|
|
isObjectType :: forall m. Type m -> Maybe (ObjectType m)
|
|
isObjectType (NamedObjectType outputType) = Just outputType
|
|
isObjectType (NonNullObjectType outputType) = Just outputType
|
|
isObjectType _ = Nothing
|
|
|
|
isEnumType :: forall m. Type m -> Maybe EnumType
|
|
isEnumType (NamedEnumType outputType) = Just outputType
|
|
isEnumType (NonNullEnumType outputType) = Just outputType
|
|
isEnumType _ = Nothing
|
|
|
|
isInterfaceType :: forall m. Type m -> Maybe (InterfaceType m)
|
|
isInterfaceType (NamedInterfaceType interfaceType) = Just interfaceType
|
|
isInterfaceType (NonNullInterfaceType interfaceType) = Just interfaceType
|
|
isInterfaceType _ = Nothing
|
|
|
|
isUnionType :: forall m. Type m -> Maybe (UnionType m)
|
|
isUnionType (NamedUnionType unionType) = Just unionType
|
|
isUnionType (NonNullUnionType unionType) = Just unionType
|
|
isUnionType _ = Nothing
|
|
|
|
isListType :: forall m. Type m -> Maybe (Type m)
|
|
isListType (ListType outputType) = Just outputType
|
|
isListType (NonNullListType outputType) = Just outputType
|
|
isListType _ = Nothing
|
|
|
|
-- | Checks whether the given output type is a non-null type.
|
|
isNonNullType :: forall m. Type m -> Bool
|
|
isNonNullType (NonNullScalarType _) = True
|
|
isNonNullType (NonNullEnumType _) = True
|
|
isNonNullType (NonNullObjectType _) = True
|
|
isNonNullType (NonNullInterfaceType _) = True
|
|
isNonNullType (NonNullUnionType _) = True
|
|
isNonNullType (NonNullListType _) = True
|
|
isNonNullType _ = False
|