2016-03-12 00:59:51 +01:00
|
|
|
{-# LANGUAGE CPP #-}
|
|
|
|
{-# LANGUAGE OverloadedStrings #-}
|
|
|
|
module Data.GraphQL.Error (
|
|
|
|
parseError,
|
|
|
|
CollectErrsT,
|
|
|
|
addErr,
|
|
|
|
addErrMsg,
|
|
|
|
runCollectErrs,
|
|
|
|
joinErrs,
|
|
|
|
errWrap
|
|
|
|
) where
|
|
|
|
|
|
|
|
import qualified Data.Aeson as Aeson
|
|
|
|
import Data.Text (Text, pack)
|
|
|
|
|
|
|
|
import Control.Arrow ((&&&))
|
|
|
|
|
|
|
|
#if !MIN_VERSION_base(4,8,0)
|
|
|
|
import Control.Applicative (Applicative, pure)
|
|
|
|
import Data.Foldable (Foldable, concatMap)
|
|
|
|
import Prelude hiding (concatMap)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
-- | Wraps a parse error into a list of errors.
|
|
|
|
parseError :: Applicative f => String -> f Aeson.Value
|
|
|
|
parseError s =
|
|
|
|
pure $ Aeson.object [("errors", Aeson.toJSON [makeErrorMsg $ pack s])]
|
|
|
|
|
2016-03-15 14:02:34 +01:00
|
|
|
-- | A wrapper for an 'Applicative' to pass error messages around.
|
2016-03-12 00:59:51 +01:00
|
|
|
type CollectErrsT f a = f (a,[Aeson.Value])
|
|
|
|
|
2016-03-15 14:02:34 +01:00
|
|
|
-- | Takes a (wrapped) list (foldable functor) of values and errors,
|
2016-03-12 00:59:51 +01:00
|
|
|
-- joins the values into a list and concatenates the errors.
|
|
|
|
joinErrs
|
|
|
|
:: (Functor m, Functor f, Foldable f)
|
|
|
|
=> m (f (a,[Aeson.Value])) -> CollectErrsT m (f a)
|
|
|
|
joinErrs = fmap $ fmap fst &&& concatMap snd
|
|
|
|
|
2016-03-15 14:02:34 +01:00
|
|
|
-- | Wraps the given 'Applicative' to handle errors
|
2016-03-12 00:59:51 +01:00
|
|
|
errWrap :: Functor f => f a -> f (a, [Aeson.Value])
|
|
|
|
errWrap = fmap (flip (,) [])
|
|
|
|
|
|
|
|
-- | Adds an error to the list of errors.
|
|
|
|
addErr :: Functor f => Aeson.Value -> CollectErrsT f a -> CollectErrsT f a
|
|
|
|
addErr v = (fmap . fmap) (v :)
|
|
|
|
|
|
|
|
makeErrorMsg :: Text -> Aeson.Value
|
|
|
|
makeErrorMsg s = Aeson.object [("message",Aeson.toJSON s)]
|
|
|
|
|
|
|
|
-- | Convenience function for just wrapping an error message.
|
|
|
|
addErrMsg :: Functor f => Text -> CollectErrsT f a -> CollectErrsT f a
|
|
|
|
addErrMsg = addErr . makeErrorMsg
|
|
|
|
|
2016-03-15 14:02:34 +01:00
|
|
|
-- | Runs the given query, but collects the errors into an error
|
|
|
|
-- list which is then sent back with the data.
|
2016-03-12 00:59:51 +01:00
|
|
|
runCollectErrs :: Functor f => CollectErrsT f Aeson.Value -> f Aeson.Value
|
|
|
|
runCollectErrs = fmap finalD
|
2016-03-15 14:02:34 +01:00
|
|
|
where
|
|
|
|
finalD (dat,errs) =
|
|
|
|
Aeson.object
|
|
|
|
$ if null errs
|
|
|
|
then [("data",dat)]
|
|
|
|
else [("data",dat),("errors",Aeson.toJSON $ reverse errs)]
|