@@ -1,3 +1,4 @@
1+{-# LANGUAGE AllowAmbiguousTypes #-}
12{-# LANGUAGE CPP #-}
23{-# LANGUAGE DataKinds #-}
34{-# LANGUAGE FlexibleContexts #-}
@@ -18,12 +19,14 @@
1819-- API.
1920module Servant.Reflex
2021 ( client
22+ , BuildHeaderKeysTo(..)
23+ , toHeaders
2124 , HasClient(..)
2225 , module Servant.Common.Req
2326 , module Servant.Common.BaseUrl
2427 ) where
2528
26−-------------------------------------------------------------------------------
29+------------------------------------------------------------------------------
2730import Control.Applicative
2831import Data.Monoid ((<>))
2932import qualified Data.Set as Set
@@ -43,6 +46,14 @@ import Servant.API ((:<|>)(..),(:>), BasicAuth,
4346 QueryParams, Raw, ReflectMethod(..),
4447 RemoteHost, ReqBody,
4548 ToHttpApiData(..), Vault, Verb)
49+
50+import Reflex.Dom (Dynamic, Event, Reflex,
51+ XhrRequest(..),
52+ XhrResponseHeaders(..),
53+ XhrResponse(..), ffor, fmapMaybe,
54+ leftmost, performRequestAsync,
55+ tagPromptlyDyn )
56+------------------------------------------------------------------------------
4657import Servant.Common.BaseUrl (BaseUrl(..), Scheme(..), baseUrlWidget,
4758 showBaseUrl,
4859 SupportsServantReflex)
@@ -50,17 +61,14 @@ import Servant.Common.Req (Req, ReqResult(..), QParam(..),
5061 QueryPart(..), addHeader, authData,
5162 defReq, prependToPathParts,
5263 performRequestCT,
64+ performRequestsCT,
5365 performRequestNoBody,
66+ performRequestsNoBody,
67+ performSomeRequestsAsync,
5468 qParamToQueryPart, reqBody,
5569 reqSuccess, reqFailure,
5670 reqMethod, respHeaders, response,
5771 qParams)
58−import Reflex.Dom (Dynamic, Event, Reflex,
59− XhrRequest(..),
60− XhrResponseHeaders(..),
61− XhrResponse(..), ffor, fmapMaybe,
62− leftmost, performRequestAsync,
63− tagPromptlyDyn )
6472
6573-- * Accessing APIs as a Client
6674
@@ -81,6 +89,7 @@ client :: (HasClient t m layout)
8189 => Proxy layout -> Proxy m -> Dynamic t BaseUrl -> Client t m layout
8290client p q baseurl = clientWithRoute p q defReq baseurl
8391
92+
8493-- | This class lets us define how each API combinator
8594-- influences the creation of an HTTP request. It's mostly
8695-- an internal class, you can just use 'client'.
@@ -91,10 +100,12 @@ class HasClient t m layout where
91100
92101instance (HasClient t m a, HasClient t m b) => HasClient t m (a :<|> b) where
93102 type Client t m (a :<|> b) = Client t m a :<|> Client t m b
103+
94104 clientWithRoute Proxy q req baseurl =
95105 clientWithRoute (Proxy :: Proxy a) q req baseurl :<|>
96106 clientWithRoute (Proxy :: Proxy b) q req baseurl
97107
108+
98109-- Capture. Example:
99110-- > type MyApi = "books" :> Capture "isbn" Text :> Get '[JSON] Book
100111-- >
@@ -106,6 +117,7 @@ instance (HasClient t m a, HasClient t m b) => HasClient t m (a :<|> b) where
106117-- -> Event t ()
107118-- -> m (Event t (Either XhrError (Text, Book)))
108119-- > getBook = client myApi (constDyn host)
120+
109121instance (SupportsServantReflex t m, ToHttpApiData a, HasClient t m sublayout)
110122 => HasClient t m (Capture capture a :> sublayout) where
111123
@@ -117,9 +129,9 @@ instance (SupportsServantReflex t m, ToHttpApiData a, HasClient t m sublayout)
117129 q
118130 (prependToPathParts p req)
119131 baseurl
120−
121132 where p = (fmap . fmap) (toUrlPiece) val
122133
134+
123135-- VERB (Returning content) --
124136instance {-# OVERLAPPABLE #-}
125137 -- Note [Non-Empty Content Types]
@@ -134,6 +146,9 @@ instance {-# OVERLAPPABLE #-}
134146 where method = E.decodeUtf8 $ reflectMethod (Proxy :: Proxy method)
135147 req' = req { reqMethod = method }
136148
149+
150+
151+
137152-- -- VERB (No content) --
138153instance {-# OVERLAPPING #-}
139154 (ReflectMethod method, SupportsServantReflex t m) =>
@@ -146,6 +161,7 @@ instance {-# OVERLAPPING #-}
146161 performRequestNoBody method req baseurl
147162 where method = E.decodeUtf8 $ reflectMethod (Proxy :: Proxy method)
148163
164+
149165toHeaders :: BuildHeadersTo ls => ReqResult a -> ReqResult (Headers ls a)
150166toHeaders r =
151167 let toBS = E.encodeUtf8
@@ -186,6 +202,7 @@ instance {-# OVERLAPPABLE #-}
186202 OnlyHeaders (Set.fromList (buildHeaderKeysTo (Proxy :: Proxy ls)))
187203 }
188204
205+
189206-- HEADERS Verb (No content) --
190207instance {-# OVERLAPPABLE #-}
191208 ( BuildHeadersTo ls, BuildHeaderKeysTo ls, ReflectMethod method,
@@ -202,6 +219,7 @@ instance {-# OVERLAPPABLE #-}
202219 }
203220
204221
222+
205223-- HEADER
206224-- > newtype Referer = Referer { referrer :: Text }
207225-- > deriving (Eq, Show, Generic, FromText, ToHttpApiData)
@@ -229,6 +247,9 @@ instance (KnownSymbol sym, ToHttpApiData a,
229247 baseurl
230248 where hname = T.pack $ symbolVal (Proxy :: Proxy sym)
231249
250+
251+
252+
232253-- | Using a 'HttpVersion' combinator in your API doesn't affect the client
233254-- functions.
234255instance HasClient t m sublayout
@@ -241,6 +262,7 @@ instance HasClient t m sublayout
241262 clientWithRoute (Proxy :: Proxy sublayout) q
242263
243264
265+
244266-- | If you use a 'QueryParam' in one of your endpoints in your API,
245267-- the corresponding querying function will automatically take
246268-- an additional argument of the type specified by your 'QueryParam',
@@ -284,6 +306,8 @@ instance (KnownSymbol sym, ToHttpApiData a, HasClient t m sublayout, Reflex t)
284306 p prm = QueryPartParam $ fmap qParamToQueryPart prm -- (fmap . fmap) (unpack . toQueryParam) prm
285307 paramPair = (T.pack pname, p mparam)
286308
309+
310+
287311-- | If you use a 'QueryParams' in one of your endpoints in your API,
288312-- the corresponding querying function will automatically take
289313-- an additional argument, a list of values of the type specified
@@ -327,6 +351,7 @@ instance (KnownSymbol sym, ToHttpApiData a, HasClient t m sublayout, Reflex t)
327351 paramlist
328352
329353
354+
330355-- | If you use a 'QueryFlag' in one of your endpoints in your API,
331356-- the corresponding querying function will automatically take
332357-- an additional 'Bool' argument.
@@ -365,6 +390,7 @@ instance (KnownSymbol sym, HasClient t m sublayout, Reflex t)
365390 pName = symbolVal (Proxy :: Proxy sym)
366391
367392
393+
368394-- | Pick a 'Method' and specify where the server you want to query is. You get
369395-- back the full `Response`.
370396-- TODO redo
@@ -389,6 +415,7 @@ instance SupportsServantReflex t m => HasClient t m Raw where
389415 ,fmap RequestFailure badReq]
390416
391417
418+
392419hush :: Either e a -> Maybe a
393420hush = either (const Nothing) Just
394421
@@ -430,6 +457,8 @@ instance (MimeRender ct a, HasClient t m sublayout, Reflex t)
430457 (\b -> (mimeRender ctProxy b, ctString))
431458 body
432459
460+
461+
433462-- | Make the querying function append @path@ to the request path.
434463instance (KnownSymbol path, HasClient t m sublayout, Reflex t) => HasClient t m (path :> sublayout) where
435464 type Client t m (path :> sublayout) = Client t m sublayout
@@ -441,24 +470,29 @@ instance (KnownSymbol path, HasClient t m sublayout, Reflex t) => HasClient t m
441470
442471 where p = symbolVal (Proxy :: Proxy path)
443472
473+
444474instance HasClient t m api => HasClient t m (Vault :> api) where
445475 type Client t m (Vault :> api) = Client t m api
446476
447477 clientWithRoute Proxy q req baseurl =
448478 clientWithRoute (Proxy :: Proxy api) q req baseurl
449479
480+
450481instance HasClient t m api => HasClient t m (RemoteHost :> api) where
451482 type Client t m (RemoteHost :> api) = Client t m api
452483
453484 clientWithRoute Proxy q req baseurl =
454485 clientWithRoute (Proxy :: Proxy api) q req baseurl
455486
487+
488+
456489instance HasClient t m api => HasClient t m (IsSecure :> api) where
457490 type Client t m (IsSecure :> api) = Client t m api
458491
459492 clientWithRoute Proxy q req baseurl =
460493 clientWithRoute (Proxy :: Proxy api) q req baseurl
461494
495+
462496instance (HasClient t m api, Reflex t)
463497 => HasClient t m (BasicAuth realm usr :> api) where
464498