{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes #-}
{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}
{-# OPTIONS_GHC -Wno-type-defaults #-}
module Shpadoinkle.Router.Client
( runXHR
, runXHR'
, runXHRe
, getClientEnv
, module Servant.Client.JS
) where
import Control.Monad.Catch (MonadThrow (throwM))
import Data.Maybe (fromMaybe)
import Data.Text (Text)
import GHCJS.DOM.Types (JSM)
import Language.Javascript.JSaddle (FromJSVal (fromJSVal), jsg, (!))
import Servant.Client.JS (BaseUrl (..), ClientEnv (..),
ClientError (..), ClientM (..),
EmptyClient (..), HasClient (..),
InvalidBaseUrlException, Response,
ResponseF (..), Scheme (..),
StreamingResponse, client,
parseBaseUrl, runClientM,
showBaseUrl,
withStreamingRequestJSM)
import Text.Read (readMaybe)
import UnliftIO (MonadIO (liftIO))
default (Text)
getClientEnv :: JSM ClientEnv
getClientEnv = do
loc <- jsg ("window" :: Text) >>= (! ("location" :: Text))
protocol <- mapProtocol <$> (loc ! ("protocol" :: Text) >>= fromJSVal)
hostname <- fromMaybe "localhost" <$> (loc ! ("hostname" :: Text) >>= fromJSVal)
port <- fromMaybe (defaultPort protocol) . (readMaybe =<<) <$> (loc ! ("port" :: Text) >>= fromJSVal)
return $ ClientEnv $ BaseUrl protocol hostname port ""
where mapProtocol :: Maybe String -> Scheme
mapProtocol (Just "https:") = Https
mapProtocol _ = Http
defaultPort :: Scheme -> Int
defaultPort Https = 443
defaultPort Http = 80
runXHR :: ClientM a -> JSM a
runXHR m = runXHR' m =<< getClientEnv
runXHR' :: ClientM a -> ClientEnv -> JSM a
runXHR' m env = either (liftIO . throwM) pure =<< runClientM m env
runXHRe :: ClientM a -> ClientEnv -> JSM (Either ClientError a)
runXHRe = runClientM