module Moo.Core where
import Control.Applicative ((<$>), (<*>))
import Control.Monad.Reader (ReaderT)
import qualified Data.Configurator as C
import Data.Configurator.Types (Config)
import qualified Data.Text as T
import Database.HDBC (IConnection)
import Database.HDBC.PostgreSQL (connectPostgreSQL)
import Database.HDBC.Sqlite3 (connectSqlite3)
import Database.Schema.Migrations ()
import Database.Schema.Migrations.Backend.HDBC ()
import Database.Schema.Migrations.Filesystem (FilesystemStore)
import Database.Schema.Migrations.Store (StoreData)
type AppT a = ReaderT AppState IO a
type CommandHandler = StoreData -> AppT ()
data AppState = AppState { _appOptions :: CommandOptions
, _appCommand :: Command
, _appRequiredArgs :: [String]
, _appOptionalArgs :: [String]
, _appStore :: FilesystemStore
, _appDatabaseConnStr :: Maybe DbConnDescriptor
, _appDatabaseType :: Maybe String
, _appStoreData :: StoreData
}
type ShellEnvironment = [(String, String)]
data Configuration = Configuration
{ _connectionString :: Maybe String
, _databaseType :: Maybe String
, _migrationStorePath :: Maybe FilePath
}
fromShellEnvironment :: ShellEnvironment -> Configuration
fromShellEnvironment env = Configuration connectionString
databaseType
migrationStorePath
where
connectionString = envLookup envDatabaseName
databaseType = envLookup envDatabaseType
migrationStorePath = envLookup envStoreName
envLookup = (\evar -> lookup evar env)
fromConfigurator :: Config -> IO Configuration
fromConfigurator conf = Configuration <$> connectionString
<*> databaseType
<*> migrationStorePath
where
connectionString = configLookup envDatabaseName
databaseType = configLookup envDatabaseType
migrationStorePath = configLookup envStoreName
configLookup = C.lookup conf . T.pack
data AnyIConnection = forall c. (IConnection c) => AnyIConnection c
data CommandOptions = CommandOptions { _configFilePath :: Maybe String
, _test :: Bool
, _noAsk :: Bool
}
data Command = Command { _cName :: String
, _cRequired :: [String]
, _cOptional :: [String]
, _cAllowedOptions :: [String]
, _cDescription :: String
, _cHandler :: CommandHandler
}
data ConfigData = ConfigData { _dbTypeStr :: String
, _dbConnStr :: String
, _fileStorePath :: String
}
newtype DbConnDescriptor = DbConnDescriptor String
databaseTypes :: [(String, String -> IO AnyIConnection)]
databaseTypes = [ ("postgresql", fmap AnyIConnection . connectPostgreSQL)
, ("sqlite3", fmap AnyIConnection . connectSqlite3)
]
envDatabaseType :: String
envDatabaseType = "DBM_DATABASE_TYPE"
envDatabaseName :: String
envDatabaseName = "DBM_DATABASE"
envStoreName :: String
envStoreName = "DBM_MIGRATION_STORE"