@@ -1,8 +1,16 @@
1+{-# LANGUAGE AllowAmbiguousTypes #-}
12{-# LANGUAGE CPP #-}
23{-# LANGUAGE DataKinds #-}
34{-# LANGUAGE FlexibleContexts #-}
45{-# LANGUAGE FlexibleInstances #-}
56{-# LANGUAGE InstanceSigs #-}
7+{-# LANGUAGE OverloadedStrings #-}
8+{-# LANGUAGE PolyKinds #-}
9+{-# LANGUAGE ScopedTypeVariables #-}
10+{-# LANGUAGE TupleSections #-}
11+{-# LANGUAGE TypeFamilies #-}
12+{-# LANGUAGE TypeOperators #-}
13+{-# LANGUAGE UndecidableInstances #-}
614{-# LANGUAGE MultiParamTypeClasses #-}
715{-# LANGUAGE OverloadedStrings #-}
816{-# LANGUAGE PolyKinds #-}
@@ -18,47 +26,59 @@
1826-- API.
1927module Servant.Reflex
2028 ( client
29+ , BuildHeaderKeysTo(..)
30+ , toHeaders
2131 , HasClient(..)
2232 , module Servant.Common.Req
2333 , module Servant.Common.BaseUrl
2434 ) where
2535
26−-------------------------------------------------------------------------------
36+------------------------------------------------------------------------------
2737import Control.Applicative
28−import Data.CaseInsensitive (mk)
29−import qualified Data.Map as Map
30−import Data.Monoid ((<>))
31−import Data.Proxy (Proxy (..))
32−import qualified Data.Set as Set
33−import Data.Text (Text)
34−import qualified Data.Text as T
35−import qualified Data.Text.Encoding as E
36−import GHC.TypeLits (KnownSymbol, symbolVal)
37−import Reflex.Dom (Dynamic, Event, Reflex,
38− XhrRequest (..), XhrResponse (..),
39− XhrResponseHeaders (..), ffor,
40− fmapMaybe, leftmost,
41− performRequestAsync, tagPromptlyDyn)
42−import Servant.API ((:<|>) (..), (:>), BasicAuth,
43− BasicAuthData, BuildHeadersTo (..),
44− Capture, Header, Headers (..),
45− HttpVersion, IsSecure, MimeRender (..),
46− MimeUnrender, NoContent, QueryFlag,
47− QueryParam, QueryParams, Raw,
48− ReflectMethod (..), RemoteHost,
49− ReqBody, ToHttpApiData (..), Vault,
50− Verb, contentType)
51−import Servant.Common.BaseUrl (BaseUrl (..), Scheme (..),
52− SupportsServantReflex, baseUrlWidget,
53− showBaseUrl)
54−import Servant.Common.Req (QParam (..), QueryPart (..), Req,
55− ReqResult (..), addHeader, authData,
56− defReq, performRequestCT,
57− performRequestNoBody,
58− prependToPathParts, qParamToQueryPart,
59− qParams, reqBody, reqFailure,
60− reqMethod, reqSuccess, respHeaders,
61− response)
38+import Data.Monoid ((<>))
39+import qualified Data.Set as Set
40+import qualified Data.Text.Encoding as E
41+import Data.CaseInsensitive (mk)
42+import Data.Functor.Identity
43+import Data.Proxy (Proxy (..))
44+import qualified Data.Map as Map
45+import Data.Text (Text)
46+import qualified Data.Text as T
47+import GHC.TypeLits (KnownSymbol, symbolVal)
48+import Servant.API ((:<|>)(..),(:>), BasicAuth,
49+ BasicAuthData, BuildHeadersTo(..),
50+ Capture, contentType, Header,
51+ Headers(..), HttpVersion, IsSecure,
52+ MimeRender(..), MimeUnrender,
53+ NoContent, QueryFlag, QueryParam,
54+ QueryParams, Raw, ReflectMethod(..),
55+ RemoteHost, ReqBody,
56+ ToHttpApiData(..), Vault, Verb)
57+
58+import Reflex.Dom (Dynamic, Event, Reflex,
59+ XhrRequest(..),
60+ XhrResponseHeaders(..),
61+ XhrResponse(..), attachPromptlyDynWith, constDyn, ffor, fmapMaybe,
62+ leftmost, performRequestsAsync,
63+ )
64+------------------------------------------------------------------------------
65+import Servant.Common.BaseUrl (BaseUrl(..), Scheme(..), baseUrlWidget,
66+ showBaseUrl,
67+ SupportsServantReflex)
68+import Servant.Common.Req (Req, ReqResult(..), QParam(..),
69+ QueryPart(..), addHeader, authData,
70+ defReq, evalResponse, prependToPathParts,
71+ -- performRequestCT,
72+ performRequestsCT,
73+ -- performRequestNoBody,
74+ performRequestsNoBody,
75+ performSomeRequestsAsync,
76+ qParamToQueryPart, reqBody,
77+ reqSuccess, reqFailure,
78+ reqMethod, respHeaders, response,
79+ reqTag,
80+ qParams)
81+
6282
6383-- * Accessing APIs as a Client
6484
@@ -70,28 +90,31 @@ import Servant.Common.Req (QParam (..), QueryPart (..), Req,
7090-- > myApi :: Proxy MyApi
7191-- > myApi = Proxy
7292-- >
73−-- > getAllBooks :: Event t () -> m (Event t (Either XhrError ((),[Book])))
74−-- > postNewBook :: Dynamic t (Maybe Book) -> Event t ()
75−-- -> m (Event t (Either XhrError (Book,Book)))
93+-- > getAllBooks :: Event t l -> m (Event t (l, ReqResult [Book]))
94+-- > postNewBook :: Dynamic t (Maybe Book) -> Event t l
95+-- -> m (Event t (l, ReqResult Book)))
7696-- > (getAllBooks :<|> postNewBook) = client myApi host
7797-- > where host = constDyn $ BaseUrl Http "localhost" 8080
78−client :: (HasClient t m layout)
79− => Proxy layout -> Proxy m -> Dynamic t BaseUrl -> Client t m layout
80−client p q = clientWithRoute p q defReq
98+client :: (HasClient t m layout tag)
99+ => Proxy layout -> Proxy m -> Proxy tag -> Dynamic t BaseUrl -> Client t m layout tag
100+client p q t baseurl = clientWithRoute p q t defReq baseurl
101+
81102
82103-- | This class lets us define how each API combinator
83104-- influences the creation of an HTTP request. It's mostly
84105-- an internal class, you can just use 'client'.
85−class HasClient t m layout where
86− type Client t m layout :: *
87− clientWithRoute :: Proxy layout -> Proxy m -> Req t -> Dynamic t BaseUrl -> Client t m layout
106+class HasClient t m layout (tag :: *) where
107+ type Client t m layout tag :: *
108+ clientWithRoute :: Proxy layout -> Proxy m -> Proxy tag -> Req t -> Dynamic t BaseUrl -> Client t m layout tag
88109
89110
90−instance (HasClient t m a, HasClient t m b) => HasClient t m (a :<|> b) where
91− type Client t m (a :<|> b) = Client t m a :<|> Client t m b
92− clientWithRoute Proxy q req baseurl =
93− clientWithRoute (Proxy :: Proxy a) q req baseurl :<|>
94− clientWithRoute (Proxy :: Proxy b) q req baseurl
111+instance (HasClient t m a tag, HasClient t m b tag) => HasClient t m (a :<|> b) tag where
112+ type Client t m (a :<|> b) tag = Client t m a tag :<|> Client t m b tag
113+
114+ clientWithRoute Proxy q pTag req baseurl =
115+ clientWithRoute (Proxy :: Proxy a) q pTag req baseurl :<|>
116+ clientWithRoute (Proxy :: Proxy b) q pTag req baseurl
117+
95118
96119-- Capture. Example:
97120-- > type MyApi = "books" :> Capture "isbn" Text :> Get '[JSON] Book
@@ -101,50 +124,54 @@ instance (HasClient t m a, HasClient t m b) => HasClient t m (a :<|> b) where
101124-- > getBook :: SupportsServantReflex t m
102125-- => Dynamic t BaseUrl
103126-- -> Dynamic t (Maybe Text)
104−-- -> Event t ()
105−-- -> m (Event t (Either XhrError (Text, Book)))
127+-- -> Event t l
128+-- -> m (Event t (l, ReqResult Book))
106129-- > getBook = client myApi (constDyn host)
107−instance (SupportsServantReflex t m, ToHttpApiData a, HasClient t m sublayout)
108− => HasClient t m (Capture capture a :> sublayout) where
109130
110− type Client t m (Capture capture a :> sublayout) =
111− Dynamic t (Either Text a) -> Client t m sublayout
131+instance (SupportsServantReflex t m, ToHttpApiData a, HasClient t m sublayout tag)
132+ => HasClient t m (Capture capture a :> sublayout) tag where
112133
113− clientWithRoute Proxy q req baseurl val =
134+ type Client t m (Capture capture a :> sublayout) tag =
135+ Dynamic t (Either Text a) -> Client t m sublayout tag
136+
137+ clientWithRoute Proxy q t req baseurl val =
114138 clientWithRoute (Proxy :: Proxy sublayout)
115− q
139+ q t
116140 (prependToPathParts p req)
117141 baseurl
142+ where p = (fmap . fmap) (toUrlPiece) val
118143
119− where p = (fmap . fmap) toUrlPiece val
120144
121145-- VERB (Returning content) --
122146instance {-# OVERLAPPABLE #-}
123147 -- Note [Non-Empty Content Types]
124148 (MimeUnrender ct a, ReflectMethod method, cts' ~ (ct ': cts), SupportsServantReflex t m
125− ) => HasClient t m (Verb method status cts' a) where
126− type Client t m (Verb method status cts' a) =
127− Event t () -> m (Event t (ReqResult a))
149+ ) => HasClient t m (Verb method status cts' a) tag where
150+ type Client t m (Verb method status cts' a) tag =
151+ Event t tag -> m (Event t (ReqResult tag a))
128152 -- TODO how to access input types here?
129153 -- ExceptT ServantError IO a
130− clientWithRoute Proxy _ req =
131− performRequestCT (Proxy :: Proxy ct) method req'
154+ clientWithRoute Proxy _ _ req baseurl trigs =
155+ -- performRequestCT (Proxy :: Proxy ct) method req' baseurl trigs
156+ fmap runIdentity <$> performRequestsCT (Proxy :: Proxy ct) method (constDyn $ Identity $ req') baseurl trigs
132157 where method = E.decodeUtf8 $ reflectMethod (Proxy :: Proxy method)
133158 req' = req { reqMethod = method }
134159
160+
135161-- -- VERB (No content) --
136162instance {-# OVERLAPPING #-}
137163 (ReflectMethod method, SupportsServantReflex t m) =>
138− HasClient t m (Verb method status cts NoContent) where
139− type Client t m (Verb method status cts NoContent) =
140− Event t () -> m (Event t (ReqResult NoContent))
164+ HasClient t m (Verb method status cts NoContent) tag where
165+ type Client t m (Verb method status cts NoContent) tag =
166+ Event t tag -> m (Event t (ReqResult tag NoContent))
141167 -- TODO: how to access input types here?
142168 -- ExceptT ServantError IO NoContent
143− clientWithRoute Proxy _ =
144− performRequestNoBody method
169+ clientWithRoute Proxy _ _ req baseurl =
170+ (fmap . fmap) runIdentity . performRequestsNoBody method (constDyn $ Identity req) baseurl
145171 where method = E.decodeUtf8 $ reflectMethod (Proxy :: Proxy method)
146172
147−toHeaders :: BuildHeadersTo ls => ReqResult a -> ReqResult (Headers ls a)
173+
174+toHeaders :: BuildHeadersTo ls => ReqResult tag a -> ReqResult tag (Headers ls a)
148175toHeaders r =
149176 let toBS = E.encodeUtf8
150177 hdrs = maybe []
@@ -173,33 +200,35 @@ instance {-# OVERLAPPABLE #-}
173200 ( MimeUnrender ct a, BuildHeadersTo ls, BuildHeaderKeysTo ls,
174201 ReflectMethod method, cts' ~ (ct ': cts),
175202 SupportsServantReflex t m
176− ) => HasClient t m (Verb method status cts' (Headers ls a)) where
177− type Client t m (Verb method status cts' (Headers ls a)) =
178− Event t () -> m (Event t (ReqResult (Headers ls a)))
179− clientWithRoute Proxy _ req baseurl = do
203+ ) => HasClient t m (Verb method status cts' (Headers ls a)) tag where
204+ type Client t m (Verb method status cts' (Headers ls a)) tag =
205+ Event t tag -> m (Event t (ReqResult tag (Headers ls a)))
206+ clientWithRoute Proxy _ _ req baseurl trigs = do
180207 let method = E.decodeUtf8 $ reflectMethod (Proxy :: Proxy method)
181− resp <- performRequestCT (Proxy :: Proxy ct) method req' baseurl
182− return $ (fmap . fmap) toHeaders resp
208+ resp <- fmap runIdentity <$> performRequestsCT (Proxy :: Proxy ct) method (constDyn $ Identity req') baseurl trigs
209+ return $ toHeaders <$> resp
183210 where req' = req { respHeaders =
184211 OnlyHeaders (Set.fromList (buildHeaderKeysTo (Proxy :: Proxy ls)))
185212 }
186213
214+
187215-- HEADERS Verb (No content) --
188216instance {-# OVERLAPPABLE #-}
189217 ( BuildHeadersTo ls, BuildHeaderKeysTo ls, ReflectMethod method,
190218 SupportsServantReflex t m
191− ) => HasClient t m (Verb method status cts (Headers ls NoContent)) where
192− type Client t m (Verb method status cts (Headers ls NoContent))
193− = Event t () -> m (Event t (ReqResult (Headers ls NoContent)))
194− clientWithRoute Proxy _ req baseurl = do
219+ ) => HasClient t m (Verb method status cts (Headers ls NoContent)) tag where
220+ type Client t m (Verb method status cts (Headers ls NoContent)) tag
221+ = Event t tag -> m (Event t (ReqResult tag (Headers ls NoContent)))
222+ clientWithRoute Proxy _ _ req baseurl trigs = do
195223 let method = E.decodeUtf8 $ reflectMethod (Proxy :: Proxy method)
196− resp <- performRequestNoBody method req' baseurl
197− return $ (fmap . fmap) toHeaders resp
224+ resp <- fmap runIdentity <$> performRequestsNoBody method (constDyn $ Identity req') baseurl trigs
225+ return $ toHeaders <$> resp
198226 where req' = req {respHeaders =
199227 OnlyHeaders (Set.fromList (buildHeaderKeysTo (Proxy :: Proxy ls)))
200228 }
201229
202230
231+
203232-- HEADER
204233-- > newtype Referer = Referer { referrer :: Text }
205234-- > deriving (Eq, Show, Generic, FromText, ToHttpApiData)
@@ -214,28 +243,32 @@ instance {-# OVERLAPPABLE #-}
214243-- > -- then you can just use "viewRefer" to query that endpoint
215244-- > -- specifying Nothing or e.g Just "http://haskell.org/" as arguments
216245instance (KnownSymbol sym, ToHttpApiData a,
217− HasClient t m sublayout, SupportsServantReflex t m)
218− => HasClient t m (Header sym a :> sublayout) where
246+ HasClient t m sublayout tag, SupportsServantReflex t m)
247+ => HasClient t m (Header sym a :> sublayout) tag where
219248
220− type Client t m (Header sym a :> sublayout) =
221− Dynamic t (Either Text a) -> Client t m sublayout
249+ type Client t m (Header sym a :> sublayout) tag =
250+ Dynamic t (Either Text a) -> Client t m sublayout tag
222251
223− clientWithRoute Proxy q req baseurl eVal =
252+ clientWithRoute Proxy q t req baseurl eVal =
224253 clientWithRoute (Proxy :: Proxy sublayout)
225− q
254+ q t
226255 (Servant.Common.Req.addHeader hname eVal req)
227256 baseurl
228257 where hname = T.pack $ symbolVal (Proxy :: Proxy sym)
229258
259+
260+
261+
230262-- | Using a 'HttpVersion' combinator in your API doesn't affect the client
231263-- functions.
232−instance HasClient t m sublayout
233− => HasClient t m (HttpVersion :> sublayout) where
264+instance HasClient t m sublayout tag
265+ => HasClient t m (HttpVersion :> sublayout) tag where
234266
235− type Client t m (HttpVersion :> sublayout) =
236− Client t m sublayout
267+ type Client t m (HttpVersion :> sublayout) tag =
268+ Client t m sublayout tag
237269
238− clientWithRoute Proxy = clientWithRoute (Proxy :: Proxy sublayout)
270+ clientWithRoute Proxy q t =
271+ clientWithRoute (Proxy :: Proxy sublayout) q t
239272
240273
241274-- | If you use a 'QueryParam' in one of your endpoints in your API,
@@ -264,15 +297,15 @@ instance HasClient t m sublayout
264297-- > -- then you can just use "getBooksBy" to query that endpoint.
265298-- > -- 'getBooksBy Nothing' for all books
266299-- > -- 'getBooksBy (Just "Isaac Asimov")' to get all books by Isaac Asimov
267−instance (KnownSymbol sym, ToHttpApiData a, HasClient t m sublayout, Reflex t)
268− => HasClient t m (QueryParam sym a :> sublayout) where
300+instance (KnownSymbol sym, ToHttpApiData a, HasClient t m sublayout tag, Reflex t)
301+ => HasClient t m (QueryParam sym a :> sublayout) tag where
269302
270− type Client t m (QueryParam sym a :> sublayout) =
271− Dynamic t (QParam a) -> Client t m sublayout
303+ type Client t m (QueryParam sym a :> sublayout) tag =
304+ Dynamic t (QParam a) -> Client t m sublayout tag
272305
273306 -- if mparam = Nothing, we don't add it to the query string
274− clientWithRoute Proxy q req baseurl mparam =
275− clientWithRoute (Proxy :: Proxy sublayout) q
307+ clientWithRoute Proxy q t req baseurl mparam =
308+ clientWithRoute (Proxy :: Proxy sublayout) q t
276309 (req {qParams = paramPair : qParams req}) baseurl
277310
278311 where pname = symbolVal (Proxy :: Proxy sym)
@@ -281,6 +314,8 @@ instance (KnownSymbol sym, ToHttpApiData a, HasClient t m sublayout, Reflex t)
281314 p prm = QueryPartParam $ fmap qParamToQueryPart prm -- (fmap . fmap) (unpack . toQueryParam) prm
282315 paramPair = (T.pack pname, p mparam)
283316
317+
318+
284319-- | If you use a 'QueryParams' in one of your endpoints in your API,
285320-- the corresponding querying function will automatically take
286321-- an additional argument, a list of values of the type specified
@@ -309,14 +344,14 @@ instance (KnownSymbol sym, ToHttpApiData a, HasClient t m sublayout, Reflex t)
309344-- > -- 'getBooksBy []' for all books
310345-- > -- 'getBooksBy ["Isaac Asimov", "Robert A. Heinlein"]'
311346-- > -- to get all books by Asimov and Heinlein
312−instance (KnownSymbol sym, ToHttpApiData a, HasClient t m sublayout, Reflex t)
313− => HasClient t m (QueryParams sym a :> sublayout) where
347+instance (KnownSymbol sym, ToHttpApiData a, HasClient t m sublayout tag, Reflex t)
348+ => HasClient t m (QueryParams sym a :> sublayout) tag where
314349
315− type Client t m (QueryParams sym a :> sublayout) =
316− Dynamic t [a] -> Client t m sublayout
350+ type Client t m (QueryParams sym a :> sublayout) tag =
351+ Dynamic t [a] -> Client t m sublayout tag
317352
318− clientWithRoute Proxy q req baseurl paramlist =
319− clientWithRoute (Proxy :: Proxy sublayout) q req' baseurl
353+ clientWithRoute Proxy q t req baseurl paramlist =
354+ clientWithRoute (Proxy :: Proxy sublayout) q t req' baseurl
320355
321356 where req' = req { qParams = (T.pack pname, params') : qParams req }
322357 pname = symbolVal (Proxy :: Proxy sym)
@@ -324,6 +359,7 @@ instance (KnownSymbol sym, ToHttpApiData a, HasClient t m sublayout, Reflex t)
324359 paramlist
325360
326361
362+
327363-- | If you use a 'QueryFlag' in one of your endpoints in your API,
328364-- the corresponding querying function will automatically take
329365-- an additional 'Bool' argument.
@@ -348,49 +384,42 @@ instance (KnownSymbol sym, ToHttpApiData a, HasClient t m sublayout, Reflex t)
348384-- > -- 'getBooksBy True' to only get _already published_ books
349385
350386-- TODO Bring back
351−instance (KnownSymbol sym, HasClient t m sublayout, Reflex t)
352− => HasClient t m (QueryFlag sym :> sublayout) where
387+instance (KnownSymbol sym, HasClient t m sublayout tag, Reflex t)
388+ => HasClient t m (QueryFlag sym :> sublayout) tag where
353389
354− type Client t m (QueryFlag sym :> sublayout) =
355− Dynamic t Bool -> Client t m sublayout
390+ type Client t m (QueryFlag sym :> sublayout) tag =
391+ Dynamic t Bool -> Client t m sublayout tag
356392
357− clientWithRoute Proxy q req baseurl flag =
358− clientWithRoute (Proxy :: Proxy sublayout) q req' baseurl
393+ clientWithRoute Proxy q t req baseurl flag =
394+ clientWithRoute (Proxy :: Proxy sublayout) q t req' baseurl
359395
360396 where req' = req { qParams = thisPair : qParams req }
361397 thisPair = (T.pack pName, QueryPartFlag flag) :: (Text, QueryPart t)
362398 pName = symbolVal (Proxy :: Proxy sym)
363399
364400
365−-- | Pick a 'Method' and specify where the server you want to query is. You get
366−-- back the full `Response`.
367−-- TODO redo
368−instance SupportsServantReflex t m => HasClient t m Raw where
369− type Client t m Raw = Dynamic t (Either Text (XhrRequest ()))
370− -> Event t ()
371− -> m (Event t (ReqResult ()))
372−
373− -- clientWithRoute :: Proxy Raw -> Proxy m -> Req -> BaseUrl -> Client t m Raw
374− clientWithRoute _ _ _ baseurl xhrs triggers = do
375− let xhrs' = liftA2 (\x path -> case x of
376− Left e -> Left e
377− Right jx -> Right $ jx {_xhrRequest_url = path
378− <> _xhrRequest_url jx})
379− xhrs
380− (showBaseUrl <$> baseurl)
381− reqs = tagPromptlyDyn xhrs' triggers
382− okReq = fmapMaybe hush reqs
383− badReq = fmapMaybe tattle reqs
384− resps <- performRequestAsync okReq
385− return $ leftmost [fmap (ResponseSuccess () ) resps
386− ,fmap RequestFailure badReq]
387−
388−
389−hush :: Either e a -> Maybe a
390−hush = either (const Nothing) Just
391−
392−tattle :: Either e a -> Maybe e
393−tattle = either Just (const Nothing)
401+
402+-- | Send a raw 'XhrRequest ()' directly to 'baseurl'
403+instance SupportsServantReflex t m => HasClient t m Raw tag where
404+ type Client t m Raw tag = Dynamic t (Either Text (XhrRequest ()))
405+ -> Event t tag
406+ -> m (Event t (ReqResult tag ()))
407+
408+ clientWithRoute _ _ _ _ baseurl xhrs triggers = do
409+
410+ let xhrs' = liftA2 (\x path -> case x of
411+ Left e -> Left e
412+ Right jx -> Right $ jx { _xhrRequest_url = path <> _xhrRequest_url jx }
413+ ) xhrs (showBaseUrl <$> baseurl)
414+ xhrs'' = attachPromptlyDynWith (flip (,)) xhrs' triggers :: Event t (tag, Either Text (XhrRequest ()))
415+ badReq = fmapMaybe (\(t,x) -> either (Just . (t,)) (const Nothing) x) xhrs'' :: Event t (tag, Text)
416+ okReq = fmapMaybe (\(t,x) -> either (const Nothing) (Just . (t,)) x) xhrs'' :: Event t (tag, XhrRequest ())
417+
418+ resps <- performRequestsAsync okReq
419+ return $ leftmost [ uncurry RequestFailure <$> badReq
420+ , evalResponse (const $ Right ()) <$> resps
421+ ]
422+
394423
395424-- | If you use a 'ReqBody' in one of your endpoints in your API,
396425-- the corresponding querying function will automatically take
@@ -412,14 +441,14 @@ tattle = either Just (const Nothing)
412441-- > where host = BaseUrl Http "localhost" 8080
413442-- > -- then you can just use "addBook" to query that endpoint
414443
415−instance (MimeRender ct a, HasClient t m sublayout, Reflex t)
416− => HasClient t m (ReqBody (ct ': cts) a :> sublayout) where
444+instance (MimeRender ct a, HasClient t m sublayout tag, Reflex t)
445+ => HasClient t m (ReqBody (ct ': cts) a :> sublayout) tag where
417446
418− type Client t m (ReqBody (ct ': cts) a :> sublayout) =
419− Dynamic t (Either Text a) -> Client t m sublayout
447+ type Client t m (ReqBody (ct ': cts) a :> sublayout) tag =
448+ Dynamic t (Either Text a) -> Client t m sublayout tag
420449
421− clientWithRoute Proxy q req baseurl body =
422− clientWithRoute (Proxy :: Proxy sublayout) q req' baseurl
450+ clientWithRoute Proxy q t req baseurl body =
451+ clientWithRoute (Proxy :: Proxy sublayout) q t req' baseurl
423452 where req' = req { reqBody = bodyBytesCT }
424453 ctProxy = Proxy :: Proxy ct
425454 ctString = T.pack $ show $ contentType ctProxy
@@ -427,39 +456,49 @@ instance (MimeRender ct a, HasClient t m sublayout, Reflex t)
427456 (\b -> (mimeRender ctProxy b, ctString))
428457 body
429458
459+
460+
430461-- | Make the querying function append @path@ to the request path.
431−instance (KnownSymbol path, HasClient t m sublayout, Reflex t) => HasClient t m (path :> sublayout) where
432− type Client t m (path :> sublayout) = Client t m sublayout
462+instance (KnownSymbol path, HasClient t m sublayout tag, Reflex t) => HasClient t m (path :> sublayout) tag where
463+ type Client t m (path :> sublayout) tag = Client t m sublayout tag
433464
434− clientWithRoute Proxy q req =
435− clientWithRoute (Proxy :: Proxy sublayout) q
436− (prependToPathParts (pure (Right $ T.pack p)) req)
465+ clientWithRoute Proxy q t req baseurl =
466+ clientWithRoute (Proxy :: Proxy sublayout) q t
467+ (prependToPathParts (pure (Right $ T.pack p)) req) baseurl
437468
438469 where p = symbolVal (Proxy :: Proxy path)
439470
440−instance HasClient t m api => HasClient t m (Vault :> api) where
441− type Client t m (Vault :> api) = Client t m api
442471
443− clientWithRoute Proxy = clientWithRoute (Proxy :: Proxy api)
472+instance HasClient t m api tag => HasClient t m (Vault :> api) tag where
473+ type Client t m (Vault :> api) tag = Client t m api tag
474+
475+ clientWithRoute Proxy q t req baseurl =
476+ clientWithRoute (Proxy :: Proxy api) q t req baseurl
477+
478+
479+instance HasClient t m api tag => HasClient t m (RemoteHost :> api) tag where
480+ type Client t m (RemoteHost :> api) tag = Client t m api tag
481+
482+ clientWithRoute Proxy q t req baseurl =
483+ clientWithRoute (Proxy :: Proxy api) q t req baseurl
484+
444485
445−instance HasClient t m api => HasClient t m (RemoteHost :> api) where
446− type Client t m (RemoteHost :> api) = Client t m api
447486
448− clientWithRoute Proxy = clientWithRoute (Proxy :: Proxy api)
487+instance HasClient t m api tag => HasClient t m (IsSecure :> api) tag where
488+ type Client t m (IsSecure :> api) tag = Client t m api tag
449489
450−instance HasClient t m api => HasClient t m (IsSecure :> api) where
451− type Client t m (IsSecure :> api) = Client t m api
490+ clientWithRoute Proxy q t req baseurl =
491+ clientWithRoute (Proxy :: Proxy api) q t req baseurl
452492
453− clientWithRoute Proxy = clientWithRoute (Proxy :: Proxy api)
454493
455−instance (HasClient t m api, Reflex t)
456− => HasClient t m (BasicAuth realm usr :> api) where
494+instance (HasClient t m api tag, Reflex t)
495+ => HasClient t m (BasicAuth realm usr :> api) tag where
457496
458− type Client t m (BasicAuth realm usr :> api) = Dynamic t (Maybe BasicAuthData)
459− -> Client t m api
497+ type Client t m (BasicAuth realm usr :> api) tag = Dynamic t (Maybe BasicAuthData)
498+ -> Client t m api tag
460499
461− clientWithRoute Proxy q req baseurl authdata =
462− clientWithRoute (Proxy :: Proxy api) q req' baseurl
500+ clientWithRoute Proxy q t req baseurl authdata =
501+ clientWithRoute (Proxy :: Proxy api) q t req' baseurl
463502 where
464503 req' = req { authData = Just authdata }
465504