{-# LANGUAGE TypeFamilies         #-}
{-# LANGUAGE TypeSynonymInstances #-}

-- | Authentication for clients

module Servant.Client.Core.Auth (
    AuthClientData,
    AuthenticatedRequest (..),
    mkAuthenticatedRequest,
    ) where

import Data.Kind (Type)

import           Servant.Client.Core.Request
                 (Request)

-- | For a resource protected by authentication (e.g. AuthProtect), we need
-- to provide the client with some data used to add authentication data
-- to a request
--
-- NOTE: THIS API IS EXPERIMENTAL AND SUBJECT TO CHANGE
type family AuthClientData a :: Type

-- | For better type inference and to avoid usage of a data family, we newtype
-- wrap the combination of some 'AuthClientData' and a function to add authentication
-- data to a request
--
-- NOTE: THIS API IS EXPERIMENTAL AND SUBJECT TO CHANGE
newtype AuthenticatedRequest a =
  AuthenticatedRequest { forall a.
AuthenticatedRequest a
-> (AuthClientData a, AuthClientData a -> Request -> Request)
unAuthReq :: (AuthClientData a, AuthClientData a -> Request -> Request) }

-- | Handy helper to avoid wrapping datatypes in tuples everywhere.
--
-- NOTE: THIS API IS EXPERIMENTAL AND SUBJECT TO CHANGE
mkAuthenticatedRequest :: AuthClientData a
                  -> (AuthClientData a -> Request -> Request)
                  -> AuthenticatedRequest a
mkAuthenticatedRequest :: forall a.
AuthClientData a
-> (AuthClientData a -> Request -> Request)
-> AuthenticatedRequest a
mkAuthenticatedRequest AuthClientData a
val AuthClientData a -> Request -> Request
func = (AuthClientData a, AuthClientData a -> Request -> Request)
-> AuthenticatedRequest a
forall a.
(AuthClientData a, AuthClientData a -> Request -> Request)
-> AuthenticatedRequest a
AuthenticatedRequest (AuthClientData a
val, AuthClientData a -> Request -> Request
func)