2020-07-20 21:29:12 +02:00
|
|
|
{- This Source Code Form is subject to the terms of the Mozilla Public License,
|
|
|
|
v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
|
|
|
obtain one at https://mozilla.org/MPL/2.0/. -}
|
|
|
|
|
2020-09-17 10:33:37 +02:00
|
|
|
{-# LANGUAGE LambdaCase #-}
|
2020-09-28 07:06:15 +02:00
|
|
|
{-# LANGUAGE OverloadedStrings #-}
|
2020-09-25 21:57:25 +02:00
|
|
|
{-# LANGUAGE ScopedTypeVariables #-}
|
2020-07-20 21:29:12 +02:00
|
|
|
|
2020-07-24 21:34:31 +02:00
|
|
|
-- | GraphQL validator.
|
2020-07-20 21:29:12 +02:00
|
|
|
module Language.GraphQL.Validate
|
2020-09-28 07:06:15 +02:00
|
|
|
( Validation.Error(..)
|
2020-07-20 21:29:12 +02:00
|
|
|
, document
|
|
|
|
, module Language.GraphQL.Validate.Rules
|
|
|
|
) where
|
|
|
|
|
2020-09-14 07:49:33 +02:00
|
|
|
import Control.Monad (join)
|
|
|
|
import Control.Monad.Trans.Class (MonadTrans(..))
|
|
|
|
import Control.Monad.Trans.Reader (runReaderT)
|
2020-09-18 07:32:58 +02:00
|
|
|
import Data.Foldable (toList)
|
2020-09-25 21:57:25 +02:00
|
|
|
import Data.HashMap.Strict (HashMap)
|
|
|
|
import qualified Data.HashMap.Strict as HashMap
|
2020-07-20 21:29:12 +02:00
|
|
|
import Data.Sequence (Seq(..), (><), (|>))
|
|
|
|
import qualified Data.Sequence as Seq
|
2020-09-28 07:06:15 +02:00
|
|
|
import Language.GraphQL.AST.DirectiveLocation (DirectiveLocation(..))
|
|
|
|
import qualified Language.GraphQL.AST.DirectiveLocation as DirectiveLocation
|
2020-07-20 21:29:12 +02:00
|
|
|
import Language.GraphQL.AST.Document
|
2020-08-25 21:03:42 +02:00
|
|
|
import Language.GraphQL.Type.Internal
|
2020-09-28 07:06:15 +02:00
|
|
|
import qualified Language.GraphQL.Type.Definition as Definition
|
|
|
|
import qualified Language.GraphQL.Type.In as In
|
2020-09-25 21:57:25 +02:00
|
|
|
import qualified Language.GraphQL.Type.Out as Out
|
2020-09-28 07:06:15 +02:00
|
|
|
import Language.GraphQL.Type.Schema (Schema)
|
2020-09-25 21:57:25 +02:00
|
|
|
import qualified Language.GraphQL.Type.Schema as Schema
|
2020-07-20 21:29:12 +02:00
|
|
|
import Language.GraphQL.Validate.Rules
|
2020-09-28 07:06:15 +02:00
|
|
|
import Language.GraphQL.Validate.Validation (Validation(Validation))
|
|
|
|
import qualified Language.GraphQL.Validate.Validation as Validation
|
2020-07-20 21:29:12 +02:00
|
|
|
|
2020-09-28 07:06:15 +02:00
|
|
|
type ApplySelectionRule m a
|
|
|
|
= HashMap Name (Schema.Type m)
|
|
|
|
-> Validation.Rule m
|
|
|
|
-> Maybe (Out.Type m)
|
|
|
|
-> a
|
|
|
|
-> Seq (Validation.RuleT m)
|
|
|
|
|
|
|
|
type ApplyRule m a = Validation.Rule m -> a -> Seq (Validation.RuleT m)
|
2020-09-25 21:57:25 +02:00
|
|
|
|
2020-07-24 21:34:31 +02:00
|
|
|
-- | Validates a document and returns a list of found errors. If the returned
|
|
|
|
-- list is empty, the document is valid.
|
2020-09-28 07:06:15 +02:00
|
|
|
document :: forall m
|
|
|
|
. Schema m
|
|
|
|
-> [Validation.Rule m]
|
|
|
|
-> Document
|
|
|
|
-> Seq Validation.Error
|
2020-07-20 21:29:12 +02:00
|
|
|
document schema' rules' document' =
|
2020-09-14 07:49:33 +02:00
|
|
|
runReaderT reader context
|
2020-07-20 21:29:12 +02:00
|
|
|
where
|
2020-08-25 21:03:42 +02:00
|
|
|
context = Validation
|
2020-09-28 07:06:15 +02:00
|
|
|
{ Validation.ast = document'
|
|
|
|
, Validation.schema = schema'
|
|
|
|
, Validation.types = collectReferencedTypes schema'
|
|
|
|
, Validation.directives = allDirectives
|
2020-07-20 21:29:12 +02:00
|
|
|
}
|
2020-09-28 07:06:15 +02:00
|
|
|
allDirectives =
|
|
|
|
HashMap.union (Schema.directives schema') defaultDirectives
|
|
|
|
defaultDirectives = HashMap.fromList
|
|
|
|
[ ("skip", skipDirective)
|
|
|
|
, ("include", includeDirective)
|
|
|
|
, ("deprecated", deprecatedDirective)
|
|
|
|
]
|
|
|
|
includeDirective =
|
|
|
|
Schema.Directive includeDescription skipIncludeLocations includeArguments
|
|
|
|
includeArguments = HashMap.singleton "if"
|
|
|
|
$ In.Argument (Just "Included when true.") ifType Nothing
|
|
|
|
includeDescription = Just
|
|
|
|
"Directs the executor to include this field or fragment only when the \
|
|
|
|
\`if` argument is true."
|
|
|
|
skipDirective =
|
|
|
|
Schema.Directive skipDescription skipIncludeLocations skipArguments
|
|
|
|
skipArguments = HashMap.singleton "if"
|
|
|
|
$ In.Argument (Just "skipped when true.") ifType Nothing
|
|
|
|
ifType = In.NonNullScalarType Definition.boolean
|
|
|
|
skipDescription = Just
|
|
|
|
"Directs the executor to skip this field or fragment when the `if` \
|
|
|
|
\argument is true."
|
|
|
|
skipIncludeLocations =
|
|
|
|
[ ExecutableDirectiveLocation DirectiveLocation.Field
|
|
|
|
, ExecutableDirectiveLocation DirectiveLocation.FragmentSpread
|
|
|
|
, ExecutableDirectiveLocation DirectiveLocation.InlineFragment
|
|
|
|
]
|
|
|
|
deprecatedDirective =
|
|
|
|
Schema.Directive deprecatedDescription deprecatedLocations deprecatedArguments
|
|
|
|
reasonDescription = Just
|
|
|
|
"Explains why this element was deprecated, usually also including a \
|
|
|
|
\suggestion for how to access supported similar data. Formatted using \
|
|
|
|
\the Markdown syntax, as specified by \
|
|
|
|
\[CommonMark](https://commonmark.org/).'"
|
|
|
|
deprecatedArguments = HashMap.singleton "reason"
|
|
|
|
$ In.Argument reasonDescription reasonType
|
|
|
|
$ Just "No longer supported"
|
|
|
|
reasonType = In.NamedScalarType Definition.string
|
|
|
|
deprecatedDescription = Just
|
|
|
|
"Marks an element of a GraphQL schema as no longer supported."
|
|
|
|
deprecatedLocations =
|
|
|
|
[ TypeSystemDirectiveLocation DirectiveLocation.FieldDefinition
|
|
|
|
, TypeSystemDirectiveLocation DirectiveLocation.ArgumentDefinition
|
|
|
|
, TypeSystemDirectiveLocation DirectiveLocation.InputFieldDefinition
|
|
|
|
, TypeSystemDirectiveLocation DirectiveLocation.EnumValue
|
|
|
|
]
|
2020-09-14 07:49:33 +02:00
|
|
|
reader = do
|
|
|
|
rule' <- lift $ Seq.fromList rules'
|
2020-09-25 21:57:25 +02:00
|
|
|
join $ lift $ foldr (definition rule' context) Seq.empty document'
|
2020-09-14 07:49:33 +02:00
|
|
|
|
2020-09-28 07:06:15 +02:00
|
|
|
definition :: Validation.Rule m
|
2020-09-25 21:57:25 +02:00
|
|
|
-> Validation m
|
|
|
|
-> Definition
|
2020-09-28 07:06:15 +02:00
|
|
|
-> Seq (Validation.RuleT m)
|
|
|
|
-> Seq (Validation.RuleT m)
|
|
|
|
definition (Validation.DefinitionRule rule) _ definition' accumulator =
|
2020-09-17 10:33:37 +02:00
|
|
|
accumulator |> rule definition'
|
2020-09-25 21:57:25 +02:00
|
|
|
definition rule context (ExecutableDefinition definition') accumulator =
|
|
|
|
accumulator >< executableDefinition rule context definition'
|
|
|
|
definition rule _ (TypeSystemDefinition typeSystemDefinition' _) accumulator =
|
2020-09-17 10:33:37 +02:00
|
|
|
accumulator >< typeSystemDefinition rule typeSystemDefinition'
|
2020-09-25 21:57:25 +02:00
|
|
|
definition rule _ (TypeSystemExtension extension _) accumulator =
|
2020-09-17 10:33:37 +02:00
|
|
|
accumulator >< typeSystemExtension rule extension
|
|
|
|
|
2020-09-28 07:06:15 +02:00
|
|
|
typeSystemExtension :: forall m. ApplyRule m TypeSystemExtension
|
2020-09-17 10:33:37 +02:00
|
|
|
typeSystemExtension rule = \case
|
|
|
|
SchemaExtension extension -> schemaExtension rule extension
|
|
|
|
TypeExtension extension -> typeExtension rule extension
|
|
|
|
|
2020-09-28 07:06:15 +02:00
|
|
|
typeExtension :: forall m. ApplyRule m TypeExtension
|
2020-09-17 10:33:37 +02:00
|
|
|
typeExtension rule = \case
|
|
|
|
ScalarTypeExtension _ directives' -> directives rule directives'
|
|
|
|
ObjectTypeFieldsDefinitionExtension _ _ directives' fields ->
|
|
|
|
directives rule directives' >< foldMap (fieldDefinition rule) fields
|
|
|
|
ObjectTypeDirectivesExtension _ _ directives' -> directives rule directives'
|
|
|
|
ObjectTypeImplementsInterfacesExtension _ _ -> mempty
|
|
|
|
InterfaceTypeFieldsDefinitionExtension _ directives' fields ->
|
|
|
|
directives rule directives' >< foldMap (fieldDefinition rule) fields
|
|
|
|
InterfaceTypeDirectivesExtension _ directives' ->
|
|
|
|
directives rule directives'
|
|
|
|
UnionTypeUnionMemberTypesExtension _ directives' _ ->
|
|
|
|
directives rule directives'
|
|
|
|
UnionTypeDirectivesExtension _ directives' -> directives rule directives'
|
|
|
|
EnumTypeEnumValuesDefinitionExtension _ directives' values ->
|
|
|
|
directives rule directives' >< foldMap (enumValueDefinition rule) values
|
|
|
|
EnumTypeDirectivesExtension _ directives' -> directives rule directives'
|
|
|
|
InputObjectTypeInputFieldsDefinitionExtension _ directives' fields
|
|
|
|
-> directives rule directives'
|
|
|
|
>< foldMap (inputValueDefinition rule) fields
|
|
|
|
InputObjectTypeDirectivesExtension _ directives' ->
|
|
|
|
directives rule directives'
|
|
|
|
|
2020-09-28 07:06:15 +02:00
|
|
|
schemaExtension :: forall m. ApplyRule m SchemaExtension
|
2020-09-17 10:33:37 +02:00
|
|
|
schemaExtension rule = \case
|
|
|
|
SchemaOperationExtension directives' _ -> directives rule directives'
|
|
|
|
SchemaDirectivesExtension directives' -> directives rule directives'
|
2020-09-14 07:49:33 +02:00
|
|
|
|
2020-09-28 07:06:15 +02:00
|
|
|
executableDefinition :: forall m
|
|
|
|
. Validation.Rule m
|
2020-09-25 21:57:25 +02:00
|
|
|
-> Validation m
|
|
|
|
-> ExecutableDefinition
|
2020-09-28 07:06:15 +02:00
|
|
|
-> Seq (Validation.RuleT m)
|
2020-09-25 21:57:25 +02:00
|
|
|
executableDefinition rule context (DefinitionOperation operation) =
|
|
|
|
operationDefinition rule context operation
|
|
|
|
executableDefinition rule context (DefinitionFragment fragment) =
|
|
|
|
fragmentDefinition rule context fragment
|
2020-09-14 07:49:33 +02:00
|
|
|
|
2020-09-28 07:06:15 +02:00
|
|
|
typeSystemDefinition :: forall m. ApplyRule m TypeSystemDefinition
|
2020-09-17 10:33:37 +02:00
|
|
|
typeSystemDefinition rule = \case
|
|
|
|
SchemaDefinition directives' _ -> directives rule directives'
|
|
|
|
TypeDefinition typeDefinition' -> typeDefinition rule typeDefinition'
|
2020-09-24 05:47:31 +02:00
|
|
|
DirectiveDefinition _ _ arguments' _ -> argumentsDefinition rule arguments'
|
2020-09-17 10:33:37 +02:00
|
|
|
|
2020-09-28 07:06:15 +02:00
|
|
|
typeDefinition :: forall m. ApplyRule m TypeDefinition
|
2020-09-17 10:33:37 +02:00
|
|
|
typeDefinition rule = \case
|
|
|
|
ScalarTypeDefinition _ _ directives' -> directives rule directives'
|
|
|
|
ObjectTypeDefinition _ _ _ directives' fields ->
|
|
|
|
directives rule directives' >< foldMap (fieldDefinition rule) fields
|
|
|
|
InterfaceTypeDefinition _ _ directives' fields ->
|
|
|
|
directives rule directives' >< foldMap (fieldDefinition rule) fields
|
|
|
|
UnionTypeDefinition _ _ directives' _ -> directives rule directives'
|
|
|
|
EnumTypeDefinition _ _ directives' values ->
|
|
|
|
directives rule directives' >< foldMap (enumValueDefinition rule) values
|
|
|
|
InputObjectTypeDefinition _ _ directives' fields
|
|
|
|
-> directives rule directives'
|
|
|
|
<> foldMap (inputValueDefinition rule) fields
|
|
|
|
|
2020-09-28 07:06:15 +02:00
|
|
|
enumValueDefinition :: forall m. ApplyRule m EnumValueDefinition
|
2020-09-17 10:33:37 +02:00
|
|
|
enumValueDefinition rule (EnumValueDefinition _ _ directives') =
|
|
|
|
directives rule directives'
|
|
|
|
|
2020-09-28 07:06:15 +02:00
|
|
|
fieldDefinition :: forall m. ApplyRule m FieldDefinition
|
2020-09-24 05:47:31 +02:00
|
|
|
fieldDefinition rule (FieldDefinition _ _ arguments' _ directives') =
|
|
|
|
directives rule directives' >< argumentsDefinition rule arguments'
|
2020-09-17 10:33:37 +02:00
|
|
|
|
2020-09-28 07:06:15 +02:00
|
|
|
argumentsDefinition :: forall m. ApplyRule m ArgumentsDefinition
|
2020-09-17 10:33:37 +02:00
|
|
|
argumentsDefinition rule (ArgumentsDefinition definitions) =
|
|
|
|
foldMap (inputValueDefinition rule) definitions
|
|
|
|
|
2020-09-28 07:06:15 +02:00
|
|
|
inputValueDefinition :: forall m. ApplyRule m InputValueDefinition
|
2020-09-17 10:33:37 +02:00
|
|
|
inputValueDefinition rule (InputValueDefinition _ _ _ _ directives') =
|
|
|
|
directives rule directives'
|
|
|
|
|
2020-09-28 07:06:15 +02:00
|
|
|
operationDefinition :: forall m
|
|
|
|
. Validation.Rule m
|
2020-09-25 21:57:25 +02:00
|
|
|
-> Validation m
|
|
|
|
-> OperationDefinition
|
2020-09-28 07:06:15 +02:00
|
|
|
-> Seq (Validation.RuleT m)
|
2020-09-25 21:57:25 +02:00
|
|
|
operationDefinition rule context operation
|
2020-09-28 07:06:15 +02:00
|
|
|
| Validation.OperationDefinitionRule operationRule <- rule =
|
2020-09-19 18:18:26 +02:00
|
|
|
pure $ operationRule operation
|
2020-09-28 07:06:15 +02:00
|
|
|
| Validation.VariablesRule variablesRule <- rule
|
2020-09-24 05:47:31 +02:00
|
|
|
, OperationDefinition _ _ variables _ _ _ <- operation
|
|
|
|
= Seq.fromList (variableDefinition rule <$> variables)
|
|
|
|
|> variablesRule variables
|
2020-09-25 21:57:25 +02:00
|
|
|
| SelectionSet selections _ <- operation =
|
|
|
|
selectionSet types' rule (getRootType Query) selections
|
|
|
|
| OperationDefinition operationType _ _ directives' selections _ <- operation
|
|
|
|
= selectionSet types' rule (getRootType operationType) selections
|
|
|
|
>< directives rule directives'
|
|
|
|
where
|
2020-09-28 07:06:15 +02:00
|
|
|
types' = Validation.types context
|
|
|
|
getRootType Query =
|
|
|
|
Just $ Out.NamedObjectType $ Schema.query $ Validation.schema context
|
|
|
|
getRootType Mutation =
|
|
|
|
Out.NamedObjectType <$> Schema.mutation (Validation.schema context)
|
2020-09-25 21:57:25 +02:00
|
|
|
getRootType Subscription =
|
2020-09-28 07:06:15 +02:00
|
|
|
Out.NamedObjectType <$> Schema.subscription (Validation.schema context)
|
2020-09-25 21:57:25 +02:00
|
|
|
|
|
|
|
typeToOut :: forall m. Schema.Type m -> Maybe (Out.Type m)
|
|
|
|
typeToOut (Schema.ObjectType objectType) =
|
|
|
|
Just $ Out.NamedObjectType objectType
|
|
|
|
typeToOut (Schema.InterfaceType interfaceType) =
|
|
|
|
Just $ Out.NamedInterfaceType interfaceType
|
|
|
|
typeToOut (Schema.UnionType unionType) = Just $ Out.NamedUnionType unionType
|
|
|
|
typeToOut (Schema.EnumType enumType) = Just $ Out.NamedEnumType enumType
|
|
|
|
typeToOut (Schema.ScalarType scalarType) = Just $ Out.NamedScalarType scalarType
|
|
|
|
typeToOut _ = Nothing
|
2020-09-14 07:49:33 +02:00
|
|
|
|
2020-09-28 07:06:15 +02:00
|
|
|
variableDefinition :: forall m
|
|
|
|
. Validation.Rule m
|
|
|
|
-> VariableDefinition
|
|
|
|
-> Validation.RuleT m
|
|
|
|
variableDefinition (Validation.ValueRule _ rule) (VariableDefinition _ _ value _) =
|
2020-09-24 05:47:31 +02:00
|
|
|
maybe (lift mempty) rule value
|
|
|
|
variableDefinition _ _ = lift mempty
|
|
|
|
|
2020-09-25 21:57:25 +02:00
|
|
|
fragmentDefinition :: forall m
|
2020-09-28 07:06:15 +02:00
|
|
|
. Validation.Rule m
|
2020-09-25 21:57:25 +02:00
|
|
|
-> Validation m
|
|
|
|
-> FragmentDefinition
|
2020-09-28 07:06:15 +02:00
|
|
|
-> Seq (Validation.RuleT m)
|
|
|
|
fragmentDefinition (Validation.FragmentDefinitionRule rule) _ definition' =
|
2020-09-25 21:57:25 +02:00
|
|
|
pure $ rule definition'
|
|
|
|
fragmentDefinition rule context definition'
|
|
|
|
| FragmentDefinition _ typeCondition directives' selections _ <- definition'
|
2020-09-28 07:06:15 +02:00
|
|
|
, Validation.FragmentRule definitionRule _ <- rule
|
2020-09-25 21:57:25 +02:00
|
|
|
= applyToChildren typeCondition directives' selections
|
|
|
|
|> definitionRule definition'
|
|
|
|
| FragmentDefinition _ typeCondition directives' selections _ <- definition'
|
|
|
|
= applyToChildren typeCondition directives' selections
|
2020-09-07 22:01:49 +02:00
|
|
|
where
|
2020-09-28 07:06:15 +02:00
|
|
|
types' = Validation.types context
|
2020-09-25 21:57:25 +02:00
|
|
|
applyToChildren typeCondition directives' selections
|
|
|
|
= selectionSet types' rule (lookupType' typeCondition) selections
|
2020-09-17 10:33:37 +02:00
|
|
|
>< directives rule directives'
|
2020-09-25 21:57:25 +02:00
|
|
|
lookupType' = flip lookupType types'
|
2020-09-07 22:01:49 +02:00
|
|
|
|
2020-09-25 21:57:25 +02:00
|
|
|
lookupType :: forall m
|
|
|
|
. TypeCondition
|
|
|
|
-> HashMap Name (Schema.Type m)
|
|
|
|
-> Maybe (Out.Type m)
|
|
|
|
lookupType typeCondition types' = HashMap.lookup typeCondition types'
|
|
|
|
>>= typeToOut
|
2020-08-31 11:06:27 +02:00
|
|
|
|
2020-09-28 07:06:15 +02:00
|
|
|
selectionSet :: Traversable t => forall m. ApplySelectionRule m (t Selection)
|
2020-09-25 21:57:25 +02:00
|
|
|
selectionSet types' rule = foldMap . selection types' rule
|
|
|
|
|
2020-09-28 07:06:15 +02:00
|
|
|
selection :: forall m. ApplySelectionRule m Selection
|
2020-09-25 21:57:25 +02:00
|
|
|
selection types' rule objectType selection'
|
2020-09-28 07:06:15 +02:00
|
|
|
| Validation.SelectionRule selectionRule <- rule =
|
2020-09-25 21:57:25 +02:00
|
|
|
applyToChildren |> selectionRule objectType selection'
|
2020-09-14 07:49:33 +02:00
|
|
|
| otherwise = applyToChildren
|
2020-08-28 08:32:21 +02:00
|
|
|
where
|
2020-09-14 07:49:33 +02:00
|
|
|
applyToChildren =
|
|
|
|
case selection' of
|
2020-09-25 21:57:25 +02:00
|
|
|
FieldSelection field' -> field types' rule objectType field'
|
2020-09-14 07:49:33 +02:00
|
|
|
InlineFragmentSelection inlineFragment' ->
|
2020-09-25 21:57:25 +02:00
|
|
|
inlineFragment types' rule objectType inlineFragment'
|
2020-09-14 07:49:33 +02:00
|
|
|
FragmentSpreadSelection fragmentSpread' ->
|
2020-09-17 10:33:37 +02:00
|
|
|
fragmentSpread rule fragmentSpread'
|
2020-09-14 07:49:33 +02:00
|
|
|
|
2020-09-28 07:06:15 +02:00
|
|
|
field :: forall m. ApplySelectionRule m Field
|
2020-09-25 21:57:25 +02:00
|
|
|
field types' rule objectType field' = go field'
|
2020-09-17 10:33:37 +02:00
|
|
|
where
|
2020-09-28 07:06:15 +02:00
|
|
|
go (Field _ fieldName _ _ _ _)
|
|
|
|
| Validation.FieldRule fieldRule <- rule =
|
|
|
|
applyToChildren fieldName |> fieldRule objectType field'
|
|
|
|
| Validation.ArgumentsRule argumentsRule _ <- rule =
|
|
|
|
applyToChildren fieldName |> argumentsRule objectType field'
|
|
|
|
| otherwise = applyToChildren fieldName
|
|
|
|
typeFieldType (Out.Field _ type' _) = type'
|
|
|
|
applyToChildren fieldName =
|
|
|
|
let Field _ _ arguments' directives' selections _ = field'
|
|
|
|
fieldType = objectType
|
|
|
|
>>= fmap typeFieldType . lookupTypeField fieldName
|
|
|
|
in selectionSet types' rule fieldType selections
|
2020-09-25 21:57:25 +02:00
|
|
|
>< directives rule directives'
|
|
|
|
>< arguments rule arguments'
|
2020-09-24 05:47:31 +02:00
|
|
|
|
2020-09-28 07:06:15 +02:00
|
|
|
arguments :: forall m. ApplyRule m [Argument]
|
2020-09-24 05:47:31 +02:00
|
|
|
arguments = (.) Seq.fromList . fmap . argument
|
|
|
|
|
2020-09-28 07:06:15 +02:00
|
|
|
argument :: forall m. Validation.Rule m -> Argument -> Validation.RuleT m
|
|
|
|
argument (Validation.ValueRule rule _) (Argument _ (Node value _) _) =
|
|
|
|
rule value
|
2020-09-24 05:47:31 +02:00
|
|
|
argument _ _ = lift mempty
|
2020-09-14 07:49:33 +02:00
|
|
|
|
2020-09-28 07:06:15 +02:00
|
|
|
inlineFragment :: forall m. ApplySelectionRule m InlineFragment
|
2020-09-25 21:57:25 +02:00
|
|
|
inlineFragment types' rule objectType inlineFragment' = go inlineFragment'
|
2020-09-17 10:33:37 +02:00
|
|
|
where
|
2020-09-25 21:57:25 +02:00
|
|
|
go (InlineFragment optionalType directives' selections _)
|
2020-09-28 07:06:15 +02:00
|
|
|
| Validation.FragmentRule _ fragmentRule <- rule
|
2020-09-25 21:57:25 +02:00
|
|
|
= applyToChildren (refineTarget optionalType) directives' selections
|
|
|
|
|> fragmentRule inlineFragment'
|
|
|
|
| otherwise = applyToChildren (refineTarget optionalType) directives' selections
|
|
|
|
refineTarget (Just typeCondition) = lookupType typeCondition types'
|
|
|
|
refineTarget Nothing = objectType
|
|
|
|
applyToChildren objectType' directives' selections
|
|
|
|
= selectionSet types' rule objectType' selections
|
2020-09-17 10:33:37 +02:00
|
|
|
>< directives rule directives'
|
|
|
|
|
2020-09-28 07:06:15 +02:00
|
|
|
fragmentSpread :: forall m. ApplyRule m FragmentSpread
|
2020-09-17 10:33:37 +02:00
|
|
|
fragmentSpread rule fragmentSpread'@(FragmentSpread _ directives' _)
|
2020-09-28 07:06:15 +02:00
|
|
|
| Validation.FragmentSpreadRule fragmentRule <- rule =
|
2020-09-17 10:33:37 +02:00
|
|
|
applyToChildren |> fragmentRule fragmentSpread'
|
|
|
|
| otherwise = applyToChildren
|
|
|
|
where
|
|
|
|
applyToChildren = directives rule directives'
|
|
|
|
|
2020-09-28 07:06:15 +02:00
|
|
|
directives :: Traversable t => forall m. ApplyRule m (t Directive)
|
2020-09-18 07:32:58 +02:00
|
|
|
directives rule directives'
|
2020-09-28 07:06:15 +02:00
|
|
|
| Validation.DirectivesRule directivesRule <- rule =
|
2020-09-18 07:32:58 +02:00
|
|
|
applyToChildren |> directivesRule directiveList
|
|
|
|
| otherwise = applyToChildren
|
|
|
|
where
|
|
|
|
directiveList = toList directives'
|
2020-09-24 05:47:31 +02:00
|
|
|
applyToChildren = foldMap (directive rule) directiveList
|
2020-09-14 07:49:33 +02:00
|
|
|
|
2020-09-28 07:06:15 +02:00
|
|
|
directive :: forall m. ApplyRule m Directive
|
|
|
|
directive (Validation.ArgumentsRule _ argumentsRule) directive' =
|
2020-09-24 05:47:31 +02:00
|
|
|
pure $ argumentsRule directive'
|
|
|
|
directive rule (Directive _ arguments' _) = arguments rule arguments'
|