packages feed

headroom-0.4.3.0: src/Headroom/Config/Global.hs

{-# LANGUAGE DeriveGeneric     #-}
{-# LANGUAGE FlexibleContexts  #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE RecordWildCards   #-}
{-# LANGUAGE StrictData        #-}

{-|
Module      : Headroom.Config.Global
Description : Global configutation
Copyright   : (c) 2019-2022 Vaclav Svejcar
License     : BSD-3-Clause
Maintainer  : vaclav.svejcar@gmail.com
Stability   : experimental
Portability : POSIX

/Global configuration/ is configuration shared between all /Headroom/ instances
and it's located in user's home directory.
-}

module Headroom.Config.Global
  ( GlobalConfig(..)
  , UpdaterConfig(..)
  , initGlobalConfigIfNeeded
  , loadGlobalConfig
  , parseGlobalConfig
  , globalConfigPath
  )
where

import           Data.Aeson                          ( FromJSON(..)
                                                     , genericParseJSON
                                                     )
import qualified Data.Yaml                          as Y
import           Headroom.Data.Has                   ( Has(..)
                                                     , HasRIO
                                                     )
import           Headroom.Data.Serialization         ( aesonOptions )
import           Headroom.Embedded                   ( defaultGlobalConfig )
import           Headroom.IO.FileSystem              ( FileSystem(..) )
import           Headroom.Meta                       ( globalConfigDirName
                                                     , globalConfigFileName
                                                     )
import           RIO
import qualified RIO.ByteString                     as B
import           RIO.FilePath                        ( (</>) )


---------------------------------  DATA TYPES  ---------------------------------

-- | Data type representing updater configuration.
data UpdaterConfig = UpdaterConfig
  { ucCheckForUpdates    :: Bool    -- ^ whether to check for updates
  , ucUpdateIntervalDays :: Integer -- ^ how ofter check for updates
  }
  deriving (Eq, Generic, Show)

instance FromJSON UpdaterConfig where
  parseJSON = genericParseJSON aesonOptions

-- | Data type representing global configuration options.
data GlobalConfig = GlobalConfig
  { gcUpdates :: UpdaterConfig -- ^ config for updater
  }
  deriving (Eq, Generic, Show)

instance FromJSON GlobalConfig where
  parseJSON = genericParseJSON aesonOptions


------------------------------  PUBLIC FUNCTIONS  ------------------------------

-- | Checks if global configuration /YAML/ file is already present and if not,
-- it creates one with default values.
initGlobalConfigIfNeeded :: (HasRIO FileSystem env) => RIO env ()
initGlobalConfigIfNeeded = do
  FileSystem {..} <- viewL
  userDir         <- fsGetUserDirectory
  configPath      <- globalConfigPath
  whenM (not <$> fsDoesFileExist configPath) $ do
    fsCreateDirectory $ userDir </> globalConfigDirName
    fsWriteFile configPath defaultGlobalConfig


-- | Loads global configuration from /YAML/ file.
loadGlobalConfig :: (HasRIO FileSystem env) => RIO env GlobalConfig
loadGlobalConfig = do
  configPath <- globalConfigPath
  content    <- liftIO . B.readFile $ configPath
  Y.decodeThrow content


-- | Parses global configuration /YAML/ file.
parseGlobalConfig :: (MonadThrow m) => ByteString -> m GlobalConfig
parseGlobalConfig = Y.decodeThrow


-- | Path to global configuration /YAML/ file in user's directory.
globalConfigPath :: HasRIO FileSystem env => RIO env FilePath
globalConfigPath = do
  FileSystem {..} <- viewL
  userDir         <- fsGetUserDirectory
  pure $ userDir </> globalConfigDirName </> globalConfigFileName