on master help sign in
Add request tagging to multi-param api
commitafed558ec9ca49f8a235eddfb141f0e93fa0b101 authorGreg Hale <imalsogreg@gmail.com> dateSun 19 Feb 2017, 21:42 (10 years ago) parentf6d3b8b
5 files changed+308−296
exec/Example.hs+37−25 servant-reflex.cabal+1−1 src/Servant/Common/Req.hs+44−37 src/Servant/Reflex.hs+118−130 src/Servant/Reflex/Multi.hs+108−103
exec/Example.hs+37−25
@@ -2,6 +2,7 @@
22{-# LANGUAGE GADTs #-}
33{-# LANGUAGE OverloadedStrings #-}
44{-# LANGUAGE RankNTypes #-}
5+{-# LANGUAGE RecursiveDo #-}
56{-# LANGUAGE ScopedTypeVariables #-}
67
78module Main where
@@ -42,14 +43,17 @@ runMulti = do
4243 url <- baseUrlWidget
4344 el "br" blank
4445 let (_ :<|> _ :<|> _ :<|> dbl :<|> _ :<|> _ ) =
45− clientA api (Proxy :: Proxy m) (Proxy :: Proxy []) url
46+ clientA api (Proxy :: Proxy m) (Proxy :: Proxy []) (Proxy :: Proxy Int) url
4647 num :: Dynamic t (Either Text Double) <- fmap (note "No read" . readMaybe . T.unpack) . value <$> textInput def
4748 num2 :: Dynamic t (Either Text Double) <- fmap (note "No read" . readMaybe . T.unpack) . value <$> textInput def
4849 -- dynText =<< holdDyn "waiting" (T.pack . show <$> num)
4950 -- numLabeled :: Event t (First Int, Double) <- zipListWithEvent (,) (First . Just <$> [0..]) num
5051 b <- button "Run dbl multi"
51− r <- dbl [num,num2] b
52− dynText =<< holdDyn "Waiting" (T.pack . show . fmapMaybe reqSuccess <$> r)
52+ reqCount <- count b
53+ r <- dbl [num,num2] (tag (current reqCount) b)
54+ dynText =<< holdDyn "Waiting" (T.pack . show . fmapMaybe reqSuccess .snd <$> r)
55+ lastInd <- holdDyn Nothing (Just . fst <$> r)
56+ display lastInd
5357 return ()
5458
5559run :: forall t m. (SupportsServantReflex t m,
@@ -58,8 +62,10 @@ run :: forall t m. (SupportsServantReflex t m,
5862 MonadFix m,
5963 PostBuild t m,
6064 MonadHold t m) => m ()
61−run = do
65+run = mdo
6266
67+ reqCount <- count $ leftmost
68+ [() <$ unitBtn, () <$ intBtn, () <$ sayHiClicks, () <$ dblBtn, () <$ mpGo]
6369 -- Allow user to choose the url target for the request
6470 -- (alternatively we could just `let url = constDyn (BasePath "/")`)
6571 url <- baseUrlWidget
@@ -70,24 +76,25 @@ run = do
7076
7177 -- Name the computed API client functions
7278 let (getUnit :<|> getInt :<|> sayhi :<|> dbl :<|> multi :<|> doRaw) =
73− client api (Proxy :: Proxy m) url
79+ client api (Proxy :: Proxy m) (Proxy :: Proxy Int) url
7480
75− elClass "div" "demo-group" $ do
81+ (unitBtn, intBtn) <- elClass "div" "demo-group" $ do
7682 unitBtn <- divClass "unit-button" $ button "Get unit"
7783 intBtn <- divClass "int-button" $ button "Get int"
7884
79− unitResponse <- getUnit unitBtn
80− intResponse :: Event t (ReqResult Int) <- getInt intBtn
85+ unitResponse <- getUnit $ tag (current reqCount) unitBtn
86+ intResponse :: Event t (Int, ReqResult Int) <- getInt $ tag (current reqCount) intBtn
8187
82− score <- foldDyn (+) 0 (fmapMaybe reqSuccess intResponse)
88+ score <- foldDyn (+) 0 (fmapMaybe reqSuccess (snd <$> intResponse))
8389
8490 r <- holdDyn "Waiting" $ fmap showXhrResponse $
85− leftmost [fmapMaybe response unitResponse
86− ,fmapMaybe response intResponse
91+ leftmost [fmapMaybe response (snd <$> unitResponse)
92+ ,fmapMaybe response (snd <$> intResponse)
8793 ]
8894 divClass "unit-int-response" $ el "p" $ dynText r >> el "br" (return ()) >> text "Total: " >> display score
95+ return (unitBtn, intBtn)
8996
90− elClass "div" "demo-group" $ do
97+ sayHiClicks <- elClass "div" "demo-group" $ do
9198
9299 text "Name"
93100 el "br" $ return ()
@@ -105,36 +112,41 @@ run = do
105112 gusto <- fmap value $ divClass "gusto-input" $ checkbox False def
106113
107114 el "br" $ return ()
108− sayhiClicks :: Event t () <- divClass "hi-button" $ button "Say hi"
109− let triggers = leftmost [sayhiClicks, () <$ updated inp]
115+ sayHiClicks :: Event t () <- divClass "hi-button" $ button "Say hi"
116+ let triggers = leftmost [sayHiClicks, () <$ updated inp]
110117
111− resp <- sayhi checkedName greetings gusto triggers
118+ resp <- sayhi checkedName greetings gusto (tag (current reqCount) triggers)
112119 divClass "greeting-response" $ dynText =<<
113− holdDyn "No hi yet" (leftmost [ fmapMaybe reqSuccess resp
114− , fmapMaybe reqFailure resp])
120+ holdDyn "No hi yet" (leftmost [ fmapMaybe reqSuccess (snd <$> resp)
121+ , fmapMaybe reqFailure (snd <$> resp)])
122+ return sayHiClicks
115123
116− elClass "div" "demo-group" $ do
124+ dblBtn <- elClass "div" "demo-group" $ do
117125 text "A Double to double"
118126 el "br" $ return ()
119127 dblinp <- fmap value $ divClass "double-input" $ textInput def
120128 (dblBtn) <- divClass "double-button" $ button "Double it"
121129 dblResp <- dbl (fmap (note "read failure" . readMaybe . T.unpack) $
122− dblinp) dblBtn
123− divClass "double-errors" $ dynText =<<
124− holdDyn "(no errors)" (fmapMaybe reqFailure dblResp)
130+ dblinp) (tag (current reqCount) dblBtn)
131+ divClass "double-errors" $ dynText =<<
132+ holdDyn "(no errors)" (fmapMaybe reqFailure (snd <$> dblResp))
125133 el "br" (return ())
126134 divClass "double-result" $ el "p" $ dynText =<<
127135 holdDyn "No number yet" (fmap tShow $
128− fmapMaybe reqSuccess dblResp)
136+ fmapMaybe reqSuccess (snd <$> dblResp))
137+ return dblBtn
129138
130− elClass "div" "demo-group" $ do
139+ mpGo <- elClass "div" "demo-group" $ do
131140 text "Multi-part path"
132141 b <- value <$> checkbox False def
133142 mpGo <- button "Test"
134− multiResp <- multi b mpGo
143+ multiResp <- multi b (tag (current reqCount) mpGo)
135144 dynText =<< holdDyn "No res yet" (fmap tShow $
136145 fmapMaybe reqSuccess $
137− multiResp)
146+ (snd <$> multiResp))
147+ return mpGo
148+
149+ return ()
138150
139151showXhrResponse :: XhrResponse -> Text
140152showXhrResponse (XhrResponse stat stattxt rbmay rtmay respHeaders) =
servant-reflex.cabal+1−1
@@ -1,5 +1,5 @@
11Name: servant-reflex
2−Version: 0.2.1
2+Version: 0.3
33Synopsis: Servant reflex API generator
44Description: Servant reflex API generator
55License: AllRightsReserved
src/Servant/Common/Req.hs+44−37
@@ -14,10 +14,12 @@ module Servant.Common.Req where
1414-------------------------------------------------------------------------------
1515import Control.Concurrent
1616import Control.Applicative (liftA2, liftA3)
17+import Control.Arrow (second)
1718import Control.Monad.IO.Class (MonadIO, liftIO)
1819import qualified Data.ByteString.Lazy.Char8 as BL
1920import qualified Data.Map as Map
2021import Data.Maybe (catMaybes)
22+import Data.Functor.Compose
2123import Data.Monoid ((<>))
2224import Data.Proxy (Proxy(..))
2325import Data.Text (Text)
@@ -209,17 +211,17 @@ displayHttpRequest :: Text -> Text
209211displayHttpRequest httpmethod = "HTTP " <> httpmethod <> " request"
210212
211213-- | This function actually performs the request.
212−performRequests :: forall t m f.(SupportsServantReflex t m, Traversable f)
214+performRequests :: forall t m f tag.(SupportsServantReflex t m, Traversable f)
213215 => Text
214216 -> f (Req t)
215217 -> Dynamic t BaseUrl
216− -> Event t ()
217− -> m (Event t (f (Either Text XhrResponse)))
218+ -> Event t tag
219+ -> m (Event t (tag, f (Either Text XhrResponse)))
218220performRequests reqMeth rs reqHost trigger = do
219221 let xhrReqs = sequence $ (\r -> reqToReflexRequest reqMeth r reqHost) <$> rs :: Dynamic t (f (Either Text (XhrRequest XhrPayload)))
220− let reqs = tagPromptlyDyn xhrReqs trigger
222+ let reqs = attachPromptlyDynWith (\fxhr t -> Compose (t, fxhr)) xhrReqs trigger
221223 resps <- performSomeRequestsAsync reqs
222− return resps
224+ return $ getCompose <$> resps
223225
224226-- | Issues a collection of requests when the supplied Event fires. When ALL requests from a given firing complete, the results are collected and returned via the return Event.
225227performSomeRequestsAsync
@@ -257,20 +259,20 @@ performSomeRequestsAsync' newXhr req = performEventAsync $ ffor req $ \hrs cb ->
257259
258260
259261-- | This function actually performs the request.
260−performRequest :: forall t m .(SupportsServantReflex t m)
262+performRequest :: forall t m tag .(SupportsServantReflex t m)
261263 => Text
262264 -> (Req t)
263265 -> Dynamic t BaseUrl
264− -> Event t ()
265− -> m (Event t (XhrResponse), Event t Text)
266+ -> Event t tag
267+ -> m (Event t (tag, XhrResponse), Event t (tag, Text))
266268performRequest reqMeth req reqHost trigger = do
267269
268270 let xhrReq = reqToReflexRequest reqMeth req reqHost
269− let reqs = tagPromptlyDyn xhrReq trigger
270− okReqs = fmapMaybe (either (const Nothing) Just) reqs
271− badReqs = fmapMaybe (either Just (const Nothing)) reqs
271+ let reqs = attachPromptlyDynWith (flip (,)) xhrReq trigger
272+ okReqs = fmapMaybe (\(t,e) -> either (const Nothing) (Just . (t,)) e) reqs
273+ badReqs = fmapMaybe (\(t,e) -> either (Just . (t,)) (const Nothing) e) reqs
272274
273− resps <- performRequestAsync okReqs
275+ resps <- performRequestsAsync okReqs
274276
275277 return (resps, badReqs)
276278
@@ -285,43 +287,47 @@ bytesToPayload :: BL.ByteString -> XhrPayload
285287bytesToPayload = T.pack . BL.unpack
286288#endif
287289
288−performRequestNoBody :: forall t m .(SupportsServantReflex t m)
290+performRequestNoBody :: forall t m tag.(SupportsServantReflex t m)
289291 => Text
290292 -> Req t
291293 -> Dynamic t BaseUrl
292− -> Event t () -> m (Event t (ReqResult NoContent))
294+ -> Event t tag -> m (Event t (tag, ReqResult NoContent))
293295performRequestNoBody reqMeth req reqHost trigger = do
294296 (resp, badReq) <- performRequest reqMeth req reqHost trigger
295− return $ leftmost [ fmap (ResponseSuccess NoContent) resp, fmap RequestFailure badReq]
297+ return $ leftmost [ fmap (ResponseSuccess NoContent) <$> resp, fmap RequestFailure <$> badReq]
296298
297−performRequestsNoBody :: forall t m f .(SupportsServantReflex t m, Traversable f)
299+performRequestsNoBody :: forall t m f tag. (SupportsServantReflex t m, Traversable f)
298300 => Text
299301 -> f (Req t)
300302 -> Dynamic t BaseUrl
301− -> Event t () -> m (Event t (f (ReqResult NoContent)))
303+ -> Event t tag -> m (Event t (tag, f (ReqResult NoContent)))
302304performRequestsNoBody reqMeth reqs reqHost trigger = do
303305 resp <- performRequests reqMeth reqs reqHost trigger
304− return $ (fmap . fmap) aux resp
306+ return $ (fmap . fmap) aux <$> resp
305307 where
306308 aux (Right x) = ResponseSuccess NoContent x
307309 aux (Left e) = RequestFailure e
308310 -- return $ leftmost [ fmap (ResponseSuccess NoContent) resp, fmap RequestFailure badReq]
309311
310312
311−
312−performRequestCT :: (SupportsServantReflex t m,
313− MimeUnrender ct a)
314− => Proxy ct -> Text -> Req t -> Dynamic t BaseUrl
315− -> Event t () -> m (Event t (ReqResult a))
313+performRequestCT
314+ :: (SupportsServantReflex t m,
315+ MimeUnrender ct a)
316+ => Proxy ct
317+ -> Text
318+ -> Req t
319+ -> Dynamic t BaseUrl
320+ -> Event t tag
321+ -> m (Event t (tag, ReqResult a))
316322performRequestCT ct reqMeth req reqHost trigger = do
317323 (resp, badReq) <- performRequest reqMeth req reqHost trigger
318− let decodes = ffor resp $ \xhr ->
324+ let decodes = ffor resp $ fmap (\xhr ->
319325 ((mimeUnrender ct . BL.fromStrict . TE.encodeUtf8)
320− =<< note "No body text" (_xhrResponse_responseText xhr), xhr)
321− reqs = ffor decodes $ \case
326+ =<< note "No body text" (_xhrResponse_responseText xhr), xhr))
327+ reqs = ffor decodes $ fmap (\case
322328 (Right a, r) -> ResponseSuccess a r
323− (Left e, r) -> ResponseFailure (T.pack e) r
324− return $ leftmost [reqs, fmap RequestFailure badReq]
329+ (Left e, r) -> ResponseFailure (T.pack e) r)
330+ return $ leftmost [reqs, fmap RequestFailure <$> badReq]
325331
326332performRequestsCT
327333 :: (SupportsServantReflex t m,
@@ -330,17 +336,18 @@ performRequestsCT
330336 -> Text
331337 -> f (Req t)
332338 -> Dynamic t BaseUrl
333− -> Event t ()
334− -> m (Event t (f (ReqResult a)))
339+ -> Event t tag
340+ -> m (Event t (tag, f (ReqResult a)))
335341performRequestsCT ct reqMeth reqs reqHost trigger = do
336342 resps <- performRequests reqMeth reqs reqHost trigger
337− return $ ffor resps $ \eithXhrs -> ffor eithXhrs $ \eithXhr -> case eithXhr of
338− Left e -> RequestFailure e
339− Right x -> case _xhrResponse_responseText x of
340− Nothing -> ResponseFailure "No body text" x
341− Just bod -> case mimeUnrender ct . BL.fromStrict . TE.encodeUtf8 $ bod of
342− Left e -> ResponseFailure (T.pack e) x
343− Right a -> ResponseSuccess a x
343+ return $ fmap (second (fmap reqToResult)) resps
344+ where
345+ reqToResult (Left e) = RequestFailure e
346+ reqToResult (Right x) = case _xhrResponse_responseText x of
347+ Nothing -> ResponseFailure "No request body" x
348+ Just bod -> case mimeUnrender ct . BL.fromStrict . TE.encodeUtf8 $ bod of
349+ Left e -> ResponseFailure (T.pack e) x
350+ Right v -> ResponseSuccess v x
344351
345352
346353note :: e -> Maybe a -> Either e a
src/Servant/Reflex.hs+118−130
@@ -50,9 +50,9 @@ import Servant.API ((:<|>)(..),(:>), BasicAuth,
5050import Reflex.Dom (Dynamic, Event, Reflex,
5151 XhrRequest(..),
5252 XhrResponseHeaders(..),
53− XhrResponse(..), ffor, fmapMaybe,
54− leftmost, performRequestAsync,
55− tagPromptlyDyn )
53+ XhrResponse(..), attachPromptlyDynWith, ffor, fmapMaybe,
54+ leftmost, performRequestsAsync,
55+ )
5656------------------------------------------------------------------------------
5757import Servant.Common.BaseUrl (BaseUrl(..), Scheme(..), baseUrlWidget,
5858 showBaseUrl,
@@ -80,30 +80,30 @@ import Servant.Common.Req (Req, ReqResult(..), QParam(..),
8080-- > myApi :: Proxy MyApi
8181-- > myApi = Proxy
8282-- >
83−-- > getAllBooks :: Event t () -> m (Event t (Either XhrError ((),[Book])))
84−-- > postNewBook :: Dynamic t (Maybe Book) -> Event t ()
85−-- -> m (Event t (Either XhrError (Book,Book)))
83+-- > getAllBooks :: Event t l -> m (Event t (l, ReqResult [Book]))
84+-- > postNewBook :: Dynamic t (Maybe Book) -> Event t l
85+-- -> m (Event t (l, ReqResult Book)))
8686-- > (getAllBooks :<|> postNewBook) = client myApi host
8787-- > where host = constDyn $ BaseUrl Http "localhost" 8080
88−client :: (HasClient t m layout)
89− => Proxy layout -> Proxy m -> Dynamic t BaseUrl -> Client t m layout
90−client p q baseurl = clientWithRoute p q defReq baseurl
88+client :: (HasClient t m layout tag)
89+ => Proxy layout -> Proxy m -> Proxy tag -> Dynamic t BaseUrl -> Client t m layout tag
90+client p q t baseurl = clientWithRoute p q t defReq baseurl
9191
9292
9393-- | This class lets us define how each API combinator
9494-- influences the creation of an HTTP request. It's mostly
9595-- an internal class, you can just use 'client'.
96−class HasClient t m layout where
97− type Client t m layout :: *
98− clientWithRoute :: Proxy layout -> Proxy m -> Req t -> Dynamic t BaseUrl -> Client t m layout
96+class HasClient t m layout (tag :: *) where
97+ type Client t m layout tag :: *
98+ clientWithRoute :: Proxy layout -> Proxy m -> Proxy tag -> Req t -> Dynamic t BaseUrl -> Client t m layout tag
9999
100100
101−instance (HasClient t m a, HasClient t m b) => HasClient t m (a :<|> b) where
102− type Client t m (a :<|> b) = Client t m a :<|> Client t m b
101+instance (HasClient t m a tag, HasClient t m b tag) => HasClient t m (a :<|> b) tag where
102+ type Client t m (a :<|> b) tag = Client t m a tag :<|> Client t m b tag
103103
104− clientWithRoute Proxy q req baseurl =
105− clientWithRoute (Proxy :: Proxy a) q req baseurl :<|>
106− clientWithRoute (Proxy :: Proxy b) q req baseurl
104+ clientWithRoute Proxy q pTag req baseurl =
105+ clientWithRoute (Proxy :: Proxy a) q pTag req baseurl :<|>
106+ clientWithRoute (Proxy :: Proxy b) q pTag req baseurl
107107
108108
109109-- Capture. Example:
@@ -114,19 +114,19 @@ instance (HasClient t m a, HasClient t m b) => HasClient t m (a :<|> b) where
114114-- > getBook :: SupportsServantReflex t m
115115-- => Dynamic t BaseUrl
116116-- -> Dynamic t (Maybe Text)
117−-- -> Event t ()
118−-- -> m (Event t (Either XhrError (Text, Book)))
117+-- -> Event t l
118+-- -> m (Event t (l, ReqResult Book))
119119-- > getBook = client myApi (constDyn host)
120120
121−instance (SupportsServantReflex t m, ToHttpApiData a, HasClient t m sublayout)
122− => HasClient t m (Capture capture a :> sublayout) where
121+instance (SupportsServantReflex t m, ToHttpApiData a, HasClient t m sublayout tag)
122+ => HasClient t m (Capture capture a :> sublayout) tag where
123123
124− type Client t m (Capture capture a :> sublayout) =
125− Dynamic t (Either Text a) -> Client t m sublayout
124+ type Client t m (Capture capture a :> sublayout) tag =
125+ Dynamic t (Either Text a) -> Client t m sublayout tag
126126
127− clientWithRoute Proxy q req baseurl val =
127+ clientWithRoute Proxy q t req baseurl val =
128128 clientWithRoute (Proxy :: Proxy sublayout)
129− q
129+ q t
130130 (prependToPathParts p req)
131131 baseurl
132132 where p = (fmap . fmap) (toUrlPiece) val
@@ -136,28 +136,26 @@ instance (SupportsServantReflex t m, ToHttpApiData a, HasClient t m sublayout)
136136instance {-# OVERLAPPABLE #-}
137137 -- Note [Non-Empty Content Types]
138138 (MimeUnrender ct a, ReflectMethod method, cts' ~ (ct ': cts), SupportsServantReflex t m
139− ) => HasClient t m (Verb method status cts' a) where
140− type Client t m (Verb method status cts' a) =
141− Event t () -> m (Event t (ReqResult a))
139+ ) => HasClient t m (Verb method status cts' a) tag where
140+ type Client t m (Verb method status cts' a) tag =
141+ Event t tag -> m (Event t (tag, ReqResult a))
142142 -- TODO how to access input types here?
143143 -- ExceptT ServantError IO a
144− clientWithRoute Proxy _ req baseurl =
145− performRequestCT (Proxy :: Proxy ct) method req' baseurl
144+ clientWithRoute Proxy _ _ req baseurl trigs =
145+ performRequestCT (Proxy :: Proxy ct) method req' baseurl trigs
146146 where method = E.decodeUtf8 $ reflectMethod (Proxy :: Proxy method)
147147 req' = req { reqMethod = method }
148148
149149
150−
151−
152150-- -- VERB (No content) --
153151instance {-# OVERLAPPING #-}
154152 (ReflectMethod method, SupportsServantReflex t m) =>
155− HasClient t m (Verb method status cts NoContent) where
156− type Client t m (Verb method status cts NoContent) =
157− Event t () -> m (Event t (ReqResult NoContent))
153+ HasClient t m (Verb method status cts NoContent) tag where
154+ type Client t m (Verb method status cts NoContent) tag =
155+ Event t tag -> m (Event t (tag, ReqResult NoContent))
158156 -- TODO: how to access input types here?
159157 -- ExceptT ServantError IO NoContent
160− clientWithRoute Proxy _ req baseurl =
158+ clientWithRoute Proxy _ _ req baseurl =
161159 performRequestNoBody method req baseurl
162160 where method = E.decodeUtf8 $ reflectMethod (Proxy :: Proxy method)
163161
@@ -191,13 +189,13 @@ instance {-# OVERLAPPABLE #-}
191189 ( MimeUnrender ct a, BuildHeadersTo ls, BuildHeaderKeysTo ls,
192190 ReflectMethod method, cts' ~ (ct ': cts),
193191 SupportsServantReflex t m
194− ) => HasClient t m (Verb method status cts' (Headers ls a)) where
195− type Client t m (Verb method status cts' (Headers ls a)) =
196− Event t () -> m (Event t (ReqResult (Headers ls a)))
197− clientWithRoute Proxy _ req baseurl = do
192+ ) => HasClient t m (Verb method status cts' (Headers ls a)) tag where
193+ type Client t m (Verb method status cts' (Headers ls a)) tag =
194+ Event t tag -> m (Event t (tag, ReqResult (Headers ls a)))
195+ clientWithRoute Proxy _ _ req baseurl = do
198196 let method = E.decodeUtf8 $ reflectMethod (Proxy :: Proxy method)
199197 resp <- performRequestCT (Proxy :: Proxy ct) method req' baseurl
200− return $ (fmap . fmap) toHeaders resp
198+ return $ (fmap . fmap) toHeaders <$> resp
201199 where req' = req { respHeaders =
202200 OnlyHeaders (Set.fromList (buildHeaderKeysTo (Proxy :: Proxy ls)))
203201 }
@@ -207,13 +205,13 @@ instance {-# OVERLAPPABLE #-}
207205instance {-# OVERLAPPABLE #-}
208206 ( BuildHeadersTo ls, BuildHeaderKeysTo ls, ReflectMethod method,
209207 SupportsServantReflex t m
210− ) => HasClient t m (Verb method status cts (Headers ls NoContent)) where
211− type Client t m (Verb method status cts (Headers ls NoContent))
212− = Event t () -> m (Event t (ReqResult (Headers ls NoContent)))
213− clientWithRoute Proxy _ req baseurl = do
208+ ) => HasClient t m (Verb method status cts (Headers ls NoContent)) tag where
209+ type Client t m (Verb method status cts (Headers ls NoContent)) tag
210+ = Event t tag -> m (Event t (tag, ReqResult (Headers ls NoContent)))
211+ clientWithRoute Proxy _ _ req baseurl = do
214212 let method = E.decodeUtf8 $ reflectMethod (Proxy :: Proxy method)
215213 resp <- performRequestNoBody method req' baseurl
216− return $ (fmap . fmap) toHeaders resp
214+ return $ (fmap . fmap) toHeaders <$> resp
217215 where req' = req {respHeaders =
218216 OnlyHeaders (Set.fromList (buildHeaderKeysTo (Proxy :: Proxy ls)))
219217 }
@@ -234,15 +232,15 @@ instance {-# OVERLAPPABLE #-}
234232-- > -- then you can just use "viewRefer" to query that endpoint
235233-- > -- specifying Nothing or e.g Just "http://haskell.org/" as arguments
236234instance (KnownSymbol sym, ToHttpApiData a,
237− HasClient t m sublayout, SupportsServantReflex t m)
238− => HasClient t m (Header sym a :> sublayout) where
235+ HasClient t m sublayout tag, SupportsServantReflex t m)
236+ => HasClient t m (Header sym a :> sublayout) tag where
239237
240− type Client t m (Header sym a :> sublayout) =
241− Dynamic t (Either Text a) -> Client t m sublayout
238+ type Client t m (Header sym a :> sublayout) tag =
239+ Dynamic t (Either Text a) -> Client t m sublayout tag
242240
243− clientWithRoute Proxy q req baseurl eVal =
241+ clientWithRoute Proxy q t req baseurl eVal =
244242 clientWithRoute (Proxy :: Proxy sublayout)
245− q
243+ q t
246244 (Servant.Common.Req.addHeader hname eVal req)
247245 baseurl
248246 where hname = T.pack $ symbolVal (Proxy :: Proxy sym)
@@ -252,14 +250,14 @@ instance (KnownSymbol sym, ToHttpApiData a,
252250
253251-- | Using a 'HttpVersion' combinator in your API doesn't affect the client
254252-- functions.
255−instance HasClient t m sublayout
256− => HasClient t m (HttpVersion :> sublayout) where
253+instance HasClient t m sublayout tag
254+ => HasClient t m (HttpVersion :> sublayout) tag where
257255
258− type Client t m (HttpVersion :> sublayout) =
259− Client t m sublayout
256+ type Client t m (HttpVersion :> sublayout) tag =
257+ Client t m sublayout tag
260258
261− clientWithRoute Proxy q =
262− clientWithRoute (Proxy :: Proxy sublayout) q
259+ clientWithRoute Proxy q t =
260+ clientWithRoute (Proxy :: Proxy sublayout) q t
263261
264262
265263
@@ -289,15 +287,15 @@ instance HasClient t m sublayout
289287-- > -- then you can just use "getBooksBy" to query that endpoint.
290288-- > -- 'getBooksBy Nothing' for all books
291289-- > -- 'getBooksBy (Just "Isaac Asimov")' to get all books by Isaac Asimov
292−instance (KnownSymbol sym, ToHttpApiData a, HasClient t m sublayout, Reflex t)
293− => HasClient t m (QueryParam sym a :> sublayout) where
290+instance (KnownSymbol sym, ToHttpApiData a, HasClient t m sublayout tag, Reflex t)
291+ => HasClient t m (QueryParam sym a :> sublayout) tag where
294292
295− type Client t m (QueryParam sym a :> sublayout) =
296− Dynamic t (QParam a) -> Client t m sublayout
293+ type Client t m (QueryParam sym a :> sublayout) tag =
294+ Dynamic t (QParam a) -> Client t m sublayout tag
297295
298296 -- if mparam = Nothing, we don't add it to the query string
299− clientWithRoute Proxy q req baseurl mparam =
300− clientWithRoute (Proxy :: Proxy sublayout) q
297+ clientWithRoute Proxy q t req baseurl mparam =
298+ clientWithRoute (Proxy :: Proxy sublayout) q t
301299 (req {qParams = paramPair : qParams req}) baseurl
302300
303301 where pname = symbolVal (Proxy :: Proxy sym)
@@ -336,14 +334,14 @@ instance (KnownSymbol sym, ToHttpApiData a, HasClient t m sublayout, Reflex t)
336334-- > -- 'getBooksBy []' for all books
337335-- > -- 'getBooksBy ["Isaac Asimov", "Robert A. Heinlein"]'
338336-- > -- to get all books by Asimov and Heinlein
339−instance (KnownSymbol sym, ToHttpApiData a, HasClient t m sublayout, Reflex t)
340− => HasClient t m (QueryParams sym a :> sublayout) where
337+instance (KnownSymbol sym, ToHttpApiData a, HasClient t m sublayout tag, Reflex t)
338+ => HasClient t m (QueryParams sym a :> sublayout) tag where
341339
342− type Client t m (QueryParams sym a :> sublayout) =
343− Dynamic t [a] -> Client t m sublayout
340+ type Client t m (QueryParams sym a :> sublayout) tag =
341+ Dynamic t [a] -> Client t m sublayout tag
344342
345− clientWithRoute Proxy q req baseurl paramlist =
346− clientWithRoute (Proxy :: Proxy sublayout) q req' baseurl
343+ clientWithRoute Proxy q t req baseurl paramlist =
344+ clientWithRoute (Proxy :: Proxy sublayout) q t req' baseurl
347345
348346 where req' = req { qParams = (T.pack pname, params') : qParams req }
349347 pname = symbolVal (Proxy :: Proxy sym)
@@ -376,14 +374,14 @@ instance (KnownSymbol sym, ToHttpApiData a, HasClient t m sublayout, Reflex t)
376374-- > -- 'getBooksBy True' to only get _already published_ books
377375
378376-- TODO Bring back
379−instance (KnownSymbol sym, HasClient t m sublayout, Reflex t)
380− => HasClient t m (QueryFlag sym :> sublayout) where
377+instance (KnownSymbol sym, HasClient t m sublayout tag, Reflex t)
378+ => HasClient t m (QueryFlag sym :> sublayout) tag where
381379
382− type Client t m (QueryFlag sym :> sublayout) =
383− Dynamic t Bool -> Client t m sublayout
380+ type Client t m (QueryFlag sym :> sublayout) tag =
381+ Dynamic t Bool -> Client t m sublayout tag
384382
385− clientWithRoute Proxy q req baseurl flag =
386− clientWithRoute (Proxy :: Proxy sublayout) q req' baseurl
383+ clientWithRoute Proxy q t req baseurl flag =
384+ clientWithRoute (Proxy :: Proxy sublayout) q t req' baseurl
387385
388386 where req' = req { qParams = thisPair : qParams req }
389387 thisPair = (T.pack pName, QueryPartFlag flag) :: (Text, QueryPart t)
@@ -391,36 +389,26 @@ instance (KnownSymbol sym, HasClient t m sublayout, Reflex t)
391389
392390
393391
394−-- | Pick a 'Method' and specify where the server you want to query is. You get
395−-- back the full `Response`.
396−-- TODO redo
397−instance SupportsServantReflex t m => HasClient t m Raw where
398− type Client t m Raw = Dynamic t (Either Text (XhrRequest ()))
399− -> Event t ()
400− -> m (Event t (ReqResult ()))
401−
402− -- clientWithRoute :: Proxy Raw -> Proxy m -> Req -> BaseUrl -> Client t m Raw
403− clientWithRoute _ _ _ baseurl xhrs triggers = do
404− let xhrs' = liftA2 (\x path -> case x of
405− Left e -> Left e
406− Right jx -> Right $ jx {_xhrRequest_url = path
407− <> _xhrRequest_url jx})
408− xhrs
409− (showBaseUrl <$> baseurl)
410− reqs = tagPromptlyDyn xhrs' triggers
411− okReq = fmapMaybe hush reqs
412− badReq = fmapMaybe tattle reqs
413− resps <- performRequestAsync okReq
414− return $ leftmost [fmap (ResponseSuccess () ) resps
415− ,fmap RequestFailure badReq]
392+-- | Send a raw 'XhrRequest ()' directly to 'baseurl'
393+instance SupportsServantReflex t m => HasClient t m Raw tag where
394+ type Client t m Raw tag = Dynamic t (Either Text (XhrRequest ()))
395+ -> Event t tag
396+ -> m (Event t (tag, ReqResult ()))
416397
398+ clientWithRoute _ _ _ _ baseurl xhrs triggers = do
417399
400+ let xhrs' = liftA2 (\x path -> case x of
401+ Left e -> Left e
402+ Right jx -> Right $ jx { _xhrRequest_url = path <> _xhrRequest_url jx }
403+ ) xhrs (showBaseUrl <$> baseurl)
404+ xhrs'' = attachPromptlyDynWith (flip (,)) xhrs' triggers :: Event t (tag, Either Text (XhrRequest ()))
405+ badReq = fmapMaybe (\(t,x) -> either (Just . (t,)) (const Nothing) x) xhrs'' :: Event t (tag, Text)
406+ okReq = fmapMaybe (\(t,x) -> either (const Nothing) (Just . (t,)) x) xhrs'' :: Event t (tag, XhrRequest ())
418407
419−hush :: Either e a -> Maybe a
420−hush = either (const Nothing) Just
408+ resps <- performRequestsAsync okReq
409+ return $ leftmost [ fmap (ResponseSuccess ()) <$> resps
410+ , fmap (RequestFailure) <$> badReq ]
421411
422−tattle :: Either e a -> Maybe e
423−tattle = either Just (const Nothing)
424412
425413-- | If you use a 'ReqBody' in one of your endpoints in your API,
426414-- the corresponding querying function will automatically take
@@ -442,14 +430,14 @@ tattle = either Just (const Nothing)
442430-- > where host = BaseUrl Http "localhost" 8080
443431-- > -- then you can just use "addBook" to query that endpoint
444432
445−instance (MimeRender ct a, HasClient t m sublayout, Reflex t)
446− => HasClient t m (ReqBody (ct ': cts) a :> sublayout) where
433+instance (MimeRender ct a, HasClient t m sublayout tag, Reflex t)
434+ => HasClient t m (ReqBody (ct ': cts) a :> sublayout) tag where
447435
448− type Client t m (ReqBody (ct ': cts) a :> sublayout) =
449− Dynamic t (Either Text a) -> Client t m sublayout
436+ type Client t m (ReqBody (ct ': cts) a :> sublayout) tag =
437+ Dynamic t (Either Text a) -> Client t m sublayout tag
450438
451− clientWithRoute Proxy q req baseurl body =
452− clientWithRoute (Proxy :: Proxy sublayout) q req' baseurl
439+ clientWithRoute Proxy q t req baseurl body =
440+ clientWithRoute (Proxy :: Proxy sublayout) q t req' baseurl
453441 where req' = req { reqBody = bodyBytesCT }
454442 ctProxy = Proxy :: Proxy ct
455443 ctString = T.pack $ show $ contentType ctProxy
@@ -460,47 +448,47 @@ instance (MimeRender ct a, HasClient t m sublayout, Reflex t)
460448
461449
462450-- | Make the querying function append @path@ to the request path.
463−instance (KnownSymbol path, HasClient t m sublayout, Reflex t) => HasClient t m (path :> sublayout) where
464− type Client t m (path :> sublayout) = Client t m sublayout
451+instance (KnownSymbol path, HasClient t m sublayout tag, Reflex t) => HasClient t m (path :> sublayout) tag where
452+ type Client t m (path :> sublayout) tag = Client t m sublayout tag
465453
466− clientWithRoute Proxy q req baseurl =
467− clientWithRoute (Proxy :: Proxy sublayout) q
454+ clientWithRoute Proxy q t req baseurl =
455+ clientWithRoute (Proxy :: Proxy sublayout) q t
468456 (prependToPathParts (pure (Right $ T.pack p)) req)
469457 baseurl
470458
471459 where p = symbolVal (Proxy :: Proxy path)
472460
473461
474−instance HasClient t m api => HasClient t m (Vault :> api) where
475− type Client t m (Vault :> api) = Client t m api
462+instance HasClient t m api tag => HasClient t m (Vault :> api) tag where
463+ type Client t m (Vault :> api) tag = Client t m api tag
476464
477− clientWithRoute Proxy q req baseurl =
478− clientWithRoute (Proxy :: Proxy api) q req baseurl
465+ clientWithRoute Proxy q t req baseurl =
466+ clientWithRoute (Proxy :: Proxy api) q t req baseurl
479467
480468
481−instance HasClient t m api => HasClient t m (RemoteHost :> api) where
482− type Client t m (RemoteHost :> api) = Client t m api
469+instance HasClient t m api tag => HasClient t m (RemoteHost :> api) tag where
470+ type Client t m (RemoteHost :> api) tag = Client t m api tag
483471
484− clientWithRoute Proxy q req baseurl =
485− clientWithRoute (Proxy :: Proxy api) q req baseurl
472+ clientWithRoute Proxy q t req baseurl =
473+ clientWithRoute (Proxy :: Proxy api) q t req baseurl
486474
487475
488476
489−instance HasClient t m api => HasClient t m (IsSecure :> api) where
490− type Client t m (IsSecure :> api) = Client t m api
477+instance HasClient t m api tag => HasClient t m (IsSecure :> api) tag where
478+ type Client t m (IsSecure :> api) tag = Client t m api tag
491479
492− clientWithRoute Proxy q req baseurl =
493− clientWithRoute (Proxy :: Proxy api) q req baseurl
480+ clientWithRoute Proxy q t req baseurl =
481+ clientWithRoute (Proxy :: Proxy api) q t req baseurl
494482
495483
496−instance (HasClient t m api, Reflex t)
497− => HasClient t m (BasicAuth realm usr :> api) where
484+instance (HasClient t m api tag, Reflex t)
485+ => HasClient t m (BasicAuth realm usr :> api) tag where
498486
499− type Client t m (BasicAuth realm usr :> api) = Dynamic t (Maybe BasicAuthData)
500− -> Client t m api
487+ type Client t m (BasicAuth realm usr :> api) tag = Dynamic t (Maybe BasicAuthData)
488+ -> Client t m api tag
501489
502− clientWithRoute Proxy q req baseurl authdata =
503− clientWithRoute (Proxy :: Proxy api) q req' baseurl
490+ clientWithRoute Proxy q t req baseurl authdata =
491+ clientWithRoute (Proxy :: Proxy api) q t req' baseurl
504492 where
505493 req' = req { authData = Just authdata }
506494
src/Servant/Reflex/Multi.hs+108−103
@@ -20,6 +20,8 @@ module Servant.Reflex.Multi
2020
2121------------------------------------------------------------------------------
2222import Control.Applicative
23+import Control.Arrow (second)
24+import Data.Functor.Compose
2325import Data.Monoid ((<>))
2426import qualified Data.Set as Set
2527import qualified Data.Text.Encoding as E
@@ -43,7 +45,7 @@ import Reflex.Dom (Dynamic, Event, Reflex,
4345 XhrRequest(..),
4446 XhrResponseHeaders(..),
4547 XhrResponse(..), ffor, fmapMaybe,
46− leftmost, performRequestAsync,
48+ leftmost, performRequestAsync, attachPromptlyDynWith,
4749 tagPromptlyDyn )
4850------------------------------------------------------------------------------
4951import Servant.Common.BaseUrl (BaseUrl(..), Scheme(..), baseUrlWidget,
@@ -63,28 +65,28 @@ import Servant.Common.Req (Req, ReqResult(..), QParam(..),
6365 qParams)
6466import Servant.Reflex (BuildHeaderKeysTo(..), toHeaders)
6567
66−clientA :: (HasClientMulti t m layout f, Applicative f)
67− => Proxy layout -> Proxy m -> Proxy f -> Dynamic t BaseUrl -> ClientMulti t m layout f
68−clientA p q f baseurl = clientWithRouteMulti p q f (pure defReq) baseurl
68+clientA :: (HasClientMulti t m layout f tag, Applicative f)
69+ => Proxy layout -> Proxy m -> Proxy f -> Proxy tag -> Dynamic t BaseUrl -> ClientMulti t m layout f tag
70+clientA p q f tag baseurl = clientWithRouteMulti p q f tag (pure defReq) baseurl
6971
70−class HasClientMulti t m layout f where
71− type ClientMulti t m layout f :: *
72− clientWithRouteMulti :: Proxy layout -> Proxy m -> Proxy f -> f (Req t) -> Dynamic t BaseUrl -> ClientMulti t m layout f
72+class HasClientMulti t m layout f (tag :: *) where
73+ type ClientMulti t m layout f tag :: *
74+ clientWithRouteMulti :: Proxy layout -> Proxy m -> Proxy f -> Proxy tag -> f (Req t) -> Dynamic t BaseUrl -> ClientMulti t m layout f tag
7375
74−instance (HasClientMulti t m a f, HasClientMulti t m b f) => HasClientMulti t m (a :<|> b) f where
75− type ClientMulti t m (a :<|> b) f = ClientMulti t m a f :<|> ClientMulti t m b f
76− clientWithRouteMulti Proxy q f reqs baseurl =
77− clientWithRouteMulti (Proxy :: Proxy a) q f reqs baseurl :<|>
78− clientWithRouteMulti (Proxy :: Proxy b) q f reqs baseurl
76+instance (HasClientMulti t m a f tag, HasClientMulti t m b f tag) => HasClientMulti t m (a :<|> b) f tag where
77+ type ClientMulti t m (a :<|> b) f tag = ClientMulti t m a f tag :<|> ClientMulti t m b f tag
78+ clientWithRouteMulti Proxy q f tag reqs baseurl =
79+ clientWithRouteMulti (Proxy :: Proxy a) q f tag reqs baseurl :<|>
80+ clientWithRouteMulti (Proxy :: Proxy b) q f tag reqs baseurl
7981
8082
81−instance (SupportsServantReflex t m, ToHttpApiData a, HasClientMulti t m sublayout f, Applicative f)
82− => HasClientMulti t m (Capture capture a :> sublayout) f where
83+instance (SupportsServantReflex t m, ToHttpApiData a, HasClientMulti t m sublayout f tag, Applicative f)
84+ => HasClientMulti t m (Capture capture a :> sublayout) f tag where
8385
84− type ClientMulti t m (Capture capture a :> sublayout) f =
85− f (Dynamic t (Either Text a)) -> ClientMulti t m sublayout f
86+ type ClientMulti t m (Capture capture a :> sublayout) f tag =
87+ f (Dynamic t (Either Text a)) -> ClientMulti t m sublayout f tag
8688
87− clientWithRouteMulti l q f reqs baseurl vals = clientWithRouteMulti (Proxy :: Proxy sublayout) q f reqs' baseurl
89+ clientWithRouteMulti l q f tag reqs baseurl vals = clientWithRouteMulti (Proxy :: Proxy sublayout) q f tag reqs' baseurl
8890 where
8991 reqs' = prependToPathParts <$> ps <*> reqs
9092 ps = (fmap . fmap . fmap) toUrlPiece vals
@@ -92,16 +94,17 @@ instance (SupportsServantReflex t m, ToHttpApiData a, HasClientMulti t m sublayo
9294-- VERB (Returning content) --
9395instance {-# OVERLAPPABLE #-}
9496 -- Note [Non-Empty Content Types]
95− (MimeUnrender ct a, ReflectMethod method, cts' ~ (ct ': cts),
97+ (MimeUnrender ct a,
98+ ReflectMethod method, cts' ~ (ct ': cts),
9699 SupportsServantReflex t m,
97100 Applicative f,
98101 Traversable f
99− ) => HasClientMulti t m (Verb method status cts' a) f where
102+ ) => HasClientMulti t m (Verb method status cts' a) f tag where
100103
101− type ClientMulti t m (Verb method status cts' a) f =
102− Event t () -> m (Event t (f (ReqResult a)))
104+ type ClientMulti t m (Verb method status cts' a) f tag =
105+ Event t tag -> m (Event t (tag, f (ReqResult a)))
103106
104− clientWithRouteMulti _ _ f reqs baseurl =
107+ clientWithRouteMulti _ _ f tag reqs baseurl =
105108 performRequestsCT (Proxy :: Proxy ct) method reqs' baseurl
106109 where method = E.decodeUtf8 $ reflectMethod (Proxy :: Proxy method)
107110 reqs' = (\r -> r { reqMethod = method }) <$> reqs
@@ -109,12 +112,12 @@ instance {-# OVERLAPPABLE #-}
109112-- -- VERB (No content) --
110113instance {-# OVERLAPPING #-}
111114 (ReflectMethod method, SupportsServantReflex t m, Traversable f) =>
112− HasClientMulti t m (Verb method status cts NoContent) f where
113− type ClientMulti t m (Verb method status cts NoContent) f =
114− Event t () -> m (Event t (f (ReqResult NoContent)))
115+ HasClientMulti t m (Verb method status cts NoContent) f tag where
116+ type ClientMulti t m (Verb method status cts NoContent) f tag =
117+ Event t tag -> m (Event t (tag, f (ReqResult NoContent)))
115118 -- TODO: how to access input types here?
116119 -- ExceptT ServantError IO NoContent
117− clientWithRouteMulti Proxy _ _ req baseurl =
120+ clientWithRouteMulti Proxy _ _ tag req baseurl =
118121 performRequestsNoBody method req baseurl
119122 where method = E.decodeUtf8 $ reflectMethod (Proxy :: Proxy method)
120123
@@ -124,12 +127,12 @@ instance {-# OVERLAPPABLE #-}
124127 ReflectMethod method, cts' ~ (ct ': cts),
125128 SupportsServantReflex t m,
126129 Traversable f
127− ) => HasClientMulti t m (Verb method status cts' (Headers ls a)) f where
128− type ClientMulti t m (Verb method status cts' (Headers ls a)) f =
129− Event t () -> m (Event t (f (ReqResult (Headers ls a))))
130− clientWithRouteMulti Proxy _ _ reqs baseurl = do
130+ ) => HasClientMulti t m (Verb method status cts' (Headers ls a)) f tag where
131+ type ClientMulti t m (Verb method status cts' (Headers ls a)) f tag =
132+ Event t tag -> m (Event t (tag, f (ReqResult (Headers ls a))))
133+ clientWithRouteMulti Proxy _ _ _ reqs baseurl triggers = do
131134 let method = E.decodeUtf8 $ reflectMethod (Proxy :: Proxy method)
132− resp <- performRequestsCT (Proxy :: Proxy ct) method reqs' baseurl
135+ resp <- performRequestsCT (Proxy :: Proxy ct) method reqs' baseurl triggers :: m (Event t (tag, f (ReqResult a)))
133136 return $ (fmap . fmap) toHeaders <$> resp
134137 where reqs' = ffor reqs $ \r -> r { respHeaders =
135138 OnlyHeaders (Set.fromList (buildHeaderKeysTo (Proxy :: Proxy ls)))
@@ -142,12 +145,12 @@ instance {-# OVERLAPPABLE #-}
142145 ReflectMethod method,
143146 SupportsServantReflex t m,
144147 Traversable f
145− ) => HasClientMulti t m (Verb method status cts (Headers ls NoContent)) f where
146− type ClientMulti t m (Verb method status cts (Headers ls NoContent)) f
147− = Event t () -> m (Event t (f (ReqResult (Headers ls NoContent))))
148− clientWithRouteMulti Proxy _ _ reqs baseurl = do
148+ ) => HasClientMulti t m (Verb method status cts (Headers ls NoContent)) f tag where
149+ type ClientMulti t m (Verb method status cts (Headers ls NoContent)) f tag
150+ = Event t tag -> m (Event t (tag, f (ReqResult (Headers ls NoContent))))
151+ clientWithRouteMulti Proxy _ _ _ reqs baseurl triggers = do
149152 let method = E.decodeUtf8 $ reflectMethod (Proxy :: Proxy method)
150− resp <- performRequestsNoBody method reqs' baseurl
153+ resp <- performRequestsNoBody method reqs' baseurl triggers
151154 return $ (fmap . fmap) toHeaders <$> resp
152155 where reqs' = ffor reqs $ \req ->
153156 req {respHeaders = OnlyHeaders (Set.fromList
@@ -157,18 +160,18 @@ instance {-# OVERLAPPABLE #-}
157160
158161instance (KnownSymbol sym,
159162 ToHttpApiData a,
160− HasClientMulti t m sublayout f,
163+ HasClientMulti t m sublayout f tag,
161164 SupportsServantReflex t m,
162165 Traversable f,
163166 Applicative f)
164− => HasClientMulti t m (Header sym a :> sublayout) f where
167+ => HasClientMulti t m (Header sym a :> sublayout) f tag where
165168
166− type ClientMulti t m (Header sym a :> sublayout) f =
167− f (Dynamic t (Either Text a)) -> ClientMulti t m sublayout f
169+ type ClientMulti t m (Header sym a :> sublayout) f tag =
170+ f (Dynamic t (Either Text a)) -> ClientMulti t m sublayout f tag
168171
169− clientWithRouteMulti Proxy f q reqs baseurl eVals =
172+ clientWithRouteMulti Proxy f q tag reqs baseurl eVals =
170173 clientWithRouteMulti (Proxy :: Proxy sublayout) f
171− q
174+ q tag
172175 reqs'
173176 baseurl
174177 where hname = T.pack $ symbolVal (Proxy :: Proxy sym)
@@ -176,26 +179,26 @@ instance (KnownSymbol sym,
176179 <$> eVals <*> reqs
177180
178181
179−instance HasClientMulti t m sublayout f
180− => HasClientMulti t m (HttpVersion :> sublayout) f where
182+instance HasClientMulti t m sublayout f tag
183+ => HasClientMulti t m (HttpVersion :> sublayout) f tag where
181184
182− type ClientMulti t m (HttpVersion :> sublayout) f =
183− ClientMulti t m sublayout f
185+ type ClientMulti t m (HttpVersion :> sublayout) f tag =
186+ ClientMulti t m sublayout f tag
184187
185− clientWithRouteMulti Proxy q f =
186− clientWithRouteMulti (Proxy :: Proxy sublayout) q f
188+ clientWithRouteMulti Proxy q f tag =
189+ clientWithRouteMulti (Proxy :: Proxy sublayout) q f tag
187190
188191
189−instance (KnownSymbol sym, ToHttpApiData a, HasClientMulti t m sublayout f, Reflex t, Traversable f, Applicative f)
190− => HasClientMulti t m (QueryParam sym a :> sublayout) f where
192+instance (KnownSymbol sym, ToHttpApiData a, HasClientMulti t m sublayout f tag, Reflex t, Traversable f, Applicative f)
193+ => HasClientMulti t m (QueryParam sym a :> sublayout) f tag where
191194
192− type ClientMulti t m (QueryParam sym a :> sublayout) f =
193− f (Dynamic t (QParam a)) -> ClientMulti t m sublayout f
195+ type ClientMulti t m (QueryParam sym a :> sublayout) f tag =
196+ f (Dynamic t (QParam a)) -> ClientMulti t m sublayout f tag
194197
195198 -- if mparam = Nothing, we don't add it to the query string
196199 -- TODO: Check the above comment
197− clientWithRouteMulti Proxy q f reqs baseurl mparams =
198− clientWithRouteMulti (Proxy :: Proxy sublayout) q f
200+ clientWithRouteMulti Proxy q f tag reqs baseurl mparams =
201+ clientWithRouteMulti (Proxy :: Proxy sublayout) q f tag
199202 reqs' baseurl
200203
201204 where pname = symbolVal (Proxy :: Proxy sym)
@@ -207,17 +210,17 @@ instance (KnownSymbol sym, ToHttpApiData a, HasClientMulti t m sublayout f, Refl
207210
208211instance (KnownSymbol sym,
209212 ToHttpApiData a,
210− HasClientMulti t m sublayout f,
213+ HasClientMulti t m sublayout f tag,
211214 Reflex t,
212215 Traversable f,
213216 Applicative f)
214− => HasClientMulti t m (QueryParams sym a :> sublayout) f where
217+ => HasClientMulti t m (QueryParams sym a :> sublayout) f tag where
215218
216− type ClientMulti t m (QueryParams sym a :> sublayout) f =
217− f (Dynamic t [a]) -> ClientMulti t m sublayout f
219+ type ClientMulti t m (QueryParams sym a :> sublayout) f tag =
220+ f (Dynamic t [a]) -> ClientMulti t m sublayout f tag
218221
219− clientWithRouteMulti Proxy q f reqs baseurl paramlists =
220− clientWithRouteMulti (Proxy :: Proxy sublayout) q f reqs' baseurl
222+ clientWithRouteMulti Proxy q f tag reqs baseurl paramlists =
223+ clientWithRouteMulti (Proxy :: Proxy sublayout) q f tag reqs' baseurl
221224
222225 where req' l r = r { qParams = (T.pack pname, params' l) : qParams r }
223226 pname = symbolVal (Proxy :: Proxy sym)
@@ -227,17 +230,17 @@ instance (KnownSymbol sym,
227230
228231
229232instance (KnownSymbol sym,
230− HasClientMulti t m sublayout f,
233+ HasClientMulti t m sublayout f tag,
231234 Reflex t,
232235 Traversable f,
233236 Applicative f)
234− => HasClientMulti t m (QueryFlag sym :> sublayout) f where
237+ => HasClientMulti t m (QueryFlag sym :> sublayout) f tag where
235238
236− type ClientMulti t m (QueryFlag sym :> sublayout) f =
237− f (Dynamic t Bool) -> ClientMulti t m sublayout f
239+ type ClientMulti t m (QueryFlag sym :> sublayout) f tag =
240+ f (Dynamic t Bool) -> ClientMulti t m sublayout f tag
238241
239− clientWithRouteMulti Proxy q f reqs baseurl flags =
240− clientWithRouteMulti (Proxy :: Proxy sublayout) q f reqs' baseurl
242+ clientWithRouteMulti Proxy q f tag reqs baseurl flags =
243+ clientWithRouteMulti (Proxy :: Proxy sublayout) q f tag reqs' baseurl
241244
242245 where req' f req = req { qParams = thisPair f : qParams req }
243246 thisPair f = (T.pack pName, QueryPartFlag f) :: (Text, QueryPart t)
@@ -246,31 +249,33 @@ instance (KnownSymbol sym,
246249
247250
248251instance (SupportsServantReflex t m,
249− Traversable f) => HasClientMulti t m Raw f where
250− type ClientMulti t m Raw f = f (Dynamic t (Either Text (XhrRequest ())))
251− -> Event t ()
252− -> m (Event t (f (ReqResult ())))
253−
254− clientWithRouteMulti Proxy Proxy Proxy oldReqs baseurl (rawReqs) triggers = do
255− resps <- performSomeRequestsAsync (tagPromptlyDyn (sequence rawReqs) triggers )
256− return $ (fmap . fmap) aux resps
252+ Traversable f) => HasClientMulti t m Raw f tag where
253+ type ClientMulti t m Raw f tag = f (Dynamic t (Either Text (XhrRequest ())))
254+ -> Event t tag
255+ -> m (Event t (tag, f (ReqResult ())))
256+
257+ clientWithRouteMulti _ _ _ _ oldReqs baseurl rawReqs triggers = do
258+ let rawReqs' = sequence rawReqs :: Dynamic t (f (Either Text (XhrRequest ())))
259+ rawReqs'' = attachPromptlyDynWith (\fxhr t -> Compose (t, fxhr)) rawReqs' triggers
260+ resps <- fmap (second (fmap aux) . getCompose) <$> performSomeRequestsAsync rawReqs''
261+ return resps
257262 where
258263 aux (Right r) = ResponseSuccess () r
259264 aux (Left e) = RequestFailure e
260265
261266
262267instance (MimeRender ct a,
263− HasClientMulti t m sublayout f,
268+ HasClientMulti t m sublayout f tag,
264269 Reflex t,
265270 Traversable f,
266271 Applicative f)
267− => HasClientMulti t m (ReqBody (ct ': cts) a :> sublayout) f where
272+ => HasClientMulti t m (ReqBody (ct ': cts) a :> sublayout) f tag where
268273
269− type ClientMulti t m (ReqBody (ct ': cts) a :> sublayout) f =
270− f (Dynamic t (Either Text a)) -> ClientMulti t m sublayout f
274+ type ClientMulti t m (ReqBody (ct ': cts) a :> sublayout) f tag =
275+ f (Dynamic t (Either Text a)) -> ClientMulti t m sublayout f tag
271276
272− clientWithRouteMulti Proxy q f reqs baseurl bodies =
273− clientWithRouteMulti (Proxy :: Proxy sublayout) q f reqs' baseurl
277+ clientWithRouteMulti Proxy q f tag reqs baseurl bodies =
278+ clientWithRouteMulti (Proxy :: Proxy sublayout) q f tag reqs' baseurl
274279 where req' b r = r { reqBody = bodyBytesCT b }
275280 ctProxy = Proxy :: Proxy ct
276281 ctString = T.pack $ show $ contentType ctProxy
@@ -281,48 +286,48 @@ instance (MimeRender ct a,
281286
282287
283288instance (KnownSymbol path,
284− HasClientMulti t m sublayout f,
289+ HasClientMulti t m sublayout f tag,
285290 Reflex t,
286− Functor f) => HasClientMulti t m (path :> sublayout) f where
287− type ClientMulti t m (path :> sublayout) f = ClientMulti t m sublayout f
291+ Functor f) => HasClientMulti t m (path :> sublayout) f tag where
292+ type ClientMulti t m (path :> sublayout) f tag = ClientMulti t m sublayout f tag
288293
289− clientWithRouteMulti Proxy q f reqs baseurl =
290− clientWithRouteMulti (Proxy :: Proxy sublayout) q f
294+ clientWithRouteMulti Proxy q f tag reqs baseurl =
295+ clientWithRouteMulti (Proxy :: Proxy sublayout) q f tag
291296 (prependToPathParts (pure (Right $ T.pack p)) <$> reqs)
292297 baseurl
293298
294299 where p = symbolVal (Proxy :: Proxy path)
295300
296301
297−instance HasClientMulti t m api f => HasClientMulti t m (Vault :> api) f where
298− type ClientMulti t m (Vault :> api) f = ClientMulti t m api f
302+instance HasClientMulti t m api f tag => HasClientMulti t m (Vault :> api) f tag where
303+ type ClientMulti t m (Vault :> api) f tag = ClientMulti t m api f tag
299304
300− clientWithRouteMulti Proxy q f reqs baseurl =
301− clientWithRouteMulti (Proxy :: Proxy api) q f reqs baseurl
305+ clientWithRouteMulti Proxy q f tag reqs baseurl =
306+ clientWithRouteMulti (Proxy :: Proxy api) q f tag reqs baseurl
302307
303308
304−instance HasClientMulti t m api f => HasClientMulti t m (RemoteHost :> api) f where
305− type ClientMulti t m (RemoteHost :> api) f = ClientMulti t m api f
309+instance HasClientMulti t m api f tag => HasClientMulti t m (RemoteHost :> api) f tag where
310+ type ClientMulti t m (RemoteHost :> api) f tag = ClientMulti t m api f tag
306311
307− clientWithRouteMulti Proxy q f reqs baseurl =
308− clientWithRouteMulti (Proxy :: Proxy api) q f reqs baseurl
312+ clientWithRouteMulti Proxy q f tag reqs baseurl =
313+ clientWithRouteMulti (Proxy :: Proxy api) q f tag reqs baseurl
309314
310315
311−instance HasClientMulti t m api f => HasClientMulti t m (IsSecure :> api) f where
312− type ClientMulti t m (IsSecure :> api) f = ClientMulti t m api f
316+instance HasClientMulti t m api f tag => HasClientMulti t m (IsSecure :> api) f tag where
317+ type ClientMulti t m (IsSecure :> api) f tag = ClientMulti t m api f tag
313318
314− clientWithRouteMulti Proxy q f reqs baseurl =
315− clientWithRouteMulti (Proxy :: Proxy api) q f reqs baseurl
319+ clientWithRouteMulti Proxy q f tag reqs baseurl =
320+ clientWithRouteMulti (Proxy :: Proxy api) q f tag reqs baseurl
316321
317322
318−instance (HasClientMulti t m api f, Reflex t, Traversable f, Applicative f)
319− => HasClientMulti t m (BasicAuth realm usr :> api) f where
323+instance (HasClientMulti t m api f tag, Reflex t, Traversable f, Applicative f)
324+ => HasClientMulti t m (BasicAuth realm usr :> api) f tag where
320325
321− type ClientMulti t m (BasicAuth realm usr :> api) f = f (Dynamic t (Maybe BasicAuthData))
322− -> ClientMulti t m api f
326+ type ClientMulti t m (BasicAuth realm usr :> api) f tag = f (Dynamic t (Maybe BasicAuthData))
327+ -> ClientMulti t m api f tag
323328
324− clientWithRouteMulti Proxy q f reqs baseurl authdatas =
325− clientWithRouteMulti (Proxy :: Proxy api) q f reqs' baseurl
329+ clientWithRouteMulti Proxy q f tag reqs baseurl authdatas =
330+ clientWithRouteMulti (Proxy :: Proxy api) q f tag reqs' baseurl
326331 where
327332 req' a r = r { authData = Just a }
328333 reqs' = req' <$> authdatas <*> reqs