diff options
| author | Eugen Wissner <belka@caraus.de> | 2020-10-03 07:34:34 +0200 |
|---|---|---|
| committer | Eugen Wissner <belka@caraus.de> | 2020-10-03 07:34:34 +0200 |
| commit | d5f518fe827d3d279d6c37740820f296689539e4 (patch) | |
| tree | f3b6fa3a397d0e9357fe77bb01373902890b1014 /src/Language/GraphQL/Validate | |
| parent | 6daae8a5219f62de98b4a65788e436fb1eac8cba (diff) | |
| download | graphql-d5f518fe827d3d279d6c37740820f296689539e4.tar.gz | |
Validate required arguments
Diffstat (limited to 'src/Language/GraphQL/Validate')
| -rw-r--r-- | src/Language/GraphQL/Validate/Rules.hs | 65 |
1 files changed, 64 insertions, 1 deletions
diff --git a/src/Language/GraphQL/Validate/Rules.hs b/src/Language/GraphQL/Validate/Rules.hs index 6c35f70..a5754c6 100644 --- a/src/Language/GraphQL/Validate/Rules.hs +++ b/src/Language/GraphQL/Validate/Rules.hs @@ -24,6 +24,7 @@ module Language.GraphQL.Validate.Rules , noUndefinedVariablesRule , noUnusedFragmentsRule , noUnusedVariablesRule + , providedRequiredArgumentsRule , scalarLeafsRule , singleFieldSubscriptionsRule , specifiedRules @@ -47,7 +48,7 @@ import Data.HashMap.Strict (HashMap) import Data.HashSet (HashSet) import qualified Data.HashSet as HashSet import Data.List (groupBy, sortBy, sortOn) -import Data.Maybe (mapMaybe) +import Data.Maybe (isNothing, mapMaybe) import Data.Ord (comparing) import Data.Sequence (Seq(..), (|>)) import qualified Data.Sequence as Seq @@ -79,6 +80,7 @@ specifiedRules = -- Arguments. , knownArgumentNamesRule , uniqueArgumentNamesRule + , providedRequiredArgumentsRule -- Fragments. , uniqueFragmentNamesRule , fragmentSpreadTypeExistenceRule @@ -893,3 +895,64 @@ directivesInValidLocationsRule = DirectivesRule directivesRule , show directiveLocation , "." ] + +-- | Arguments can be required. An argument is required if the argument type is +-- non‐null and does not have a default value. Otherwise, the argument is +-- optional. +providedRequiredArgumentsRule :: Rule m +providedRequiredArgumentsRule = ArgumentsRule fieldRule directiveRule + where + fieldRule (Just objectType) (Field _ fieldName arguments _ _ location') + | Just typeField <- lookupTypeField fieldName objectType + , Out.Field _ _ definitions <- typeField = + let forEach = go (fieldMessage fieldName) arguments location' + in lift $ HashMap.foldrWithKey forEach Seq.empty definitions + fieldRule _ _ = lift mempty + directiveRule (Directive directiveName arguments location') = do + available <- asks $ HashMap.lookup directiveName . directives + case available of + Just (Schema.Directive _ _ definitions) -> + let forEach = go (directiveMessage directiveName) arguments location' + in lift $ HashMap.foldrWithKey forEach Seq.empty definitions + _ -> lift mempty + inputTypeName (In.ScalarBaseType (Definition.ScalarType typeName _)) = + typeName + inputTypeName (In.EnumBaseType (Definition.EnumType typeName _ _)) = + typeName + inputTypeName (In.InputObjectBaseType (In.InputObjectType typeName _ _)) = + typeName + inputTypeName (In.ListBaseType listType) = inputTypeName listType + go makeMessage arguments location' argumentName argumentType errors + | In.Argument _ type' optionalValue <- argumentType + , In.isNonNullType type' + , typeName <- inputTypeName type' + , isNothing optionalValue + , isNothingOrNull $ find (lookupArgument argumentName) arguments + = errors + |> makeError (makeMessage argumentName typeName) location' + | otherwise = errors + makeError errorMessage location' = Error + { message = errorMessage + , locations = [location'] + } + isNothingOrNull (Just (Argument _ (Node Null _) _)) = True + isNothingOrNull x = isNothing x + lookupArgument needle (Argument argumentName _ _) = needle == argumentName + fieldMessage fieldName argumentName typeName = concat + [ "Field \"" + , Text.unpack fieldName + , "\" argument \"" + , Text.unpack argumentName + , "\" of type \"" + , Text.unpack typeName + , "\" is required, but it was not provided." + ] + directiveMessage directiveName argumentName typeName = concat + [ "Directive \"@" + , Text.unpack directiveName + , "\" argument \"" + , Text.unpack argumentName + , "\" of type \"" + , Text.unpack typeName + , "\" is required, but it was not provided." + ] |
