diff --git a/MycroForge.CLI/CodeGen/OrmEnvInitializer.cs b/MycroForge.CLI/CodeGen/DbEnvInitializer.cs similarity index 83% rename from MycroForge.CLI/CodeGen/OrmEnvInitializer.cs rename to MycroForge.CLI/CodeGen/DbEnvInitializer.cs index 39e2671..e6eb3fb 100644 --- a/MycroForge.CLI/CodeGen/OrmEnvInitializer.cs +++ b/MycroForge.CLI/CodeGen/DbEnvInitializer.cs @@ -2,14 +2,14 @@ namespace MycroForge.CLI.CodeGen; -public class OrmEnvInitializer : PythonSourceModifier +public class DbEnvInitializer : PythonSourceModifier { private PythonParser.Import_fromContext? _alembicImport; private PythonParser.AssignmentContext? _targetMetaDataAssignment; private PythonParser.AssignmentContext? _urlAssignmentContext; private PythonParser.AssignmentContext? _connectableAssignmentContext; - public OrmEnvInitializer(string source) : base(source) + public DbEnvInitializer(string source) : base(source) { } @@ -32,17 +32,17 @@ public class OrmEnvInitializer : PythonSourceModifier Rewrite(_alembicImport, [ GetOriginalText(_alembicImport), - "from orm.settings import OrmSettings", - "from orm.entities.entity_base import EntityBase" + "from db.settings import DbSettings", + "from db.entities.entity_base import EntityBase" ]); Rewrite(_targetMetaDataAssignment, "target_metadata = EntityBase.metadata"); - Rewrite(_urlAssignmentContext, "url = OrmSettings.get_connectionstring()"); + Rewrite(_urlAssignmentContext, "url = DbSettings.get_connectionstring()"); const string indent = " "; Rewrite(_connectableAssignmentContext, [ - "url = OrmSettings.get_connectionstring()", + "url = DbSettings.get_connectionstring()", $"{indent}context.config.set_main_option('sqlalchemy.url', url)", $"{indent}{GetOriginalText(_connectableAssignmentContext)}" ]); diff --git a/MycroForge.CLI/CodeGen/OrmEnvUpdater.cs b/MycroForge.CLI/CodeGen/DbEnvUpdater.cs similarity index 62% rename from MycroForge.CLI/CodeGen/OrmEnvUpdater.cs rename to MycroForge.CLI/CodeGen/DbEnvUpdater.cs index f2b40f4..07f1703 100644 --- a/MycroForge.CLI/CodeGen/OrmEnvUpdater.cs +++ b/MycroForge.CLI/CodeGen/DbEnvUpdater.cs @@ -2,15 +2,15 @@ namespace MycroForge.CLI.CodeGen; -public class OrmEnvUpdater : PythonSourceModifier +public class DbEnvUpdater : PythonSourceModifier { - private readonly string _moduleName; + private readonly string _importPath; private readonly string _className; private PythonParser.Import_fromContext? _lastImport; - public OrmEnvUpdater(string source, string moduleName, string className) : base(source) + public DbEnvUpdater(string source, string importPath, string className) : base(source) { - _moduleName = moduleName; + _importPath = importPath; _className = className; } @@ -22,11 +22,11 @@ public class OrmEnvUpdater : PythonSourceModifier if (_lastImport is null) throw new Exception("Could not find import insertion point."); - var text = GetOriginalText(_lastImport); + var lastImportText = GetOriginalText(_lastImport); Rewrite(_lastImport, [ - text, - $"from orm.entities.{_moduleName} import {_className}" + lastImportText, + $"from db.entities.{_importPath} import {_className}" ]); return Rewriter.GetText(); @@ -36,7 +36,7 @@ public class OrmEnvUpdater : PythonSourceModifier { var text = GetOriginalText(context); - if (text.StartsWith("from orm.entities")) + if (text.StartsWith("from db.entities")) _lastImport = context; return base.VisitImport_from(context); diff --git a/MycroForge.CLI/CodeGen/EntityLinker.cs b/MycroForge.CLI/CodeGen/EntityLinker.cs index c305f54..a200b74 100644 --- a/MycroForge.CLI/CodeGen/EntityLinker.cs +++ b/MycroForge.CLI/CodeGen/EntityLinker.cs @@ -77,9 +77,9 @@ public partial class EntityLinker // var right = await LoadEntity(_right); // // left.AppendImportIfNotExists( - // $"orm.entities.{right.FieldName}", + // $"db.entities.{right.FieldName}", // $"{right.ClassName}", - // $"from orm.entities.{right.FieldName} import {right.ClassName}" + // $"from db.entities.{right.FieldName} import {right.ClassName}" // ); // left.AppendImportIfNotExists( // "typing", @@ -92,9 +92,9 @@ public partial class EntityLinker // ]); // // right.AppendImportIfNotExists( - // $"orm.entities.{left.FieldName}", + // $"db.entities.{left.FieldName}", // $"{left.ClassName}", - // $"from orm.entities.{left.FieldName} import {left.ClassName}" + // $"from db.entities.{left.FieldName} import {left.ClassName}" // ); // left.AppendImportIfNotExists( // "typing", @@ -118,5 +118,5 @@ public partial class EntityLinker return entity; } - private string GetEntityPath(string name) => $"orm/entities/{name.Underscore().ToLower()}.py"; + private string GetEntityPath(string name) => $"{Features.Db.FeatureName}/entities/{name.Underscore().ToLower()}.py"; } \ No newline at end of file diff --git a/MycroForge.CLI/Commands/MycroForge.Api.Generate.Router.cs b/MycroForge.CLI/Commands/MycroForge.Api.Generate.Router.cs index d31f1ea..6269fd5 100644 --- a/MycroForge.CLI/Commands/MycroForge.Api.Generate.Router.cs +++ b/MycroForge.CLI/Commands/MycroForge.Api.Generate.Router.cs @@ -40,14 +40,14 @@ public partial class MycroForge private async Task ExecuteAsync(string name) { - _context.AssertDirectoryExists("api/routers"); - + _context.AssertDirectoryExists($"{Features.Api.FeatureName}/routers"); + var moduleName = name.Underscore(); - await _context.CreateFile($"api/routers/{moduleName}.py", Template); + await _context.CreateFile($"{Features.Api.FeatureName}/routers/{moduleName}.py", Template); var main = await _context.ReadFile("main.py"); main += string.Join('\n', - $"\n\nfrom api.routers import {moduleName}", + $"\n\nfrom {Features.Api.FeatureName}.routers import {moduleName}", $"app.include_router(prefix=\"/{name.Kebaberize()}\", router={moduleName}.router)" ); await _context.WriteFile("main.py", main); diff --git a/MycroForge.CLI/Commands/MycroForge.Db.Generate.Entity.cs b/MycroForge.CLI/Commands/MycroForge.Db.Generate.Entity.cs new file mode 100644 index 0000000..ee8452c --- /dev/null +++ b/MycroForge.CLI/Commands/MycroForge.Db.Generate.Entity.cs @@ -0,0 +1,131 @@ +using System.CommandLine; +using Humanizer; +using MycroForge.CLI.CodeGen; +using MycroForge.CLI.Commands.Interfaces; + +namespace MycroForge.CLI.Commands; + +public partial class MycroForge +{ + public partial class Db + { + public partial class Generate + { + public class Entity : Command, ISubCommandOf + { + private record ColumnDefinition(string Name, string NativeType, string OrmType); + + private static readonly string[] Template = + [ + "from sqlalchemy import %type_imports%", + "from sqlalchemy.orm import Mapped, mapped_column", + "from db.entities.entity_base import EntityBase", + "", + "class %class_name%(EntityBase):", + "\t__tablename__ = \"%table_name%\"", + "\tid: Mapped[int] = mapped_column(primary_key=True)", + "\t%column_definitions%", + "", + "\tdef __repr__(self) -> str:", + "\t\treturn f\"%class_name%(id={self.id!r})\"" + ]; + + private static readonly Argument NameArgument = + new(name: "name", description: string.Join('\n', [ + "The name of the database entity", + "", + "Supported formats:", + "\tEntity", + "\tpath/relative/to/entities:Entity", + ])); + + private static readonly Option> ColumnsOption = + new(aliases: ["--column", "-c"], description: string.Join('\n', [ + "Specify the fields to add.", + "", + "Format:", + "\t::", + "\t", + "\t = Name of the column", + "\t = The native Python type", + "\t = The SQLAlchemy type", + "", + "Example:", + "\tfirst_name:str:String(255)", + ])) { AllowMultipleArgumentsPerToken = true }; + + private readonly ProjectContext _context; + + public Entity(ProjectContext context) : base("entity", "Generate and database entity") + { + _context = context; + AddAlias("e"); + AddArgument(NameArgument); + AddOption(ColumnsOption); + this.SetHandler(ExecuteAsync, NameArgument, ColumnsOption); + } + + private async Task ExecuteAsync(string name, IEnumerable columns) + { + _context.AssertDirectoryExists(Features.Db.FeatureName); + + var path = string.Empty; + if (name.Split(':').Select(s => s.Trim()).ToArray() is { Length: 2 } fullName) + { + path = fullName[0]; + name = fullName[1]; + } + + var _columns = GetColumnDefinitions(columns.ToArray()); + var className = name.Underscore().Pascalize(); + var typeImports = string.Join(", ", _columns.Select(c => c.OrmType.Split('(').First()).Distinct()); + var columnDefinitions = string.Join("\n\t", _columns.Select(ColumnToString)); + + var code = string.Join('\n', Template); + code = code.Replace("%type_imports%", typeImports); + code = code.Replace("%class_name%", className); + code = code.Replace("%table_name%", name.Underscore().ToLower().Pluralize()); + code = code.Replace("%column_definitions%", columnDefinitions); + + var folderPath = Path.Join($"{Features.Db.FeatureName}/entities", path); + var fileName = $"{name.ToLower()}.py"; + var filePath = Path.Join(folderPath, fileName); + await _context.CreateFile(filePath, code); + + var importPathParts = new[] { path, fileName.Replace(".py", "") } + .Where(s => !string.IsNullOrEmpty(s)); + + var importPath = string.Join('.', importPathParts) + .Replace('/', '.') + .Replace('\\', '.') + .Underscore() + .ToLower(); + + var env = await _context.ReadFile($"{Features.Db.FeatureName}/env.py"); + env = new DbEnvUpdater(env, importPath, className).Rewrite(); + await _context.WriteFile($"{Features.Db.FeatureName}/env.py", env); + } + + private List GetColumnDefinitions(string[] fields) + { + var definitions = new List(); + + foreach (var field in fields) + { + if (field.Split(':') is not { Length: 3 } definition) + throw new Exception($"Field definition {field} is invalid."); + + definitions.Add(new ColumnDefinition(definition[0], definition[1], definition[2])); + } + + return definitions; + } + + private static string ColumnToString(ColumnDefinition definition) + { + return $"{definition.Name}: Mapped[{definition.NativeType}] = mapped_column({definition.OrmType})"; + } + } + } + } +} \ No newline at end of file diff --git a/MycroForge.CLI/Commands/MycroForge.Orm.Generate.Migration.cs b/MycroForge.CLI/Commands/MycroForge.Db.Generate.Migration.cs similarity index 88% rename from MycroForge.CLI/Commands/MycroForge.Orm.Generate.Migration.cs rename to MycroForge.CLI/Commands/MycroForge.Db.Generate.Migration.cs index 3bfe585..89aec3a 100644 --- a/MycroForge.CLI/Commands/MycroForge.Orm.Generate.Migration.cs +++ b/MycroForge.CLI/Commands/MycroForge.Db.Generate.Migration.cs @@ -5,7 +5,7 @@ namespace MycroForge.CLI.Commands; public partial class MycroForge { - public partial class Orm + public partial class Db { public partial class Generate { @@ -26,7 +26,7 @@ public partial class MycroForge private async Task ExecuteAsync(string name) { - _context.AssertDirectoryExists("orm/versions"); + _context.AssertDirectoryExists($"{Features.Db.FeatureName}/versions"); await _context.Bash( "source .venv/bin/activate", diff --git a/MycroForge.CLI/Commands/MycroForge.Orm.Generate.cs b/MycroForge.CLI/Commands/MycroForge.Db.Generate.cs similarity index 71% rename from MycroForge.CLI/Commands/MycroForge.Orm.Generate.cs rename to MycroForge.CLI/Commands/MycroForge.Db.Generate.cs index de6ed4b..b4349f3 100644 --- a/MycroForge.CLI/Commands/MycroForge.Orm.Generate.cs +++ b/MycroForge.CLI/Commands/MycroForge.Db.Generate.cs @@ -5,12 +5,12 @@ namespace MycroForge.CLI.Commands; public partial class MycroForge { - public partial class Orm + public partial class Db { - public partial class Generate : Command, ISubCommandOf + public partial class Generate : Command, ISubCommandOf { public Generate(IEnumerable> subCommands) : - base("generate", "Generate an ORM item") + base("generate", "Generate a database item") { AddAlias("g"); foreach (var subCommandOf in subCommands.Cast()) diff --git a/MycroForge.CLI/Commands/MycroForge.Orm.Link.Many.cs b/MycroForge.CLI/Commands/MycroForge.Db.Link.Many.cs similarity index 84% rename from MycroForge.CLI/Commands/MycroForge.Orm.Link.Many.cs rename to MycroForge.CLI/Commands/MycroForge.Db.Link.Many.cs index 337bc39..20f86ac 100644 --- a/MycroForge.CLI/Commands/MycroForge.Orm.Link.Many.cs +++ b/MycroForge.CLI/Commands/MycroForge.Db.Link.Many.cs @@ -6,7 +6,7 @@ namespace MycroForge.CLI.Commands; public partial class MycroForge { - public partial class Orm + public partial class Db { public partial class Link { @@ -39,20 +39,20 @@ public partial class MycroForge throw new Exception("Cannot set both --to-one and --to-many option."); if (toOneOption is not null) - await ManyToOne(left, toOneOption); + await ToOne(left, toOneOption); else if (toManyOption is not null) - await ManyToMany(left, toManyOption); + await ToMany(left, toManyOption); else throw new Exception("Set --to-one or --to-many option."); } - private async Task ManyToOne(string left, string toOneOption) + private async Task ToOne(string left, string toOneOption) { await new EntityLinker(_context, left, toOneOption).ManyToOne(); } - private async Task ManyToMany(string left, string toManyOption) + private async Task ToMany(string left, string toManyOption) { await new EntityLinker(_context, left, toManyOption).ManyToMany(); } diff --git a/MycroForge.CLI/Commands/MycroForge.Orm.Link.One.cs b/MycroForge.CLI/Commands/MycroForge.Db.Link.One.cs similarity index 84% rename from MycroForge.CLI/Commands/MycroForge.Orm.Link.One.cs rename to MycroForge.CLI/Commands/MycroForge.Db.Link.One.cs index 04e871f..1471e26 100644 --- a/MycroForge.CLI/Commands/MycroForge.Orm.Link.One.cs +++ b/MycroForge.CLI/Commands/MycroForge.Db.Link.One.cs @@ -6,7 +6,7 @@ namespace MycroForge.CLI.Commands; public partial class MycroForge { - public partial class Orm + public partial class Db { public partial class Link { @@ -39,20 +39,20 @@ public partial class MycroForge throw new Exception("Cannot set both --to-one and --to-many option."); if (toOneOption is not null) - await OneToOne(left, toOneOption); + await ToOne(left, toOneOption); else if (toManyOption is not null) - await OneToMany(left, toManyOption); + await ToMany(left, toManyOption); else throw new Exception("Set --to-one or --to-many option."); } - private async Task OneToOne(string left, string toOneOption) + private async Task ToOne(string left, string toOneOption) { await new EntityLinker(_context, left, toOneOption).OneToOne(); } - private async Task OneToMany(string left, string toManyOption) + private async Task ToMany(string left, string toManyOption) { await new EntityLinker(_context, left, toManyOption).OneToMany(); } diff --git a/MycroForge.CLI/Commands/MycroForge.Orm.Link.cs b/MycroForge.CLI/Commands/MycroForge.Db.Link.cs similarity index 79% rename from MycroForge.CLI/Commands/MycroForge.Orm.Link.cs rename to MycroForge.CLI/Commands/MycroForge.Db.Link.cs index dce0eb4..c46abe4 100644 --- a/MycroForge.CLI/Commands/MycroForge.Orm.Link.cs +++ b/MycroForge.CLI/Commands/MycroForge.Db.Link.cs @@ -5,9 +5,9 @@ namespace MycroForge.CLI.Commands; public partial class MycroForge { - public partial class Orm + public partial class Db { - public partial class Link : Command, ISubCommandOf + public partial class Link : Command, ISubCommandOf { public Link(IEnumerable> commands) : base("link", "Define relationships between entities") diff --git a/MycroForge.CLI/Commands/MycroForge.Orm.Migrate.cs b/MycroForge.CLI/Commands/MycroForge.Db.Migrate.cs similarity index 85% rename from MycroForge.CLI/Commands/MycroForge.Orm.Migrate.cs rename to MycroForge.CLI/Commands/MycroForge.Db.Migrate.cs index f1040e7..fc6b214 100644 --- a/MycroForge.CLI/Commands/MycroForge.Orm.Migrate.cs +++ b/MycroForge.CLI/Commands/MycroForge.Db.Migrate.cs @@ -5,9 +5,9 @@ namespace MycroForge.CLI.Commands; public partial class MycroForge { - public partial class Orm + public partial class Db { - public class Migrate : Command, ISubCommandOf + public class Migrate : Command, ISubCommandOf { private readonly ProjectContext _context; diff --git a/MycroForge.CLI/Commands/MycroForge.Orm.Rollback.cs b/MycroForge.CLI/Commands/MycroForge.Db.Rollback.cs similarity index 85% rename from MycroForge.CLI/Commands/MycroForge.Orm.Rollback.cs rename to MycroForge.CLI/Commands/MycroForge.Db.Rollback.cs index 0b03edb..4e66c3a 100644 --- a/MycroForge.CLI/Commands/MycroForge.Orm.Rollback.cs +++ b/MycroForge.CLI/Commands/MycroForge.Db.Rollback.cs @@ -5,9 +5,9 @@ namespace MycroForge.CLI.Commands; public partial class MycroForge { - public partial class Orm + public partial class Db { - public class Rollback : Command, ISubCommandOf + public class Rollback : Command, ISubCommandOf { private readonly ProjectContext _context; diff --git a/MycroForge.CLI/Commands/MycroForge.Db.cs b/MycroForge.CLI/Commands/MycroForge.Db.cs new file mode 100644 index 0000000..aa25061 --- /dev/null +++ b/MycroForge.CLI/Commands/MycroForge.Db.cs @@ -0,0 +1,17 @@ +using System.CommandLine; +using MycroForge.CLI.Commands.Interfaces; + +namespace MycroForge.CLI.Commands; + +public partial class MycroForge +{ + public partial class Db : Command, ISubCommandOf + { + public Db(IEnumerable> commands) + : base("db", "Database related commands") + { + foreach (var command in commands.Cast()) + AddCommand(command); + } + } +} \ No newline at end of file diff --git a/MycroForge.CLI/Commands/MycroForge.Generate.Service.cs b/MycroForge.CLI/Commands/MycroForge.Generate.Service.cs index 0d94938..f61634f 100644 --- a/MycroForge.CLI/Commands/MycroForge.Generate.Service.cs +++ b/MycroForge.CLI/Commands/MycroForge.Generate.Service.cs @@ -30,9 +30,9 @@ public partial class MycroForge private static readonly string[] WithSessionTemplate = [ - "from orm.engine.async_session import async_session", + "from db.engine.async_session import async_session", "from sqlalchemy import select", - "# from orm.entities.some_entity import SomeEntity", + "# from db.entities.some_entity import SomeEntity", "", "class %class_name%Service:", "", diff --git a/MycroForge.CLI/Commands/MycroForge.Hydrate.cs b/MycroForge.CLI/Commands/MycroForge.Hydrate.cs index 5169b1d..8d770c6 100644 --- a/MycroForge.CLI/Commands/MycroForge.Hydrate.cs +++ b/MycroForge.CLI/Commands/MycroForge.Hydrate.cs @@ -10,7 +10,7 @@ public partial class MycroForge private readonly ProjectContext _context; public Hydrate(ProjectContext context) - : base("hydrate", "Create a new venv and install dependencies listed in requirements.txt") + : base("hydrate", "Initialize venv and install dependencies from requirements.txt") { _context = context; this.SetHandler(ExecuteAsync); diff --git a/MycroForge.CLI/Commands/MycroForge.Init.cs b/MycroForge.CLI/Commands/MycroForge.Init.cs index 9e0cdff..b06f2a5 100644 --- a/MycroForge.CLI/Commands/MycroForge.Init.cs +++ b/MycroForge.CLI/Commands/MycroForge.Init.cs @@ -59,7 +59,7 @@ public partial class MycroForge [ Features.Git.FeatureName, Features.Api.FeatureName, - Features.Orm.FeatureName + Features.Db.FeatureName ]; private static readonly Argument NameArgument = @@ -111,8 +111,17 @@ public partial class MycroForge // Initialize default features foreach (var feature in _features.Where(f => DefaultFeatures.Contains(f.Name))) + { if (!withoutList.Contains(feature.Name)) + { + Console.WriteLine($"Initializing feature {feature.Name}"); await feature.ExecuteAsync(_context); + } + else + { + Console.WriteLine($"Skipping feature {feature.Name}"); + } + } Console.WriteLine($"Directory {projectRoot} was successfully initialized"); } diff --git a/MycroForge.CLI/Commands/MycroForge.Orm.Generate.Entity.cs b/MycroForge.CLI/Commands/MycroForge.Orm.Generate.Entity.cs deleted file mode 100644 index 00b06db..0000000 --- a/MycroForge.CLI/Commands/MycroForge.Orm.Generate.Entity.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System.CommandLine; -using Humanizer; -using MycroForge.CLI.CodeGen; -using MycroForge.CLI.Commands.Interfaces; - -namespace MycroForge.CLI.Commands; - -public partial class MycroForge -{ - public partial class Orm - { - public partial class Generate - { - public class Entity : Command, ISubCommandOf - { - private static readonly string[] Template = - [ - "from sqlalchemy import String", - "from sqlalchemy.orm import Mapped, mapped_column", - "from orm.entities.entity_base import EntityBase", - "", - "class %class_name%(EntityBase):", - "\t__tablename__ = \"%table_name%\"", - "\tid: Mapped[int] = mapped_column(primary_key=True)", - "\tvalue: Mapped[str] = mapped_column(String(255))", - "", - "\tdef __repr__(self) -> str:", - "\t\treturn f\"%class_name%(id={self.id!r}, value={self.value!r})\"" - ]; - - private static readonly Argument NameArgument = - new(name: "name", description: "The name of the orm entity"); - - private readonly ProjectContext _context; - - public Entity(ProjectContext context) : base("entity", "Generate and orm entity") - { - _context = context; - AddAlias("e"); - AddArgument(NameArgument); - this.SetHandler(ExecuteAsync, NameArgument); - } - - private async Task ExecuteAsync(string name) - { - _context.AssertDirectoryExists("orm"); - - var className = name.Underscore().Pascalize(); - var moduleName = name.Underscore(); - var code = string.Join('\n', Template); - - code = code.Replace("%class_name%", className); - code = code.Replace("%table_name%", name.Underscore().ToLower().Pluralize()); - await _context.CreateFile($"orm/entities/{moduleName}.py", code); - - var env = await _context.ReadFile("orm/env.py"); - env = new OrmEnvUpdater(env, moduleName, className).Rewrite(); - await _context.WriteFile("orm/env.py", env); - } - } - } - } -} \ No newline at end of file diff --git a/MycroForge.CLI/Commands/MycroForge.Orm.cs b/MycroForge.CLI/Commands/MycroForge.Orm.cs deleted file mode 100644 index 8a00e45..0000000 --- a/MycroForge.CLI/Commands/MycroForge.Orm.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System.CommandLine; -using MycroForge.CLI.Commands.Interfaces; - -namespace MycroForge.CLI.Commands; - -public partial class MycroForge -{ - public partial class Orm : Command, ISubCommandOf - { - public Orm(IEnumerable> subCommands) - : base("orm", "ORM related commands") - { - foreach (var subCommandOf in subCommands.Cast()) - AddCommand(subCommandOf); - } - } -} \ No newline at end of file diff --git a/MycroForge.CLI/Extensions/ServiceCollectionExtensions.cs b/MycroForge.CLI/Extensions/ServiceCollectionExtensions.cs index 8d3a91a..9a2f68d 100644 --- a/MycroForge.CLI/Extensions/ServiceCollectionExtensions.cs +++ b/MycroForge.CLI/Extensions/ServiceCollectionExtensions.cs @@ -11,7 +11,7 @@ public static class ServiceCollectionExtensions services.AddScoped(); services.AddScoped(); services.AddScoped(); - services.AddScoped(); + services.AddScoped(); return services; } @@ -37,15 +37,15 @@ public static class ServiceCollectionExtensions services.AddScoped, Commands.MycroForge.Api.Generate.Router>(); // Register "m4g orm" - services.AddScoped, Commands.MycroForge.Orm>(); - services.AddScoped, Commands.MycroForge.Orm.Migrate>(); - services.AddScoped, Commands.MycroForge.Orm.Rollback>(); - services.AddScoped, Commands.MycroForge.Orm.Generate>(); - services.AddScoped, Commands.MycroForge.Orm.Generate.Entity>(); - services.AddScoped, Commands.MycroForge.Orm.Generate.Migration>(); - services.AddScoped, Commands.MycroForge.Orm.Link>(); - services.AddScoped, Commands.MycroForge.Orm.Link.One>(); - services.AddScoped, Commands.MycroForge.Orm.Link.Many>(); + services.AddScoped, Commands.MycroForge.Db>(); + services.AddScoped, Commands.MycroForge.Db.Migrate>(); + services.AddScoped, Commands.MycroForge.Db.Rollback>(); + services.AddScoped, Commands.MycroForge.Db.Generate>(); + services.AddScoped, Commands.MycroForge.Db.Generate.Entity>(); + services.AddScoped, Commands.MycroForge.Db.Generate.Migration>(); + services.AddScoped, Commands.MycroForge.Db.Link>(); + services.AddScoped, Commands.MycroForge.Db.Link.One>(); + services.AddScoped, Commands.MycroForge.Db.Link.Many>(); // Register "m4g script" services.AddScoped, Commands.MycroForge.Script>(); diff --git a/MycroForge.CLI/Features/Api.cs b/MycroForge.CLI/Features/Api.cs index 3fcd922..c1e1b98 100644 --- a/MycroForge.CLI/Features/Api.cs +++ b/MycroForge.CLI/Features/Api.cs @@ -22,7 +22,7 @@ public sealed class Api : IFeature "from fastapi import FastAPI", "app = FastAPI()", "", - "from api.routers import hello", + $"from {FeatureName}.routers import hello", "app.include_router(prefix=\"/hello\", router=hello.router)" ]; @@ -42,7 +42,7 @@ public sealed class Api : IFeature "python3 -m pip freeze > requirements.txt" ); - await context.CreateFile("api/routers/hello.py", HelloRouter); + await context.CreateFile($"{FeatureName}/routers/hello.py", HelloRouter); var main = await context.ReadFile("main.py"); main = string.Join('\n', Main) + main; diff --git a/MycroForge.CLI/Features/Orm.cs b/MycroForge.CLI/Features/Db.cs similarity index 64% rename from MycroForge.CLI/Features/Orm.cs rename to MycroForge.CLI/Features/Db.cs index f51136e..b5646ea 100644 --- a/MycroForge.CLI/Features/Orm.cs +++ b/MycroForge.CLI/Features/Db.cs @@ -2,7 +2,7 @@ namespace MycroForge.CLI.Features; -public sealed class Orm : IFeature +public sealed class Db : IFeature { #region Defaults @@ -10,7 +10,7 @@ public sealed class Orm : IFeature [ "connectionstring = \"mysql+asyncmy://root:root@localhost:3306/example\"", "", - "class OrmSettings:", + "class DbSettings:", "\tdef get_connectionstring() -> str:", "\t\treturn connectionstring" ]; @@ -18,9 +18,9 @@ public sealed class Orm : IFeature private static readonly string[] AsyncSession = [ "from sqlalchemy.ext.asyncio import create_async_engine, AsyncEngine, AsyncSession", - "from orm.settings import OrmSettings", + "from db.settings import DbSettings", "", - "async_engine: AsyncEngine = create_async_engine(OrmSettings.get_connectionstring())", + "async_engine: AsyncEngine = create_async_engine(DbSettings.get_connectionstring())", "", "def async_session() -> AsyncSession:", "\treturn AsyncSession(async_engine, expire_on_commit=False)" @@ -38,7 +38,7 @@ public sealed class Orm : IFeature [ "from sqlalchemy import String", "from sqlalchemy.orm import Mapped, mapped_column", - "from orm.entities.entity_base import EntityBase", + "from db.entities.entity_base import EntityBase", "", "class User(EntityBase):", "\t__tablename__ = \"users\"", @@ -52,7 +52,7 @@ public sealed class Orm : IFeature #endregion - public const string FeatureName = "orm"; + public const string FeatureName = "db"; public string Name => FeatureName; @@ -64,21 +64,21 @@ public sealed class Orm : IFeature "source .venv/bin/activate", "python3 -m pip install asyncmy sqlalchemy alembic", "python3 -m pip freeze > requirements.txt", - "alembic init -t async orm" + $"alembic init -t async {FeatureName}" ); - var env = await context.ReadFile("orm/env.py"); - env = new OrmEnvInitializer(env).Rewrite(); - env = new OrmEnvUpdater(env, "user", "User").Rewrite(); - await context.WriteFile("orm/env.py", env); + var env = await context.ReadFile($"{FeatureName}/env.py"); + env = new DbEnvInitializer(env).Rewrite(); + env = new DbEnvUpdater(env, "user", "User").Rewrite(); + await context.WriteFile($"{FeatureName}/env.py", env); - await context.CreateFile("orm/settings.py", Settings); + await context.CreateFile($"{FeatureName}/settings.py", Settings); - await context.CreateFile("orm/engine/async_session.py", AsyncSession); + await context.CreateFile($"{FeatureName}/engine/async_session.py", AsyncSession); - await context.CreateFile("orm/entities/entity_base.py", EntityBase); + await context.CreateFile($"{FeatureName}/entities/entity_base.py", EntityBase); - await context.CreateFile("orm/entities/user.py", User); + await context.CreateFile($"{FeatureName}/entities/user.py", User); await context.SaveConfig(config); }