diff options
Diffstat (limited to 'src/Language/GraphQL/Type')
| -rw-r--r-- | src/Language/GraphQL/Type/Definition.hs | 174 | ||||
| -rw-r--r-- | src/Language/GraphQL/Type/In.hs | 89 | ||||
| -rw-r--r-- | src/Language/GraphQL/Type/Out.hs | 91 | ||||
| -rw-r--r-- | src/Language/GraphQL/Type/Schema.hs | 64 |
4 files changed, 214 insertions, 204 deletions
diff --git a/src/Language/GraphQL/Type/Definition.hs b/src/Language/GraphQL/Type/Definition.hs index 54eac85..aecb64a 100644 --- a/src/Language/GraphQL/Type/Definition.hs +++ b/src/Language/GraphQL/Type/Definition.hs @@ -1,28 +1,9 @@ -{-# LANGUAGE ExplicitForAll #-} {-# LANGUAGE OverloadedStrings #-} -{-# LANGUAGE PatternSynonyms #-} -{-# LANGUAGE ViewPatterns #-} --- | Types representing GraphQL type system. +-- | Types that can be used as both input and output types. module Language.GraphQL.Type.Definition - ( Argument(..) - , EnumType(..) - , Field(..) - , InputField(..) - , InputObjectType(..) - , InputType(..) - , ObjectType(..) - , OutputType(..) + ( EnumType(..) , ScalarType(..) - , TypeDefinition(..) - , pattern EnumInputTypeDefinition - , pattern ListInputTypeDefinition - , pattern ObjectInputTypeDefinition - , pattern ScalarInputTypeDefinition - , pattern EnumOutputTypeDefinition - , pattern ListOutputTypeDefinition - , pattern ObjectOutputTypeDefinition - , pattern ScalarOutputTypeDefinition , boolean , float , id @@ -30,31 +11,11 @@ module Language.GraphQL.Type.Definition , string ) where -import Data.HashMap.Strict (HashMap) import Data.Set (Set) import Data.Text (Text) import Language.GraphQL.AST.Document (Name) -import Language.GraphQL.Trans -import qualified Language.GraphQL.Type.In as In -import qualified Language.GraphQL.Type.Out as Out import Prelude hiding (id) --- | 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) (HashMap Name (Field m)) - --- | Output object field definition. -data Field m = Field - (Maybe Text) -- ^ Description. - (OutputType m) -- ^ Field type. - (HashMap Name Argument) -- ^ Arguments. - (ActionT m (Out.Value m)) -- ^ Resolver. - --- | Field argument definition. -data Argument = Argument (Maybe Text) InputType (Maybe In.Value) - -- | Scalar type definition. -- -- The leaf values of any request and input values to arguments are Scalars (or @@ -68,45 +29,6 @@ data ScalarType = ScalarType Name (Maybe Text) -- kind of type, often integers. data EnumType = EnumType Name (Maybe Text) (Set Text) --- | Single field of an 'InputObjectType'. -data InputField = InputField (Maybe Text) InputType (Maybe In.Value) - --- | Input object type definition. --- --- An input object defines a structured collection of fields which may be --- supplied to a field argument. -data InputObjectType = InputObjectType - Name (Maybe Text) (HashMap Name InputField) - --- | These types may be used as input types for arguments and directives. -data InputType - = ScalarInputType ScalarType - | EnumInputType EnumType - | ObjectInputType InputObjectType - | ListInputType InputType - | NonNullScalarInputType ScalarType - | NonNullEnumInputType EnumType - | NonNullObjectInputType InputObjectType - | NonNullListInputType InputType - --- | These types may be used as output types as the result of fields. -data OutputType m - = ScalarOutputType ScalarType - | EnumOutputType EnumType - | ObjectOutputType (ObjectType m) - | ListOutputType (OutputType m) - | NonNullScalarOutputType ScalarType - | NonNullEnumOutputType EnumType - | NonNullObjectOutputType (ObjectType m) - | NonNullListOutputType (OutputType m) - --- | These are all of the possible kinds of types. -data TypeDefinition m - = ScalarTypeDefinition ScalarType - | EnumTypeDefinition EnumType - | ObjectTypeDefinition (ObjectType m) - | InputObjectTypeDefinition InputObjectType - -- | The @String@ scalar type represents textual data, represented as UTF-8 -- character sequences. The String type is most often used by GraphQL to -- represent free-form human-readable text. @@ -158,95 +80,3 @@ id = ScalarType "ID" (Just description) \JSON response as a String; however, it is not intended to be \ \human-readable. When expected as an input type, any string (such as \ \`\"4\"`) or integer (such as `4`) input value will be accepted as an ID." - --- | Matches either 'ScalarInputType' or 'NonNullScalarInputType'. -pattern ScalarInputTypeDefinition :: ScalarType -> InputType -pattern ScalarInputTypeDefinition scalarType <- - (isScalarInputType -> Just scalarType) - --- | Matches either 'EnumInputType' or 'NonNullEnumInputType'. -pattern EnumInputTypeDefinition :: EnumType -> InputType -pattern EnumInputTypeDefinition enumType <- - (isEnumInputType -> Just enumType) - --- | Matches either 'ObjectInputType' or 'NonNullObjectInputType'. -pattern ObjectInputTypeDefinition :: InputObjectType -> InputType -pattern ObjectInputTypeDefinition objectType <- - (isObjectInputType -> Just objectType) - --- | Matches either 'ListInputType' or 'NonNullListInputType'. -pattern ListInputTypeDefinition :: InputType -> InputType -pattern ListInputTypeDefinition listType <- - (isListInputType -> Just listType) - -{-# COMPLETE EnumInputTypeDefinition - , ListInputTypeDefinition - , ObjectInputTypeDefinition - , ScalarInputTypeDefinition - #-} - --- | Matches either 'ScalarOutputType' or 'NonNullScalarOutputType'. -pattern ScalarOutputTypeDefinition :: forall m. ScalarType -> OutputType m -pattern ScalarOutputTypeDefinition scalarType <- - (isScalarOutputType -> Just scalarType) - --- | Matches either 'EnumOutputType' or 'NonNullEnumOutputType'. -pattern EnumOutputTypeDefinition :: forall m. EnumType -> OutputType m -pattern EnumOutputTypeDefinition enumType <- - (isEnumOutputType -> Just enumType) - --- | Matches either 'ObjectOutputType' or 'NonNullObjectOutputType'. -pattern ObjectOutputTypeDefinition :: forall m. ObjectType m -> OutputType m -pattern ObjectOutputTypeDefinition objectType <- - (isObjectOutputType -> Just objectType) - --- | Matches either 'ListOutputType' or 'NonNullListOutputType'. -pattern ListOutputTypeDefinition :: forall m. OutputType m -> OutputType m -pattern ListOutputTypeDefinition listType <- - (isListOutputType -> Just listType) - -{-# COMPLETE ScalarOutputTypeDefinition - , EnumOutputTypeDefinition - , ObjectOutputTypeDefinition - , ListOutputTypeDefinition - #-} - -isScalarInputType :: InputType -> Maybe ScalarType -isScalarInputType (ScalarInputType inputType) = Just inputType -isScalarInputType (NonNullScalarInputType inputType) = Just inputType -isScalarInputType _ = Nothing - -isObjectInputType :: InputType -> Maybe InputObjectType -isObjectInputType (ObjectInputType inputType) = Just inputType -isObjectInputType (NonNullObjectInputType inputType) = Just inputType -isObjectInputType _ = Nothing - -isEnumInputType :: InputType -> Maybe EnumType -isEnumInputType (EnumInputType inputType) = Just inputType -isEnumInputType (NonNullEnumInputType inputType) = Just inputType -isEnumInputType _ = Nothing - -isListInputType :: InputType -> Maybe InputType -isListInputType (ListInputType inputType) = Just inputType -isListInputType (NonNullListInputType inputType) = Just inputType -isListInputType _ = Nothing - -isScalarOutputType :: forall m. OutputType m -> Maybe ScalarType -isScalarOutputType (ScalarOutputType outputType) = Just outputType -isScalarOutputType (NonNullScalarOutputType outputType) = Just outputType -isScalarOutputType _ = Nothing - -isObjectOutputType :: forall m. OutputType m -> Maybe (ObjectType m) -isObjectOutputType (ObjectOutputType outputType) = Just outputType -isObjectOutputType (NonNullObjectOutputType outputType) = Just outputType -isObjectOutputType _ = Nothing - -isEnumOutputType :: forall m. OutputType m -> Maybe EnumType -isEnumOutputType (EnumOutputType outputType) = Just outputType -isEnumOutputType (NonNullEnumOutputType outputType) = Just outputType -isEnumOutputType _ = Nothing - -isListOutputType :: forall m. OutputType m -> Maybe (OutputType m) -isListOutputType (ListOutputType outputType) = Just outputType -isListOutputType (NonNullListOutputType outputType) = Just outputType -isListOutputType _ = Nothing diff --git a/src/Language/GraphQL/Type/In.hs b/src/Language/GraphQL/Type/In.hs index a6d35e2..c2e8ded 100644 --- a/src/Language/GraphQL/Type/In.hs +++ b/src/Language/GraphQL/Type/In.hs @@ -1,7 +1,21 @@ --- | This module is intended to be imported qualified, to avoid name clashes +{-# LANGUAGE PatternSynonyms #-} +{-# LANGUAGE ViewPatterns #-} + +-- | Input types and values. +-- +-- This module is intended to be imported qualified, to avoid name clashes -- with 'Language.GraphQL.Type.Out'. module Language.GraphQL.Type.In - ( Value(..) + ( Argument(..) + , InputField(..) + , InputObjectType(..) + , Type(..) + , Value(..) + , isNonNullType + , pattern EnumBaseType + , pattern ListBaseType + , pattern InputObjectBaseType + , pattern ScalarBaseType ) where import Data.HashMap.Strict (HashMap) @@ -9,6 +23,28 @@ import Data.Int (Int32) import Data.String (IsString(..)) import Data.Text (Text) import Language.GraphQL.AST.Document (Name) +import Language.GraphQL.Type.Definition + +-- | Single field of an 'InputObjectType'. +data InputField = InputField (Maybe Text) Type (Maybe Value) + +-- | Input object type definition. +-- +-- An input object defines a structured collection of fields which may be +-- supplied to a field argument. +data InputObjectType = InputObjectType + Name (Maybe Text) (HashMap Name InputField) + +-- | These types may be used as input types for arguments and directives. +data Type + = NamedScalarType ScalarType + | NamedEnumType EnumType + | NamedInputObjectType InputObjectType + | ListType Type + | NonNullScalarType ScalarType + | NonNullEnumType EnumType + | NonNullInputObjectType InputObjectType + | NonNullListType Type -- | Represents accordingly typed GraphQL values. data Value @@ -24,3 +60,52 @@ data Value instance IsString Value where fromString = String . fromString + +-- | Field argument definition. +data Argument = Argument (Maybe Text) Type (Maybe Value) + +-- | Matches either 'NamedScalarType' or 'NonNullScalarType'. +pattern ScalarBaseType :: ScalarType -> Type +pattern ScalarBaseType scalarType <- (isScalarType -> Just scalarType) + +-- | Matches either 'NamedEnumType' or 'NonNullEnumType'. +pattern EnumBaseType :: EnumType -> Type +pattern EnumBaseType enumType <- (isEnumType -> Just enumType) + +-- | Matches either 'NamedInputObjectType' or 'NonNullInputObjectType'. +pattern InputObjectBaseType :: InputObjectType -> Type +pattern InputObjectBaseType objectType <- (isInputObjectType -> Just objectType) + +-- | Matches either 'ListType' or 'NonNullListType'. +pattern ListBaseType :: Type -> Type +pattern ListBaseType listType <- (isListType -> Just listType) + +{-# COMPLETE EnumBaseType, ListBaseType, InputObjectBaseType, ScalarBaseType #-} + +isScalarType :: Type -> Maybe ScalarType +isScalarType (NamedScalarType inputType) = Just inputType +isScalarType (NonNullScalarType inputType) = Just inputType +isScalarType _ = Nothing + +isInputObjectType :: Type -> Maybe InputObjectType +isInputObjectType (NamedInputObjectType inputType) = Just inputType +isInputObjectType (NonNullInputObjectType inputType) = Just inputType +isInputObjectType _ = Nothing + +isEnumType :: Type -> Maybe EnumType +isEnumType (NamedEnumType inputType) = Just inputType +isEnumType (NonNullEnumType inputType) = Just inputType +isEnumType _ = Nothing + +isListType :: Type -> Maybe Type +isListType (ListType inputType) = Just inputType +isListType (NonNullListType inputType) = Just inputType +isListType _ = Nothing + +-- | Checks whether the given input type is a non-null type. +isNonNullType :: Type -> Bool +isNonNullType (NonNullScalarType _) = True +isNonNullType (NonNullEnumType _) = True +isNonNullType (NonNullInputObjectType _) = True +isNonNullType (NonNullListType _) = True +isNonNullType _ = False diff --git a/src/Language/GraphQL/Type/Out.hs b/src/Language/GraphQL/Type/Out.hs index 96bc9cf..b421f2e 100644 --- a/src/Language/GraphQL/Type/Out.hs +++ b/src/Language/GraphQL/Type/Out.hs @@ -1,9 +1,22 @@ +{-# LANGUAGE ExplicitForAll #-} {-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE PatternSynonyms #-} +{-# LANGUAGE ViewPatterns #-} --- | This module is intended to be imported qualified, to avoid name clashes +-- | 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 - ( Value(..) + ( Field(..) + , ObjectType(..) + , Type(..) + , Value(..) + , isNonNullType + , pattern EnumBaseType + , pattern ListBaseType + , pattern ObjectBaseType + , pattern ScalarBaseType ) where import Data.HashMap.Strict (HashMap) @@ -14,6 +27,32 @@ import Data.Text (Text) import qualified Data.Text as Text import Language.GraphQL.AST.Document (Name) import Language.GraphQL.Trans +import Language.GraphQL.Type.Definition +import qualified Language.GraphQL.Type.In as In +-- +-- | 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) (HashMap Name (Field m)) + +-- | Output object field definition. +data Field m = Field + (Maybe Text) -- ^ Description. + (Type m) -- ^ Field type. + (HashMap Name In.Argument) -- ^ Arguments. + (ActionT m (Value m)) -- ^ Resolver. + +-- | These types may be used as output types as the result of fields. +data Type m + = NamedScalarType ScalarType + | NamedEnumType EnumType + | NamedObjectType (ObjectType m) + | ListType (Type m) + | NonNullScalarType ScalarType + | NonNullEnumType EnumType + | NonNullObjectType (ObjectType m) + | NonNullListType (Type m) -- | GraphQL distinguishes between "wrapping" and "named" types. Each wrapping -- type can wrap other wrapping or named types. Wrapping types are lists and @@ -37,7 +76,7 @@ instance IsString (Value m) where instance Show (Value m) where show (Int integer) = "Int " ++ show integer - show (Float float) = "Float " ++ show float + show (Float float') = "Float " ++ show float' show (String text) = Text.unpack $ "String " <> text show (Boolean True) = "Boolean True" show (Boolean False) = "Boolean False" @@ -56,3 +95,49 @@ instance Eq (Value m) where (List this) == (List that) = this == that (Object this) == (Object that) = HashMap.keys this == HashMap.keys that _ == _ = False + +-- | 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 'ListType' or 'NonNullListType'. +pattern ListBaseType :: forall m. Type m -> Type m +pattern ListBaseType listType <- (isListType -> Just listType) + +{-# COMPLETE ScalarBaseType, EnumBaseType, ObjectBaseType, ListBaseType #-} + +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 + +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 (NonNullListType _) = True +isNonNullType _ = False diff --git a/src/Language/GraphQL/Type/Schema.hs b/src/Language/GraphQL/Type/Schema.hs index 095f27d..91096d3 100644 --- a/src/Language/GraphQL/Type/Schema.hs +++ b/src/Language/GraphQL/Type/Schema.hs @@ -3,13 +3,23 @@ -- | Schema Definition. module Language.GraphQL.Type.Schema ( Schema(..) + , Type(..) , collectReferencedTypes ) where import Data.HashMap.Strict (HashMap) import qualified Data.HashMap.Strict as HashMap import Language.GraphQL.AST.Core (Name) -import Language.GraphQL.Type.Definition +import qualified Language.GraphQL.Type.Definition as Definition +import qualified Language.GraphQL.Type.In as In +import qualified Language.GraphQL.Type.Out as Out + +-- | These are all of the possible kinds of types. +data Type m + = ScalarType Definition.ScalarType + | EnumType Definition.EnumType + | ObjectType (Out.ObjectType m) + | InputObjectType In.InputObjectType -- | A Schema is created by supplying the root types of each type of operation, -- query and mutation (optional). A schema definition is then supplied to the @@ -19,12 +29,12 @@ import Language.GraphQL.Type.Definition -- are reachable by traversing the root types are included, other types must -- be explicitly referenced. data Schema m = Schema - { query :: ObjectType m - , mutation :: Maybe (ObjectType m) + { query :: Out.ObjectType m + , mutation :: Maybe (Out.ObjectType m) } -- | Traverses the schema and finds all referenced types. -collectReferencedTypes :: forall m. Schema m -> HashMap Name (TypeDefinition m) +collectReferencedTypes :: forall m. Schema m -> HashMap Name (Type m) collectReferencedTypes schema = let queryTypes = traverseObjectType (query schema) HashMap.empty in maybe queryTypes (`traverseObjectType` queryTypes) $ mutation schema @@ -33,36 +43,36 @@ collectReferencedTypes schema = let newMap = HashMap.insert typeName element foundTypes in maybe (traverser newMap) (const foundTypes) $ HashMap.lookup typeName foundTypes - visitFields (Field _ outputType arguments _) foundTypes + visitFields (Out.Field _ outputType arguments _) foundTypes = traverseOutputType outputType $ foldr visitArguments foundTypes arguments - visitArguments (Argument _ inputType _) = traverseInputType inputType - visitInputFields (InputField _ inputType _) = traverseInputType inputType - traverseInputType (ObjectInputTypeDefinition objectType) = - let (InputObjectType typeName _ inputFields) = objectType - element = InputObjectTypeDefinition objectType + visitArguments (In.Argument _ inputType _) = traverseInputType inputType + visitInputFields (In.InputField _ inputType _) = traverseInputType inputType + traverseInputType (In.InputObjectBaseType objectType) = + let (In.InputObjectType typeName _ inputFields) = objectType + element = InputObjectType objectType traverser = flip (foldr visitInputFields) inputFields in collect traverser typeName element - traverseInputType (ListInputTypeDefinition listType) = + traverseInputType (In.ListBaseType listType) = traverseInputType listType - traverseInputType (ScalarInputTypeDefinition scalarType) = - let (ScalarType typeName _) = scalarType - in collect Prelude.id typeName (ScalarTypeDefinition scalarType) - traverseInputType (EnumInputTypeDefinition enumType) = - let (EnumType typeName _ _) = enumType - in collect Prelude.id typeName (EnumTypeDefinition enumType) - traverseOutputType (ObjectOutputTypeDefinition objectType) = + traverseInputType (In.ScalarBaseType scalarType) = + let (Definition.ScalarType typeName _) = scalarType + in collect Prelude.id typeName (ScalarType scalarType) + traverseInputType (In.EnumBaseType enumType) = + let (Definition.EnumType typeName _ _) = enumType + in collect Prelude.id typeName (EnumType enumType) + traverseOutputType (Out.ObjectBaseType objectType) = traverseObjectType objectType - traverseOutputType (ListOutputTypeDefinition listType) = + traverseOutputType (Out.ListBaseType listType) = traverseOutputType listType - traverseOutputType (ScalarOutputTypeDefinition scalarType) = - let (ScalarType typeName _) = scalarType - in collect Prelude.id typeName (ScalarTypeDefinition scalarType) - traverseOutputType (EnumOutputTypeDefinition enumType) = - let (EnumType typeName _ _) = enumType - in collect Prelude.id typeName (EnumTypeDefinition enumType) + traverseOutputType (Out.ScalarBaseType scalarType) = + let (Definition.ScalarType typeName _) = scalarType + in collect Prelude.id typeName (ScalarType scalarType) + traverseOutputType (Out.EnumBaseType enumType) = + let (Definition.EnumType typeName _ _) = enumType + in collect Prelude.id typeName (EnumType enumType) traverseObjectType objectType foundTypes = - let (ObjectType typeName _ objectFields) = objectType - element = ObjectTypeDefinition objectType + let (Out.ObjectType typeName _ objectFields) = objectType + element = ObjectType objectType traverser = flip (foldr visitFields) objectFields in collect traverser typeName element foundTypes |
