{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE LambdaCase #-}
module SimFin.Common
( ApiError(..)
, ApiResult
, fetchCompanyList
, performRequest
) where
import Control.Monad.Catch
import Control.Monad.IO.Class
import Data.Aeson
import Data.ByteString (ByteString)
import qualified Data.ByteString.Lazy as LBS
import Data.Text (Text)
import qualified Data.Text as T
import SimFin.Internal
import SimFin.Types.CompanyListing
data ApiError
= DecodeError LBS.ByteString String
| ParseError Value String
| Other Text
instance Show ApiError where
show :: ApiError -> String
show (DecodeError ByteString
_ String
err) = String
"Couldn't decode reponse body. Err: " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
err
show (ParseError Value
_ String
err) = String
"Couldn't parse JSON value. Err: " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
err
show (Other Text
err) = String
"Server returned error: " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Text -> String
T.unpack Text
err
type ApiResult = Either ApiError
instance FromJSON ApiError where
parseJSON :: Value -> Parser ApiError
parseJSON = String -> (Object -> Parser ApiError) -> Value -> Parser ApiError
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"Root" ((Object -> Parser ApiError) -> Value -> Parser ApiError)
-> (Object -> Parser ApiError) -> Value -> Parser ApiError
forall a b. (a -> b) -> a -> b
$ \Object
v -> Text -> ApiError
Other (Text -> ApiError) -> Parser Text -> Parser ApiError
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
v Object -> Text -> Parser Text
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"error"
performRequest
:: ( MonadIO m
, FromJSON a
)
=> SimFinContext
-> ByteString
-> [QueryParam]
-> m (ApiResult a)
performRequest :: SimFinContext -> ByteString -> [QueryParam] -> m (ApiResult a)
performRequest = (ByteString -> String -> ApiError)
-> (Value -> String -> ApiError)
-> SimFinContext
-> ByteString
-> [QueryParam]
-> m (ApiResult a)
forall (m :: * -> *) a e.
(MonadIO m, FromJSON a, FromJSON e) =>
(ByteString -> String -> e)
-> (Value -> String -> e)
-> SimFinContext
-> ByteString
-> [QueryParam]
-> m (Either e a)
performGenericRequest ByteString -> String -> ApiError
DecodeError Value -> String -> ApiError
ParseError
fetchCompanyList
:: (MonadThrow m, MonadIO m)
=> SimFinContext
-> m (Either ApiError [CompanyListingRow])
fetchCompanyList :: SimFinContext -> m (Either ApiError [CompanyListingRow])
fetchCompanyList SimFinContext
ctx =
(CompanyListingKeyed -> [CompanyListingRow])
-> Either ApiError CompanyListingKeyed
-> Either ApiError [CompanyListingRow]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap CompanyListingKeyed -> [CompanyListingRow]
unKeyCompanyListing (Either ApiError CompanyListingKeyed
-> Either ApiError [CompanyListingRow])
-> m (Either ApiError CompanyListingKeyed)
-> m (Either ApiError [CompanyListingRow])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> SimFinContext
-> ByteString
-> [QueryParam]
-> m (Either ApiError CompanyListingKeyed)
forall (m :: * -> *) a.
(MonadIO m, FromJSON a) =>
SimFinContext -> ByteString -> [QueryParam] -> m (ApiResult a)
performRequest SimFinContext
ctx ByteString
"companies/list" []