mycroforge/MycroForge.CLI/Features/Db.cs

116 lines
3.7 KiB
C#

using MycroForge.CLI.CodeGen;
namespace MycroForge.CLI.Features;
public sealed class Db : IFeature
{
#region Defaults
private static readonly string[] Settings =
[
"class DbSettings:",
"\tdef get_connectionstring() -> str:",
"\t\tconnectionstring = \"mysql+asyncmy://root:password@localhost:%db_port%/%app_name%\"",
"\t\treturn connectionstring",
];
private static readonly string[] AsyncSession =
[
"from sqlalchemy.ext.asyncio import create_async_engine, AsyncEngine, AsyncSession",
$"from {FeatureName}.settings import DbSettings",
"",
"async_engine: AsyncEngine = create_async_engine(DbSettings.get_connectionstring())",
"",
"def async_session() -> AsyncSession:",
"\treturn AsyncSession(async_engine, expire_on_commit=False)"
];
private static readonly string[] EntityBase =
[
"from sqlalchemy.orm import DeclarativeBase",
"",
"class EntityBase(DeclarativeBase):",
"\tpass"
];
private static readonly string[] DockerCompose =
[
"version: '3.8'",
"# Access the database UI at http://localhost:${DB_PORT}.",
"# Login: username = root & password = password",
"",
"services:",
" %app_name%_mariadb:",
" image: 'mariadb:10.4'",
" container_name: '%app_name%_mariadb'",
" networks:",
" - default",
" ports:",
" - '${DB_PORT}:3306'",
" environment:",
" MYSQL_ROOT_PASSWORD: 'password'",
" MYSQL_USER: 'root'",
" MYSQL_PASSWORD: 'password'",
" MYSQL_DATABASE: '%app_name%'",
" volumes:",
" - '%app_name%_mariadb:/var/lib/mysql'",
"",
" %app_name%_phpmyadmin:",
" image: phpmyadmin/phpmyadmin",
" container_name: %app_name%_phpmyadmin",
" ports:",
" - '${PMA_PORT}:80'",
" networks:",
" - default",
" environment:",
" PMA_HOST: %app_name%_mariadb",
" PMA_PORT: 3306",
" PMA_ARBITRARY: 1",
" links:",
" - %app_name%_mariadb",
"",
"volumes:",
" %app_name%_mariadb:\n",
];
#endregion
public const string FeatureName = "db";
public string Name => FeatureName;
public async Task ExecuteAsync(ProjectContext context)
{
var config = await context.LoadConfig();
config.Db = new() { DbPort = 5050, PmaPort = 5051 };
await context.SaveConfig(config);
var appName = context.AppName;
await context.Bash(
"source .venv/bin/activate",
"python3 -m pip install asyncmy sqlalchemy alembic",
"python3 -m pip freeze > requirements.txt",
$"alembic init -t async {FeatureName}"
);
var env = await context.ReadFile($"{FeatureName}/env.py");
env = new DbEnvInitializer(env).Rewrite();
await context.WriteFile($"{FeatureName}/env.py", env);
var settings = string.Join('\n', Settings)
.Replace("%app_name%", appName)
.Replace("%db_port%", config.Db.DbPort.ToString())
;
await context.CreateFile($"{FeatureName}/settings.py", settings);
await context.CreateFile($"{FeatureName}/engine/async_session.py", AsyncSession);
await context.CreateFile($"{FeatureName}/entities/entity_base.py", EntityBase);
var dockerCompose = string.Join('\n', DockerCompose).Replace("%app_name%", appName);
await context.CreateFile($"{FeatureName}.docker-compose.yml", dockerCompose);
}
}