summaryrefslogtreecommitdiff
path: root/src/Language/GraphQL/Resolver.hs
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2022-08-24 22:33:20 +0300
committerEugen Wissner <belka@caraus.de>2022-10-01 18:11:51 +0200
commit92463f7c4a9be2581aa5f6913762a8de393c4924 (patch)
tree8a0d994a7705224221bb46f8641d8caa186b79c1 /src/Language/GraphQL/Resolver.hs
parent53ce65d7137a983df43056a3ea33d31054afd5fc (diff)
downloadgraphql-spice-92463f7c4a9be2581aa5f6913762a8de393c4924.tar.gz
Add Resolver module with helpers and exceptions
Diffstat (limited to 'src/Language/GraphQL/Resolver.hs')
-rw-r--r--src/Language/GraphQL/Resolver.hs61
1 files changed, 61 insertions, 0 deletions
diff --git a/src/Language/GraphQL/Resolver.hs b/src/Language/GraphQL/Resolver.hs
new file mode 100644
index 0000000..dbf9a6a
--- /dev/null
+++ b/src/Language/GraphQL/Resolver.hs
@@ -0,0 +1,61 @@
+{- 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/. -}
+
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | Helper functions and exceptions to write resolvers.
+module Language.GraphQL.Resolver
+ ( argument
+ , defaultResolver
+ ) where
+
+import Control.Monad.Catch (Exception(..), MonadCatch(..), MonadThrow(..))
+import Control.Monad.Trans.Reader (ReaderT, asks)
+import Data.HashMap.Strict ((!))
+import Data.Text (Text)
+import qualified Data.Text as Text
+import Data.Typeable (cast)
+import Language.GraphQL.AST.Document (Name)
+import Language.GraphQL.Error
+import qualified Language.GraphQL.Type as Type
+import Language.GraphQL.Class (FromGraphQL(..))
+
+-- | Exceptions thrown by the functions in this module.
+data ServerException
+ = FieldNotResolvedException !Text
+ | ErroneousArgumentTypeException !Text
+
+instance Show ServerException where
+ show (FieldNotResolvedException fieldName) =
+ Text.unpack $ Text.unwords ["Field", fieldName, "not resolved."]
+ show (ErroneousArgumentTypeException argumentName) =
+ Text.unpack $ Text.unwords
+ [ "Unable to convert the argument"
+ , argumentName
+ , "to a user-defined type."
+ ]
+
+instance Exception ServerException where
+ toException = toException . ResolverException
+ fromException x = do
+ ResolverException a <- fromException x
+ cast a
+
+-- | Default resolver expects that the field value is returned by the parent
+-- object. If the parent is not an object or it doesn't contain the requested
+-- field name, an error is thrown.
+defaultResolver :: MonadCatch m => Name -> Type.Resolve m
+defaultResolver fieldName = do
+ values' <- asks Type.values
+ case values' of
+ Type.Object objectValue -> pure $ objectValue ! fieldName
+ _nonObject -> throwM $ FieldNotResolvedException fieldName
+
+-- | Takes an argument name, validates that the argument exists, and optionally
+-- converts it to a user-defined type.
+argument :: (MonadCatch m, FromGraphQL a) => Name -> ReaderT Type.Context m a
+argument argumentName =
+ Type.argument argumentName >>= maybe throwError pure . fromGraphQL
+ where
+ throwError = throwM $ ErroneousArgumentTypeException argumentName