{-# LANGUAGE CPP #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RankNTypes #-} {-# OPTIONS_GHC -fno-warn-redundant-constraints #-} {-# OPTIONS_GHC -Wno-type-defaults #-} -- | Helper for querying the server from client side code using a derived client. -- This module exists to save you from having to use CPP yourself. module Shpadoinkle.Router.Client ( runXHR , runXHR' , runXHRe , 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) -- | Run the ClientM from Servant as an XHR request. runXHR :: ClientM a -> JSM a runXHR m = do -- TODO cache the base url or make it optional 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) runXHR' m . 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 -- | Run the ClientM from Servant as an XHR request with a customized base URL. 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