{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE NoImplicitPrelude #-}
module Data.Morpheus.App.MapAPI
( MapAPI (..),
)
where
import Control.Monad.Except (MonadError (throwError))
import Data.Aeson
( encode,
)
import Data.Aeson.Parser
( eitherDecodeWith,
jsonNoDup,
)
#if MIN_VERSION_aeson(2,1,0)
import Data.Aeson.Types ( formatError,ifromJSON,)
#else
import Data.Aeson.Internal ( formatError,ifromJSON,)
#endif
import Data.ByteString.Lazy.Char8 (pack)
import qualified Data.ByteString.Lazy.Char8 as LB
( ByteString,
fromStrict,
toStrict,
)
import Data.Morpheus.Types.IO
( GQLRequest (..),
GQLResponse (..),
)
import qualified Data.Text.Lazy as LT
( Text,
fromStrict,
toStrict,
)
import Data.Text.Lazy.Encoding
( decodeUtf8,
encodeUtf8,
)
import Relude hiding
( decodeUtf8,
encodeUtf8,
)
decodeNoDup :: (MonadError LB.ByteString m) => LB.ByteString -> m GQLRequest
decodeNoDup str = case eitherDecodeWith jsonNoDup ifromJSON str of
Left (path, x) -> throwError $ pack $ "Bad Request. Could not decode Request body: " <> formatError path x
Right value -> pure value
class MapAPI a b where
mapAPI :: (Applicative m) => (GQLRequest -> m GQLResponse) -> a -> m b
instance MapAPI GQLRequest GQLResponse where
mapAPI f = f
instance MapAPI LB.ByteString LB.ByteString where
mapAPI api = either pure (fmap encode . api) . decodeNoDup
instance MapAPI LT.Text LT.Text where
mapAPI api = fmap decodeUtf8 . mapAPI api . encodeUtf8
instance MapAPI ByteString ByteString where
mapAPI api = fmap LB.toStrict . mapAPI api . LB.fromStrict
instance MapAPI Text Text where
mapAPI api = fmap LT.toStrict . mapAPI api . LT.fromStrict