summaryrefslogtreecommitdiff
path: root/src/Language/GraphQL
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2019-12-28 07:07:58 +0100
committerEugen Wissner <belka@caraus.de>2019-12-28 07:07:58 +0100
commitfdf5914626ad172a8a459696f0114ef990c0d5cb (patch)
treed336c133d8ea7929a99b5e2e5bfedaa84d7dd6b2 /src/Language/GraphQL
parent78ee76f9d5bd59e6fe97dfb39ca690a473b256b1 (diff)
downloadgraphql-fdf5914626ad172a8a459696f0114ef990c0d5cb.tar.gz
Move AST to AST.Document
Diffstat (limited to 'src/Language/GraphQL')
-rw-r--r--src/Language/GraphQL/AST.hs155
-rw-r--r--src/Language/GraphQL/AST/Document.hs223
-rw-r--r--src/Language/GraphQL/AST/Encoder.hs2
-rw-r--r--src/Language/GraphQL/AST/Parser.hs17
-rw-r--r--src/Language/GraphQL/Execute/Transform.hs12
5 files changed, 226 insertions, 183 deletions
diff --git a/src/Language/GraphQL/AST.hs b/src/Language/GraphQL/AST.hs
index ea7912a..aba6dfd 100644
--- a/src/Language/GraphQL/AST.hs
+++ b/src/Language/GraphQL/AST.hs
@@ -1,157 +1,6 @@
-- | Target AST for Parser.
module Language.GraphQL.AST
- ( Alias
- , Argument(..)
- , ExecutableDefinition(..)
- , Directive(..)
- , FragmentDefinition(..)
- , Name
- , NonNullType(..)
- , ObjectField(..)
- , OperationDefinition(..)
- , OperationType(..)
- , Selection(..)
- , SelectionSet
- , SelectionSetOpt
- , Type(..)
- , TypeCondition
- , Value(..)
- , VariableDefinition(..)
+ ( module Language.GraphQL.AST.Document
) where
-import Data.Int (Int32)
-import Data.List.NonEmpty (NonEmpty)
-import Data.Text (Text)
-
--- | Name
-type Name = Text
-
--- | Directive.
-data Directive = Directive Name [Argument] deriving (Eq, Show)
-
--- * Operations
-
--- | Top-level definition of a document, either an operation or a fragment.
-data ExecutableDefinition
- = DefinitionOperation OperationDefinition
- | DefinitionFragment FragmentDefinition
- deriving (Eq, Show)
-
--- | Operation definition.
-data OperationDefinition
- = OperationSelectionSet SelectionSet
- | OperationDefinition OperationType
- (Maybe Name)
- [VariableDefinition]
- [Directive]
- SelectionSet
- deriving (Eq, Show)
-
--- | GraphQL has 3 operation types: queries, mutations and subscribtions.
---
--- Currently only queries and mutations are supported.
-data OperationType = Query | Mutation deriving (Eq, Show)
-
--- * Selections
-
--- | "Top-level" selection, selection on an operation or fragment.
-type SelectionSet = NonEmpty Selection
-
--- | Field selection.
-type SelectionSetOpt = [Selection]
-
--- | Single GraphQL field.
---
--- The only required property of a field is its name. Optionally it can also
--- have an alias, arguments or a list of subfields.
---
--- Given the following query:
---
--- @
--- {
--- zuck: user(id: 4) {
--- id
--- name
--- }
--- }
--- @
---
--- * "user", "id" and "name" are field names.
--- * "user" has two subfields, "id" and "name".
--- * "zuck" is an alias for "user". "id" and "name" have no aliases.
--- * "id: 4" is an argument for "user". "id" and "name" don't have any
--- arguments.
-data Selection
- = Field (Maybe Alias) Name [Argument] [Directive] SelectionSetOpt
- | FragmentSpread Name [Directive]
- | InlineFragment (Maybe TypeCondition) [Directive] SelectionSet
- deriving (Eq, Show)
-
--- | Alternative field name.
---
--- @
--- {
--- smallPic: profilePic(size: 64)
--- bigPic: profilePic(size: 1024)
--- }
--- @
---
--- Here "smallPic" and "bigPic" are aliases for the same field, "profilePic",
--- used to distinquish between profile pictures with different arguments
--- (sizes).
-type Alias = Name
-
--- | Single argument.
---
--- @
--- {
--- user(id: 4) {
--- name
--- }
--- }
--- @
---
--- Here "id" is an argument for the field "user" and its value is 4.
-data Argument = Argument Name Value deriving (Eq,Show)
-
--- | Fragment definition.
-data FragmentDefinition
- = FragmentDefinition Name TypeCondition [Directive] SelectionSet
- deriving (Eq, Show)
-
--- * Inputs
-
--- | Input value.
-data Value = Variable Name
- | Int Int32
- | Float Double
- | String Text
- | Boolean Bool
- | Null
- | Enum Name
- | List [Value]
- | Object [ObjectField]
- deriving (Eq, Show)
-
--- | Key-value pair.
---
--- A list of 'ObjectField's represents a GraphQL object type.
-data ObjectField = ObjectField Name Value deriving (Eq, Show)
-
--- | Variable definition.
-data VariableDefinition = VariableDefinition Name Type (Maybe Value)
- deriving (Eq, Show)
-
--- | Type condition.
-type TypeCondition = Name
-
--- | Type representation.
-data Type = TypeNamed Name
- | TypeList Type
- | TypeNonNull NonNullType
- deriving (Eq, Show)
-
--- | Helper type to represent Non-Null types and lists of such types.
-data NonNullType = NonNullTypeNamed Name
- | NonNullTypeList Type
- deriving (Eq, Show)
+import Language.GraphQL.AST.Document
diff --git a/src/Language/GraphQL/AST/Document.hs b/src/Language/GraphQL/AST/Document.hs
index ebe8918..b94b629 100644
--- a/src/Language/GraphQL/AST/Document.hs
+++ b/src/Language/GraphQL/AST/Document.hs
@@ -1,34 +1,46 @@
-- | This module defines an abstract syntax tree for the @GraphQL@ language. It
--- follows closely the structure given in the specification. Please refer to
--- <https://facebook.github.io/graphql/ Facebook's GraphQL Specification>.
--- for more information.
+-- follows closely the structure given in the specification. Please refer to
+-- <https://facebook.github.io/graphql/ Facebook's GraphQL Specification>.
+-- for more information.
module Language.GraphQL.AST.Document
- ( Definition(..)
+ ( Alias
+ , Argument(..)
+ , Definition(ExecutableDefinition)
+ , Directive(..)
, Document
, ExecutableDefinition(..)
+ , FragmentDefinition(..)
+ , Name
+ , NonNullType(..)
+ , ObjectField(..)
+ , OperationDefinition(..)
+ , OperationType(..)
+ , Selection(..)
+ , SelectionSet
+ , SelectionSetOpt
+ , Type(..)
+ , TypeCondition
+ , Value(..)
+ , VariableDefinition(..)
) where
+import Data.Int (Int32)
import Data.List.NonEmpty (NonEmpty)
import Data.Text (Text)
-import Language.GraphQL.AST
- ( ExecutableDefinition(..)
- , Directive
- , Name
- , OperationType
- , Type
- , Value
- )
import Language.GraphQL.AST.DirectiveLocation
-- * Language
+-- ** Source Text
+
+-- | Name.
+type Name = Text
+
-- ** Document
-- | GraphQL document.
type Document = NonEmpty Definition
-type NamedType = Name
-
-- | All kinds of definitions that can occur in a GraphQL document.
data Definition
= ExecutableDefinition ExecutableDefinition
@@ -36,12 +48,190 @@ data Definition
| TypeSystemExtension TypeSystemExtension
deriving (Eq, Show)
+-- | Top-level definition of a document, either an operation or a fragment.
+data ExecutableDefinition
+ = DefinitionOperation OperationDefinition
+ | DefinitionFragment FragmentDefinition
+ deriving (Eq, Show)
+
+-- ** Operations
+
+-- | Operation definition.
+data OperationDefinition
+ = SelectionSet SelectionSet
+ | OperationDefinition
+ OperationType
+ (Maybe Name)
+ [VariableDefinition]
+ [Directive]
+ SelectionSet
+ deriving (Eq, Show)
+
+-- | GraphQL has 3 operation types:
+--
+-- * query - a read-only fetch.
+-- * mutation - a write operation followed by a fetch.
+-- * subscription - a long-lived request that fetches data in response to
+-- source events.
+--
+-- Currently only queries and mutations are supported.
+data OperationType = Query | Mutation deriving (Eq, Show)
+
+-- ** Selection Sets
+
+-- | "Top-level" selection, selection on an operation or fragment.
+type SelectionSet = NonEmpty Selection
+
+-- | Field selection.
+type SelectionSetOpt = [Selection]
+
+-- | Selection is a single entry in a selection set. It can be a single field,
+-- fragment spread or inline fragment.
+--
+-- The only required property of a field is its name. Optionally it can also
+-- have an alias, arguments, directives and a list of subfields.
+--
+-- In the following query "user" is a field with two subfields, "id" and "name":
+--
+-- @
+-- {
+-- user {
+-- id
+-- name
+-- }
+-- }
+-- @
+--
+-- A fragment spread refers to a fragment defined outside the operation and is
+-- expanded at the execution time.
+--
+-- @
+-- {
+-- user {
+-- ...userFragment
+-- }
+-- }
+--
+-- fragment userFragment on UserType {
+-- id
+-- name
+-- }
+-- @
+--
+-- Inline fragments are similar but they don't have any name and the type
+-- condition ("on UserType") is optional.
+--
+-- @
+-- {
+-- user {
+-- ... on UserType {
+-- id
+-- name
+-- }
+-- }
+-- @
+data Selection
+ = Field (Maybe Alias) Name [Argument] [Directive] SelectionSetOpt
+ | FragmentSpread Name [Directive]
+ | InlineFragment (Maybe TypeCondition) [Directive] SelectionSet
+ deriving (Eq, Show)
+
+-- ** Arguments
+
+-- | Single argument.
+--
+-- @
+-- {
+-- user(id: 4) {
+-- name
+-- }
+-- }
+-- @
+--
+-- Here "id" is an argument for the field "user" and its value is 4.
+data Argument = Argument Name Value deriving (Eq,Show)
+
+-- ** Field Alias
+
+-- | Alternative field name.
+--
+-- @
+-- {
+-- smallPic: profilePic(size: 64)
+-- bigPic: profilePic(size: 1024)
+-- }
+-- @
+--
+-- Here "smallPic" and "bigPic" are aliases for the same field, "profilePic",
+-- used to distinquish between profile pictures with different arguments
+-- (sizes).
+type Alias = Name
+
+-- ** Fragments
+
+-- | Fragment definition.
+data FragmentDefinition
+ = FragmentDefinition Name TypeCondition [Directive] SelectionSet
+ deriving (Eq, Show)
+
+-- | Type condition.
+type TypeCondition = Name
+
+-- ** Input Values
+
+-- | Input value.
+data Value
+ = Variable Name
+ | Int Int32
+ | Float Double
+ | String Text
+ | Boolean Bool
+ | Null
+ | Enum Name
+ | List [Value]
+ | Object [ObjectField]
+ deriving (Eq, Show)
+
+-- | Key-value pair.
+--
+-- A list of 'ObjectField's represents a GraphQL object type.
+data ObjectField = ObjectField Name Value deriving (Eq, Show)
+
+-- ** Variables
+
+-- | Variable definition.
+data VariableDefinition = VariableDefinition Name Type (Maybe Value)
+ deriving (Eq, Show)
+
+-- ** Type References
+
+-- | Type representation.
+data Type
+ = TypeNamed Name
+ | TypeList Type
+ | TypeNonNull NonNullType
+ deriving (Eq, Show)
+
+type NamedType = Name
+
+-- | Helper type to represent Non-Null types and lists of such types.
+data NonNullType
+ = NonNullTypeNamed Name
+ | NonNullTypeList Type
+ deriving (Eq, Show)
+
+-- ** Directives
+
+-- | Directive.
+data Directive = Directive Name [Argument] deriving (Eq, Show)
+
-- * Type System
data TypeSystemDefinition
= SchemaDefinition [Directive] RootOperationTypeDefinitions
| TypeDefinition TypeDefinition
- | DirectiveDefinition Description Name ArgumentsDefinition DirectiveLocation
+ | DirectiveDefinition
+ Description Name ArgumentsDefinition DirectiveLocation
deriving (Eq, Show)
-- ** Type System Extensions
@@ -109,7 +299,8 @@ newtype ImplementsInterfaces = ImplementsInterfaces (NonEmpty NamedType)
newtype ImplementsInterfacesOpt = ImplementsInterfacesOpt [NamedType]
deriving (Eq, Show)
-data FieldDefinition = FieldDefinition Description Name ArgumentsDefinition Type
+data FieldDefinition
+ = FieldDefinition Description Name ArgumentsDefinition Type
deriving (Eq, Show)
newtype ArgumentsDefinition = ArgumentsDefinition [InputValueDefinition]
diff --git a/src/Language/GraphQL/AST/Encoder.hs b/src/Language/GraphQL/AST/Encoder.hs
index e33068d..eb865c9 100644
--- a/src/Language/GraphQL/AST/Encoder.hs
+++ b/src/Language/GraphQL/AST/Encoder.hs
@@ -66,7 +66,7 @@ definition formatter x
= fragmentDefinition formatter fragment
operationDefinition :: Formatter -> Full.OperationDefinition -> Lazy.Text
-operationDefinition formatter (Full.OperationSelectionSet sels)
+operationDefinition formatter (Full.SelectionSet sels)
= selectionSet formatter sels
operationDefinition formatter (Full.OperationDefinition Full.Query name vars dirs sels)
= "query " <> node formatter name vars dirs sels
diff --git a/src/Language/GraphQL/AST/Parser.hs b/src/Language/GraphQL/AST/Parser.hs
index ad2b96d..113b0a4 100644
--- a/src/Language/GraphQL/AST/Parser.hs
+++ b/src/Language/GraphQL/AST/Parser.hs
@@ -25,13 +25,16 @@ definition = DefinitionOperation <$> operationDefinition
<?> "definition error!"
operationDefinition :: Parser OperationDefinition
-operationDefinition = OperationSelectionSet <$> selectionSet
- <|> OperationDefinition <$> operationType
- <*> optional name
- <*> opt variableDefinitions
- <*> opt directives
- <*> selectionSet
- <?> "operationDefinition error"
+operationDefinition = SelectionSet <$> selectionSet
+ <|> operationDefinition'
+ <?> "operationDefinition error"
+ where
+ operationDefinition'
+ = OperationDefinition <$> operationType
+ <*> optional name
+ <*> opt variableDefinitions
+ <*> opt directives
+ <*> selectionSet
operationType :: Parser OperationType
operationType = Query <$ symbol "query"
diff --git a/src/Language/GraphQL/Execute/Transform.hs b/src/Language/GraphQL/Execute/Transform.hs
index 28b9481..7c2e100 100644
--- a/src/Language/GraphQL/Execute/Transform.hs
+++ b/src/Language/GraphQL/Execute/Transform.hs
@@ -58,13 +58,13 @@ operations operations' = do
lift . lift $ NonEmpty.nonEmpty coreOperations
operation :: Full.OperationDefinition -> TransformT Core.Operation
-operation (Full.OperationSelectionSet sels) =
- operation $ Full.OperationDefinition Full.Query mempty mempty mempty sels
+operation (Full.SelectionSet sels)
+ = operation $ Full.OperationDefinition Full.Query mempty mempty mempty sels
-- TODO: Validate Variable definitions with substituter
-operation (Full.OperationDefinition Full.Query name _vars _dirs sels) =
- Core.Query name <$> appendSelection sels
-operation (Full.OperationDefinition Full.Mutation name _vars _dirs sels) =
- Core.Mutation name <$> appendSelection sels
+operation (Full.OperationDefinition Full.Query name _vars _dirs sels)
+ = Core.Query name <$> appendSelection sels
+operation (Full.OperationDefinition Full.Mutation name _vars _dirs sels)
+ = Core.Mutation name <$> appendSelection sels
-- * Selection