@@ -12,7 +12,7 @@ module Servant.Client.Generic
12 , genericMkClientP
12 , genericMkClientP
15−import Generics.SOP (Code, Generic, I(..), NP(..), NS(Z), Rep, SOP(..), to)
15+import Generics.SOP (Code, Generic, I(..), NP(..), NS(Z), SOP(..), to)
16import Servant.API ((:<|>)(..))
16import Servant.API ((:<|>)(..))
17import Servant.Client (ClientM)
17import Servant.Client (ClientM)
@@ -38,7 +38,7 @@ import Servant.Client (ClientM)
38-- > , mkNestedClient :: Int -> NestedClient
38-- > , mkNestedClient :: Int -> NestedClient
39-- > } deriving GHC.Generic
39-- > } deriving GHC.Generic
41−-- > instance Generic.SOP.Generic APIClient
41+-- > instance Generics.SOP.Generic APIClient
42-- > instance (Client API ~ client) => ClientLike client APIClient
42-- > instance (Client API ~ client) => ClientLike client APIClient
44-- > data NestedClient = NestedClient
44-- > data NestedClient = NestedClient
@@ -46,11 +46,57 @@ import Servant.Client (ClientM)
46-- > , postBaz :: Maybe Char -> ClientM ()
46-- > , postBaz :: Maybe Char -> ClientM ()
47-- > } deriving GHC.Generic
47-- > } deriving GHC.Generic
49−-- > instance Generic.SOP.Generic NestedClient
49+-- > instance Generics.SOP.Generic NestedClient
50-- > instance (Client NestedAPI ~ client) => ClientLike client NestedClient
50-- > instance (Client NestedAPI ~ client) => ClientLike client NestedClient
52-- > mkAPIClient :: APIClient
52-- > mkAPIClient :: APIClient
53-- > mkAPIClient = mkClient (client (Proxy :: Proxy API))
53-- > mkAPIClient = mkClient (client (Proxy :: Proxy API))
55+-- By default, left-nested alternatives are expanded:
58+-- > = "foo" :> Capture "x" Int :> Get '[JSON] Int
59+-- > :<|> "bar" :> QueryParam "a" Char :> Post '[JSON] String
62+-- > = "baz" :> QueryParam "c" Char :> Post '[JSON] ()
64+-- > type API = API1 :<|> API2
66+-- > data APIClient = APIClient
67+-- > { getFoo :: Int -> ClientM Int
68+-- > , postBar :: Maybe Char -> ClientM String
69+-- > , postBaz :: Maybe Char -> ClientM ()
70+-- > } deriving GHC.Generic
72+-- > instance Generics.SOP.Generic APIClient
73+-- > instance (Client API ~ client) => ClientLike client APIClient
75+-- > mkAPIClient :: APIClient
76+-- > mkAPIClient = mkClient (client (Proxy :: Proxy API))
78+-- If you want to define client for @API1@ as a separate data structure,
79+-- you can use 'genericMkClientP':
81+-- > data APIClient1 = APIClient1
82+-- > { getFoo :: Int -> ClientM Int
83+-- > , postBar :: Maybe Char -> ClientM String
84+-- > } deriving GHC.Generic
86+-- > instance Generics.SOP.Generic APIClient1
87+-- > instance (Client API1 ~ client) => ClientLike client APIClient1
89+-- > data APIClient = APIClient
90+-- > { mkAPIClient1 :: APIClient1
91+-- > , postBaz :: Maybe Char -> ClientM ()
92+-- > } deriving GHC.Generic
94+-- > instance Generics.SOP.Generic APIClient
95+-- > instance (Client API ~ client) => ClientLike client APIClient where
96+-- > mkClient = genericMkClientP
98+-- > mkAPIClient :: APIClient
99+-- > mkAPIClient = mkClient (client (Proxy :: Proxy API))
54class ClientLike client custom where
100class ClientLike client custom where
55 mkClient :: client -> custom
101 mkClient :: client -> custom
56 default mkClient :: (Generic custom, Code custom ~ '[xs], GClientList client '[], GClientLikeL (ClientList client '[]) xs)
102 default mkClient :: (Generic custom, Code custom ~ '[xs], GClientList client '[], GClientLikeL (ClientList client '[]) xs)
@@ -100,11 +146,12 @@ instance {-# OVERLAPPABLE #-} (ClientList client acc ~ (client ': acc))
100 => GClientList client acc where
146 => GClientList client acc where
101 gClientList c acc = I c :* acc
147 gClientList c acc = I c :* acc
103−-- | Generate client structure from client type.
149+-- | Generate client structure from client type, expanding left-nested API (done by default).
104genericMkClientL :: (Generic custom, Code custom ~ '[xs], GClientList client '[], GClientLikeL (ClientList client '[]) xs)
150genericMkClientL :: (Generic custom, Code custom ~ '[xs], GClientList client '[], GClientLikeL (ClientList client '[]) xs)
105 => client -> custom
151 => client -> custom
106genericMkClientL = to . SOP . Z . gMkClientL . flip gClientList Nil
152genericMkClientL = to . SOP . Z . gMkClientL . flip gClientList Nil
154+-- | Generate client structure from client type, regarding left-nested API clients as separate data structures.
108genericMkClientP :: (Generic custom, Code custom ~ '[xs], GClientLikeP client xs)
155genericMkClientP :: (Generic custom, Code custom ~ '[xs], GClientLikeP client xs)
109 => client -> custom
156 => client -> custom
110genericMkClientP = to . SOP . Z . gMkClientP
157genericMkClientP = to . SOP . Z . gMkClientP