git.iko.soy/typeable/servant
on master help sign in
Add parameter-supplying operator

Renamed `(/:)` to `(//)`, and used `(/:)` for supplying parameters to client functions. Should close #1442.

commitd81c8d99119d4cb896c59d81a98a37798b6aaa6a authorGaël Deest <gael.deest@tweag.io> dateFri 8 Oct 2021, 15:45 (5 years ago) parent6718752
4 files changed+55−13
servant-client-core/src/Servant/Client/Core/HasClient.hs+48−7 servant-client-core/src/Servant/Client/Core/Reexport.hs+1 servant-client/test/Servant/ClientTestUtils.hs+2−2 servant-client/test/Servant/GenericSpec.hs+4−4
servant-client-core/src/Servant/Client/Core/HasClient.hs+48−7
@@ -27,6 +27,7 @@ module Servant.Client.Core.HasClient (
2727 HasClient (..),
2828 EmptyClient (..),
2929 AsClientT,
30+ (//),
3031 (/:),
3132 foldMapUnion,
3233 matchUnion,
@@ -54,7 +55,8 @@ import Data.Sequence
5455 (fromList)
5556import qualified Data.Text as T
5657import Network.HTTP.Media
57− (MediaType, matches, parseAccept, (//))
58+ (MediaType, matches, parseAccept)
59+import qualified Network.HTTP.Media as Media
5860import qualified Data.Sequence as Seq
5961import Data.SOP.BasicFunctors
6062 (I (I), (:.:) (Comp))
@@ -873,9 +875,12 @@ instance
873875
874876#endif
875877
876−infixl 1 /:
878+infixl 1 //
879+infixl 2 /:
877880
878−-- | Convenience function for working with nested record-clients.
881+-- | Helper to make code using records of clients more readable.
882+--
883+-- Can be mixed with (/:) for supplying arguments.
879884--
880885-- Example:
881886--
@@ -899,10 +904,46 @@ infixl 1 /:
899904-- rootClient = client api
900905--
901906-- endpointClient :: ClientM Person
902−-- endpointClient = client /: subApi /: endpoint
907+-- endpointClient = client // subApi // endpoint
908+-- @@
909+(//) :: a -> (a -> b) -> b
910+x // f = f x
911+
912+-- | Convenience function for supplying arguments to client functions when
913+-- working with records of clients.
914+--
915+-- Intended to be use in conjunction with '(//)'.
916+--
917+-- Example:
918+--
919+-- @@
920+-- type Api = NamedAPI RootApi
921+--
922+-- data RootApi mode = RootApi
923+-- { subApi :: mode :- Capture "token" String :> NamedAPI SubApi
924+-- , hello :: mode :- Capture "name" String :> Get '[JSON] String
925+-- , …
926+-- } deriving Generic
927+--
928+-- data SubAmi mode = SubApi
929+-- { endpoint :: mode :- Get '[JSON] Person
930+-- , …
931+-- } deriving Generic
932+--
933+-- api :: Proxy API
934+-- api = Proxy
935+--
936+-- rootClient :: RootApi (AsClientT ClientM)
937+-- rootClient = client api
938+--
939+-- hello :: String -> ClientM String
940+-- hello name = rootClient // hello /: name
941+--
942+-- endpointClient :: ClientM Person
943+-- endpointClient = client // subApi /: "foobar123" // endpoint
903944-- @@
904−(/:) :: a -> (a -> b) -> b
905−x /: f = f x
945+(/:) :: (a -> b -> c) -> b -> a -> c
946+(/:) = flip
906947
907948
908949{- Note [Non-Empty Content Types]
@@ -928,7 +969,7 @@ for empty and one for non-empty lists).
928969checkContentTypeHeader :: RunClient m => Response -> m MediaType
929970checkContentTypeHeader response =
930971 case lookup "Content-Type" $ toList $ responseHeaders response of
931− Nothing -> return $ "application"//"octet-stream"
972+ Nothing -> return $ "application" Media.// "octet-stream"
932973 Just t -> case parseAccept t of
933974 Nothing -> throwClientError $ InvalidContentTypeHeader response
934975 Just t' -> return t'
servant-client-core/src/Servant/Client/Core/Reexport.hs+1
@@ -8,6 +8,7 @@ module Servant.Client.Core.Reexport
88 , foldMapUnion
99 , matchUnion
1010 , AsClientT
11+ , (//)
1112 , (/:)
1213
1314 -- * Response (for @Raw@)
servant-client/test/Servant/ClientTestUtils.hs+2−2
@@ -111,7 +111,7 @@ type TestHeaders = '[Header "X-Example1" Int, Header "X-Example2" String]
111111data RecordRoutes mode = RecordRoutes
112112 { version :: mode :- "version" :> Get '[JSON] Int
113113 , echo :: mode :- "echo" :> Capture "string" String :> Get '[JSON] String
114− , otherRoutes :: mode :- "other" :> NamedRoutes OtherRoutes
114+ , otherRoutes :: mode :- "other" :> Capture "someParam" Int :> NamedRoutes OtherRoutes
115115 } deriving Generic
116116
117117data OtherRoutes mode = OtherRoutes
@@ -246,7 +246,7 @@ server = serve api (
246246 :<|> RecordRoutes
247247 { version = pure 42
248248 , echo = pure
249− , otherRoutes = OtherRoutes
249+ , otherRoutes = \_ -> OtherRoutes
250250 { something = pure ["foo", "bar", "pweet"]
251251 }
252252 }
servant-client/test/Servant/GenericSpec.hs+4−4
@@ -19,7 +19,7 @@ module Servant.GenericSpec (spec) where
1919
2020import Test.Hspec
2121
22−import Servant.Client ((/:))
22+import Servant.Client ((//), (/:))
2323import Servant.ClientTestUtils
2424
2525spec :: Spec
@@ -31,7 +31,7 @@ genericSpec = beforeAll (startWaiApp server) $ afterAll endWaiApp $ do
3131 context "Record clients work as expected" $ do
3232
3333 it "Client functions return expected values" $ \(_,baseUrl) -> do
34− runClient (recordRoutes /: version) baseUrl `shouldReturn` Right 42
35− runClient (recordRoutes /: echo $ "foo") baseUrl `shouldReturn` Right "foo"
34+ runClient (recordRoutes // version) baseUrl `shouldReturn` Right 42
35+ runClient (recordRoutes // echo /: "foo") baseUrl `shouldReturn` Right "foo"
3636 it "Clients can be nested" $ \(_,baseUrl) -> do
37− runClient (recordRoutes /: otherRoutes /: something) baseUrl `shouldReturn` Right ["foo", "bar", "pweet"]
37+ runClient (recordRoutes // otherRoutes /: 42 // something) baseUrl `shouldReturn` Right ["foo", "bar", "pweet"]