module Cachix.Client.Env
  ( Env (..),
    mkEnv,
    cachixVersion,
    customManagerSettings,
  )
where

import Cachix.Client.Config (Config, readConfig)
import Cachix.Client.OptionsParser (CachixOptions (..))
import Cachix.Client.URI (getBaseUrl)
import Data.Version (showVersion)
import Hercules.CNix.Store (Store, openStore)
import Network.HTTP.Client
  ( ManagerSettings,
    managerModifyRequest,
    managerResponseTimeout,
    responseTimeoutNone,
  )
import Network.HTTP.Client.TLS (newTlsManagerWith, tlsManagerSettings)
import Network.HTTP.Simple (setRequestHeader)
import Paths_cachix (version)
import Protolude hiding (toS)
import Protolude.Conv
import Servant.Client (ClientEnv, mkClientEnv)
import System.Directory (canonicalizePath)

data Env = Env
  { Env -> Maybe Config
config :: Maybe Config,
    Env -> ClientEnv
clientenv :: ClientEnv,
    Env -> CachixOptions
cachixoptions :: CachixOptions,
    Env -> Async Store
storeAsync :: Async Store
  }

mkEnv :: CachixOptions -> IO Env
mkEnv :: CachixOptions -> IO Env
mkEnv CachixOptions
rawcachixoptions = do
  Async Store
store <- IO Store -> IO (Async Store)
forall a. IO a -> IO (Async a)
async IO Store
openStore
  -- make sure path to the config is passed as absolute to dhall logic
  FilePath
canonicalConfigPath <- FilePath -> IO FilePath
canonicalizePath (CachixOptions -> FilePath
configPath CachixOptions
rawcachixoptions)
  let cachixOptions :: CachixOptions
cachixOptions = CachixOptions
rawcachixoptions {configPath :: FilePath
configPath = FilePath
canonicalConfigPath}
  Maybe Config
cfg <- FilePath -> IO (Maybe Config)
readConfig (FilePath -> IO (Maybe Config)) -> FilePath -> IO (Maybe Config)
forall a b. (a -> b) -> a -> b
$ CachixOptions -> FilePath
configPath CachixOptions
cachixOptions
  Manager
manager <- ManagerSettings -> IO Manager
forall (m :: * -> *). MonadIO m => ManagerSettings -> m Manager
newTlsManagerWith ManagerSettings
customManagerSettings
  let clientEnv :: ClientEnv
clientEnv = Manager -> BaseUrl -> ClientEnv
mkClientEnv Manager
manager (BaseUrl -> ClientEnv) -> BaseUrl -> ClientEnv
forall a b. (a -> b) -> a -> b
$ URIRef Absolute -> BaseUrl
getBaseUrl (CachixOptions -> URIRef Absolute
host CachixOptions
cachixOptions)
  Env -> IO Env
forall (m :: * -> *) a. Monad m => a -> m a
return
    Env :: Maybe Config -> ClientEnv -> CachixOptions -> Async Store -> Env
Env
      { config :: Maybe Config
config = Maybe Config
cfg,
        clientenv :: ClientEnv
clientenv = ClientEnv
clientEnv,
        cachixoptions :: CachixOptions
cachixoptions = CachixOptions
cachixOptions,
        storeAsync :: Async Store
storeAsync = Async Store
store
      }

customManagerSettings :: ManagerSettings
customManagerSettings :: ManagerSettings
customManagerSettings =
  ManagerSettings
tlsManagerSettings
    { managerResponseTimeout :: ResponseTimeout
managerResponseTimeout = ResponseTimeout
responseTimeoutNone,
      -- managerModifyRequest :: Request -> IO Request
      managerModifyRequest :: Request -> IO Request
managerModifyRequest = Request -> IO Request
forall (m :: * -> *) a. Monad m => a -> m a
return (Request -> IO Request)
-> (Request -> Request) -> Request -> IO Request
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HeaderName -> [ByteString] -> Request -> Request
setRequestHeader HeaderName
"User-Agent" [Text -> ByteString
forall a b. StringConv a b => a -> b
toS Text
cachixVersion]
    }

cachixVersion :: Text
cachixVersion :: Text
cachixVersion = Text
"cachix " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> FilePath -> Text
forall a b. StringConv a b => a -> b
toS (Version -> FilePath
showVersion Version
version)