ihp-ide-1.4.0: IHP/IDE/CodeGen/JobGenerator.hs
module IHP.IDE.CodeGen.JobGenerator (buildPlan, buildPlan', JobConfig (..)) where
import IHP.Prelude
import qualified Data.Text as Text
import IHP.IDE.CodeGen.Types
import qualified System.Directory as Directory
data JobConfig = JobConfig
{ applicationName :: Text
, tableName :: Text -- E.g. create_container_jobs
, modelName :: Text -- E.g. CreateContainerJob
, isFirstJobInApplication :: Bool -- If true, creates Worker.hs in application directory
} deriving (Eq, Show)
buildPlan :: Text -> Text -> IO (Either Text [GeneratorAction])
buildPlan jobName applicationName = do
isFirstJobInApplication <- not <$> Directory.doesFileExist (cs $ applicationName <> "/Worker.hs")
if null jobName
then pure $ Left "Job name cannot be empty"
else do
let jobConfig = JobConfig
{ applicationName
, tableName = jobName
, modelName = tableNameToModelName jobName
, isFirstJobInApplication
}
pure $ Right $ buildPlan' jobConfig
-- E.g. qualifiedMailModuleName config "Confirmation" == "Web.Mail.Users.Confirmation"
qualifiedJobModuleName :: JobConfig -> Text
qualifiedJobModuleName config =
config.applicationName <> ".Job." <> unqualifiedJobModuleName config
unqualifiedJobModuleName :: JobConfig -> Text
unqualifiedJobModuleName config = Text.replace "Job" "" (config.modelName)
buildPlan' :: JobConfig -> [GeneratorAction]
buildPlan' config =
let
name = config.modelName
tableName = modelNameToTableName nameWithSuffix
nameWithSuffix = if "Job" `isSuffixOf` name
then name
else name <> "Job" --e.g. "Test" -> "TestJob"
nameWithoutSuffix = if "Job" `isSuffixOf` name
then Text.replace "Job" "" name
else name --e.g. "TestJob" -> "Test""
job =
""
<> "module " <> qualifiedJobModuleName config <> " where\n"
<> "import " <> config.applicationName <> ".Controller.Prelude\n"
<> "\n"
<> "instance Job " <> nameWithSuffix <> " where\n"
<> " perform " <> nameWithSuffix <> " { .. } = do\n"
<> " putStrLn \"Hello World!\"\n"
schemaSql =
""
<> "CREATE TABLE " <> tableName <> " (\n"
<> " id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,\n"
<> " created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,\n"
<> " updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,\n"
<> " status JOB_STATUS DEFAULT 'job_status_not_started' NOT NULL,\n"
<> " last_error TEXT DEFAULT NULL,\n"
<> " attempts_count INT DEFAULT 0 NOT NULL,\n"
<> " locked_at TIMESTAMP WITH TIME ZONE DEFAULT NULL,\n"
<> " locked_by UUID DEFAULT NULL,\n"
<> " run_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL\n"
<> ");\n"
emptyWorkerHs :: Text
emptyWorkerHs =
let
applicationName = config.applicationName
in cs [plain|module #{applicationName}.Worker where
import IHP.Prelude
import #{applicationName}.Types
import Generated.Types
import IHP.Job.Runner
import IHP.Job.Types
import #{qualifiedJobModuleName config}
instance Worker #{applicationName}Application where
workers _ =
[ worker @#{nameWithSuffix}
-- Generator Marker
]
|]
in
[ EnsureDirectory { directory = config.applicationName <> "/Job" }
, AppendToFile { filePath = "Application/Schema.sql", fileContent = schemaSql }
, CreateFile { filePath = config.applicationName <> "/Job/" <> nameWithoutSuffix <> ".hs", fileContent = job }
]
<> if config.isFirstJobInApplication
then [ CreateFile { filePath = config.applicationName <> "/Worker.hs", fileContent = emptyWorkerHs } ]
else
[ AddImport { filePath = config.applicationName <> "/Worker.hs", fileContent = "import " <> qualifiedJobModuleName config }
, AppendToMarker { marker = "-- Generator Marker", filePath = config.applicationName <> "/Worker.hs", fileContent = " , worker @" <> nameWithSuffix }
]