module GraphQL.Internal.Syntax.AST
( Name(unName)
, nameParser
, NameError(..)
, unsafeMakeName
, makeName
, QueryDocument(..)
, SchemaDocument(..)
, Definition(..)
, OperationDefinition(..)
, Node(..)
, getNodeName
, VariableDefinition(..)
, Variable(..)
, SelectionSet
, Selection(..)
, Field(..)
, Alias
, Argument(..)
, FragmentSpread(..)
, InlineFragment(..)
, FragmentDefinition(..)
, TypeCondition
, Value(..)
, StringValue(..)
, ListValue(..)
, ObjectValue(..)
, ObjectField(..)
, DefaultValue
, Directive(..)
, Type(..)
, NamedType(..)
, ListType(..)
, NonNullType(..)
, TypeDefinition(..)
, ObjectTypeDefinition(..)
, Interfaces
, FieldDefinition(..)
, ArgumentsDefinition
, InputValueDefinition(..)
, InterfaceTypeDefinition(..)
, UnionTypeDefinition(..)
, ScalarTypeDefinition(..)
, EnumTypeDefinition(..)
, EnumValueDefinition(..)
, InputObjectTypeDefinition(..)
, TypeExtensionDefinition(..)
) where
import Protolude
import qualified Data.Aeson as Aeson
import qualified Data.Attoparsec.Text as A
import Data.Char (isDigit)
import Data.String (IsString(..))
import Test.QuickCheck (Arbitrary(..), elements, listOf, oneof)
import GraphQL.Internal.Arbitrary (arbitraryText)
import GraphQL.Internal.Syntax.Tokens (tok)
newtype Name = Name { unName :: Text } deriving (Eq, Ord, Show)
unsafeMakeName :: HasCallStack => Text -> Name
unsafeMakeName name =
case makeName name of
Left e -> panic (show e)
Right n -> n
makeName :: Text -> Either NameError Name
makeName name = first (const (NameError name)) (A.parseOnly nameParser name)
newtype NameError = NameError Text deriving (Eq, Show)
instance IsString Name where
fromString = unsafeMakeName . toS
instance Aeson.ToJSON Name where
toJSON = Aeson.toJSON . unName
instance Arbitrary Name where
arbitrary = do
initial <- elements alpha
rest <- listOf (elements (alpha <> numeric))
pure (Name (toS (initial:rest)))
where
alpha = ['A'..'Z'] <> ['a'..'z'] <> ['_']
numeric = ['0'..'9']
nameParser :: A.Parser Name
nameParser = Name <$> tok ((<>) <$> A.takeWhile1 isA_z
<*> A.takeWhile ((||) <$> isDigit <*> isA_z))
where
isA_z = A.inClass $ '_' : ['A'..'Z'] <> ['a'..'z']
newtype QueryDocument = QueryDocument { getDefinitions :: [Definition] } deriving (Eq,Show)
data Definition = DefinitionOperation OperationDefinition
| DefinitionFragment FragmentDefinition
deriving (Eq,Show)
newtype SchemaDocument = SchemaDocument [TypeDefinition] deriving (Eq, Show)
data OperationDefinition
= Query Node
| Mutation Node
| AnonymousQuery SelectionSet
deriving (Eq,Show)
data Node = Node Name [VariableDefinition] [Directive] SelectionSet
deriving (Eq,Show)
getNodeName :: Node -> Name
getNodeName (Node name _ _ _) = name
data VariableDefinition = VariableDefinition Variable Type (Maybe DefaultValue)
deriving (Eq,Show)
newtype Variable = Variable Name deriving (Eq, Ord, Show)
instance Arbitrary Variable where
arbitrary = Variable <$> arbitrary
type SelectionSet = [Selection]
data Selection = SelectionField Field
| SelectionFragmentSpread FragmentSpread
| SelectionInlineFragment InlineFragment
deriving (Eq,Show)
data Field = Field (Maybe Alias) Name [Argument] [Directive] SelectionSet
deriving (Eq,Show)
type Alias = Name
data Argument = Argument Name Value deriving (Eq,Show)
data FragmentSpread = FragmentSpread Name [Directive]
deriving (Eq,Show)
data InlineFragment =
InlineFragment (Maybe TypeCondition) [Directive] SelectionSet
deriving (Eq,Show)
data FragmentDefinition =
FragmentDefinition Name TypeCondition [Directive] SelectionSet
deriving (Eq,Show)
type TypeCondition = NamedType
data Value = ValueVariable Variable
| ValueInt Int32
| ValueFloat Double
| ValueBoolean Bool
| ValueString StringValue
| ValueEnum Name
| ValueList ListValue
| ValueObject ObjectValue
| ValueNull
deriving (Eq, Show)
instance Arbitrary Value where
arbitrary = oneof [ ValueVariable <$> arbitrary
, ValueInt <$> arbitrary
, ValueFloat <$> arbitrary
, ValueBoolean <$> arbitrary
, ValueString <$> arbitrary
, ValueEnum <$> arbitrary
, ValueList <$> arbitrary
, ValueObject <$> arbitrary
, pure ValueNull
]
newtype StringValue = StringValue Text deriving (Eq,Show)
instance Arbitrary StringValue where
arbitrary = StringValue <$> arbitraryText
newtype ListValue = ListValue [Value] deriving (Eq,Show)
instance Arbitrary ListValue where
arbitrary = ListValue <$> listOf arbitrary
newtype ObjectValue = ObjectValue [ObjectField] deriving (Eq,Show)
instance Arbitrary ObjectValue where
arbitrary = ObjectValue <$> listOf arbitrary
data ObjectField = ObjectField Name Value deriving (Eq,Show)
instance Arbitrary ObjectField where
arbitrary = ObjectField <$> arbitrary <*> arbitrary
type DefaultValue = Value
data Directive = Directive Name [Argument] deriving (Eq,Show)
data Type = TypeNamed NamedType
| TypeList ListType
| TypeNonNull NonNullType
deriving (Eq, Ord, Show)
newtype NamedType = NamedType Name deriving (Eq, Ord, Show)
newtype ListType = ListType Type deriving (Eq, Ord, Show)
data NonNullType = NonNullTypeNamed NamedType
| NonNullTypeList ListType
deriving (Eq, Ord, Show)
data TypeDefinition = TypeDefinitionObject ObjectTypeDefinition
| TypeDefinitionInterface InterfaceTypeDefinition
| TypeDefinitionUnion UnionTypeDefinition
| TypeDefinitionScalar ScalarTypeDefinition
| TypeDefinitionEnum EnumTypeDefinition
| TypeDefinitionInputObject InputObjectTypeDefinition
| TypeDefinitionTypeExtension TypeExtensionDefinition
deriving (Eq,Show)
data ObjectTypeDefinition = ObjectTypeDefinition Name Interfaces [FieldDefinition]
deriving (Eq,Show)
type Interfaces = [NamedType]
data FieldDefinition = FieldDefinition Name ArgumentsDefinition Type
deriving (Eq,Show)
type ArgumentsDefinition = [InputValueDefinition]
data InputValueDefinition = InputValueDefinition Name Type (Maybe DefaultValue)
deriving (Eq,Show)
data InterfaceTypeDefinition = InterfaceTypeDefinition Name [FieldDefinition]
deriving (Eq,Show)
data UnionTypeDefinition = UnionTypeDefinition Name [NamedType]
deriving (Eq,Show)
newtype ScalarTypeDefinition = ScalarTypeDefinition Name
deriving (Eq,Show)
data EnumTypeDefinition = EnumTypeDefinition Name [EnumValueDefinition]
deriving (Eq,Show)
newtype EnumValueDefinition = EnumValueDefinition Name
deriving (Eq,Show)
data InputObjectTypeDefinition = InputObjectTypeDefinition Name [InputValueDefinition]
deriving (Eq,Show)
newtype TypeExtensionDefinition = TypeExtensionDefinition ObjectTypeDefinition
deriving (Eq,Show)