servant-matrix-param-0.3.3: src/Servant/MatrixParam/Client/Internal.hs
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module Servant.MatrixParam.Client.Internal where
import Data.Proxy
import qualified Data.Text as T
import GHC.TypeLits
import Servant.API
import Servant.Client
import Servant.Common.Req
import Servant.MatrixParam
instance
( HasClient (WMP mat :> api)
, KnownSymbol path
)
=> HasClient (WithMatrixParams path mat :> api) where
type Client (WithMatrixParams path mat :> api)
= Client (WMP mat :> api)
clientWithRoute Proxy req =
clientWithRoute (Proxy :: Proxy (WMP mat :> api))
req { reqPath = reqPath req ++ "/" ++ path }
where
path = symbolVal (Proxy :: Proxy path)
instance
( HasClient (WMP mat :> api)
, ToHttpApiData captureType
)
=> HasClient (CaptureWithMatrixParams info captureType mat :> api) where
type Client (CaptureWithMatrixParams info captureType mat :> api)
= captureType -> Client (WMP mat :> api)
clientWithRoute Proxy req = \capture ->
clientWithRoute (Proxy :: Proxy (WMP mat :> api))
req { reqPath = reqPath req ++ "/" ++ T.unpack (toUrlPiece capture) }
-- This is just a dummy used to keep track of whether we have already processed
-- the leading path. If we are in a WMP instance, we have already dealt with
-- the leading path, and can just proceed recursively over the matrix params.
-- If not, we deal with the leading path, and call the WMP instance. WMP itself
-- should not be exported.
data WMP (x :: [*])
instance
( HasClient (WMP rest :> api)
, ToHttpApiData v
, KnownSymbol k
) => HasClient (WMP (MatrixParam k v ': rest) :> api) where
type Client (WMP (MatrixParam k v ': rest) :> api)
= Maybe v -> Client (WMP rest :> api)
clientWithRoute Proxy req x = case x of
Nothing -> clientWithRoute nextProxy req
Just v -> clientWithRoute nextProxy
req { reqPath = reqPath req ++ ";" ++ key ++ "=" ++ T.unpack (toQueryParam v) }
where
nextProxy :: Proxy (WMP rest :> api)
nextProxy = Proxy
key :: String
key = symbolVal (Proxy :: Proxy k)
instance
( HasClient (WMP rest :> api)
, KnownSymbol k
) => HasClient (WMP (MatrixFlag k ': rest) :> api) where
type Client (WMP (MatrixFlag k ': rest) :> api)
= Bool -> Client (WMP rest :> api)
clientWithRoute Proxy req flag
| flag = clientWithRoute nextProxy
req { reqPath = reqPath req ++ ";" ++ key }
| otherwise = clientWithRoute nextProxy req
where
nextProxy :: Proxy (WMP rest :> api)
nextProxy = Proxy
key :: String
key = symbolVal (Proxy :: Proxy k)
instance
( HasClient api
) => HasClient (WMP '[] :> api) where
type Client (WMP '[] :> api) = Client api
clientWithRoute Proxy req =
clientWithRoute (Proxy :: Proxy api) req