Refactored FullyQualifiedName functionality

This commit is contained in:
mdnapo 2024-07-14 23:08:47 +02:00
parent 02a82589ae
commit be6b3691b4
9 changed files with 77 additions and 64 deletions

View File

@ -20,7 +20,7 @@ public class CrudRouterGenerator
"",
"@router.get(\"/\")",
"async def list(",
"\tservice: Annotated[%service_class_name%, Depends(%service_class_name%)]",
"\tservice: Annotated[%service_class_name%, Depends()]",
"):",
"\ttry:",
"\t\tresult = await service.list()",
@ -32,7 +32,7 @@ public class CrudRouterGenerator
"@router.get(\"/{id}\")",
"async def get_by_id(",
"\tid: int,",
"\tservice: Annotated[%service_class_name%, Depends(%service_class_name%)]",
"\tservice: Annotated[%service_class_name%, Depends()]",
"):",
"\ttry:",
"\t\tresult = await service.get_by_id(id)",
@ -44,7 +44,7 @@ public class CrudRouterGenerator
"@router.post(\"/\")",
"async def create(",
"\trequest: Create%entity_class_name%Request,",
"\tservice: Annotated[%service_class_name%, Depends(%service_class_name%)]",
"\tservice: Annotated[%service_class_name%, Depends()]",
"):",
"\ttry:",
"\t\tawait service.create(request.model_dump())",
@ -57,7 +57,7 @@ public class CrudRouterGenerator
"async def update(",
"\tid: int,",
"\trequest: Update%entity_class_name%Request,",
"\tservice: Annotated[%service_class_name%, Depends(%service_class_name%)]",
"\tservice: Annotated[%service_class_name%, Depends()]",
"):",
"\ttry:",
"\t\tupdated = await service.update(id, request.model_dump(exclude_unset=True))",
@ -69,7 +69,7 @@ public class CrudRouterGenerator
"@router.delete(\"/{id}\")",
"async def delete(",
"\tid: int,",
"\tservice: Annotated[%service_class_name%, Depends(%service_class_name%)]",
"\tservice: Annotated[%service_class_name%, Depends()]",
"):",
"\ttry:",
"\t\tdeleted = await service.delete(id)",

View File

@ -1,4 +1,5 @@
using Humanizer;
using MycroForge.CLI.Commands;
using MycroForge.Core;
namespace MycroForge.CLI.CodeGen;
@ -143,16 +144,14 @@ public partial class EntityLinker
private async Task<EntityModel> LoadEntity(string name)
{
var fqn = new FullyQualifiedName(name);
var path = $"{Features.Db.FeatureName}/entities";
if (name.Split(':').Select(s => s.Trim()).ToArray() is { Length: 2 } fullName)
{
path = Path.Combine(path, fullName[0]);
name = fullName[1];
}
if (fqn.HasPath)
path = Path.Combine(path, fqn.Path);
path = Path.Combine(path, $"{name.Underscore().ToLower()}.py");
var entity = new EntityModel(name, path, await _context.ReadFile(path));
path = Path.Combine(path, $"{fqn.SnakeCasedName}.py");
var entity = new EntityModel(fqn.PascalizedName, path, await _context.ReadFile(path));
entity.Initialize();
return entity;
}

View File

@ -0,0 +1,28 @@
using Humanizer;
namespace MycroForge.CLI.Commands;
public class FullyQualifiedName
{
public string Path { get; }
public string PascalizedName { get; }
public string SnakeCasedName { get; }
public bool HasPath => Path.Length > 0;
public FullyQualifiedName(string name)
{
var path = string.Empty;
if (name.Split(':').Select(s => s.Trim()).ToArray() is { Length: 2 } fullName)
{
path = fullName[0];
name = fullName[1];
}
Path = path;
PascalizedName = name.Pascalize();
SnakeCasedName = name.Underscore().ToLower();
}
}

View File

@ -28,17 +28,12 @@ public partial class MycroForge
private async Task ExecuteAsync(string entity)
{
var path = string.Empty;
if (entity.Split(':').Select(s => s.Trim()).ToArray() is { Length: 2 } fullName)
{
path = fullName[0];
entity = fullName[1];
}
var fqn = new FullyQualifiedName(entity);
await new CrudServiceGenerator(_context).Generate(path, entity);
await new RequestClassGenerator(_context).Generate(path, entity, RequestClassGenerator.Type.Create);
await new RequestClassGenerator(_context).Generate(path, entity, RequestClassGenerator.Type.Update);
await new CrudRouterGenerator(_context).Generate(path, entity);
await new CrudServiceGenerator(_context).Generate(fqn.Path, fqn.PascalizedName);
await new RequestClassGenerator(_context).Generate(fqn.Path, fqn.PascalizedName, RequestClassGenerator.Type.Create);
await new RequestClassGenerator(_context).Generate(fqn.Path, fqn.PascalizedName, RequestClassGenerator.Type.Update);
await new CrudRouterGenerator(_context).Generate(fqn.Path, fqn.PascalizedName);
}
}
}

View File

@ -1,5 +1,6 @@
using System.CommandLine;
using Humanizer;
using MycroForge.CLI.CodeGen;
using MycroForge.Core.Contract;
using MycroForge.CLI.Extensions;
using MycroForge.Core;
@ -42,30 +43,31 @@ public partial class MycroForge
private async Task ExecuteAsync(string name)
{
var fqn = new FullyQualifiedName(name);
var folderPath = $"{Features.Api.FeatureName}/routers";
_context.AssertDirectoryExists(folderPath);
if (name.FullyQualifiedName() is { Length: 2 } fullName)
{
folderPath = Path.Combine(folderPath, fullName[0]);
name = fullName[1];
}
var moduleImportPath = folderPath.Replace('\\', '.').Replace('/', '.');
var moduleName = name.Underscore().ToLower();
var fileName = $"{moduleName}.py";
if (fqn.HasPath)
folderPath = Path.Combine(folderPath, fqn.Path);
var fileName = $"{fqn.SnakeCasedName}.py";
var filePath = Path.Combine(folderPath, fileName);
await _context.CreateFile(filePath, Template);
var moduleImportPath = folderPath
.Replace('\\', '.')
.Replace('/', '.');
var main = await _context.ReadFile("main.py");
main += string.Join('\n',
$"\n\nfrom {moduleImportPath} import {moduleName}",
$"app.include_router(prefix=\"/{name.Kebaberize()}\", router={moduleName}.router)"
);
main = new MainModifier(main)
.Initialize()
.Import(from: moduleImportPath, import: fqn.SnakeCasedName)
.IncludeRouter(prefix: name.Kebaberize(), router: fqn.SnakeCasedName)
.Rewrite();
await _context.WriteFile("main.py", main);
}
}

View File

@ -69,28 +69,25 @@ public partial class MycroForge
private async Task ExecuteAsync(string name, IEnumerable<string> columns)
{
var fqn = new FullyQualifiedName(name);
var folderPath = $"{Features.Db.FeatureName}/entities";
_context.AssertDirectoryExists(Features.Db.FeatureName);
if (name.FullyQualifiedName() is { Length: 2 } fullName)
{
folderPath = Path.Combine(folderPath, fullName[0]);
name = fullName[1];
}
if (fqn.HasPath)
folderPath = Path.Combine(folderPath, fqn.Path);
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("%class_name%", fqn.PascalizedName);
code = code.Replace("%table_name%", fqn.SnakeCasedName.Pluralize());
code = code.Replace("%column_definitions%", columnDefinitions);
var fileName = $"{name.Underscore().ToLower()}.py";
var fileName = $"{fqn.SnakeCasedName}.py";
var filePath = Path.Combine(folderPath, fileName);
await _context.CreateFile(filePath, code);
@ -104,11 +101,11 @@ public partial class MycroForge
.ToLower();
var env = await _context.ReadFile($"{Features.Db.FeatureName}/env.py");
env = new DbEnvModifier(env, importPath, className).Rewrite();
env = new DbEnvModifier(env, importPath, fqn.PascalizedName).Rewrite();
await _context.WriteFile($"{Features.Db.FeatureName}/env.py", env);
var main = await _context.ReadFile("main.py");
main = new MainModifier(main).Initialize().Import(importPath, className).Rewrite();
main = new MainModifier(main).Initialize().Import(importPath, fqn.PascalizedName).Rewrite();
await _context.WriteFile("main.py", main);
}

View File

@ -57,18 +57,16 @@ public partial class MycroForge
private async Task ExecuteAsync(string name, bool withSession)
{
var fqn = new FullyQualifiedName(name);
var folderPath = string.Empty;
if (name.FullyQualifiedName() is { Length: 2} fullName)
{
folderPath = Path.Combine(folderPath, fullName[0]);
name = fullName[1];
}
if (fqn.HasPath)
folderPath = Path.Combine(folderPath, fqn.Path);
var filePath = Path.Combine(folderPath, $"{name.Underscore().ToLower()}.py");
var className = Path.GetFileName(name).Pascalize();
var code = string.Join('\n', withSession ? WithSessionTemplate : DefaultTemplate)
.Replace("%class_name%", className);
var filePath = Path.Combine(folderPath, $"{fqn.SnakeCasedName}.py");
var template = withSession ? WithSessionTemplate : DefaultTemplate;
var code = string.Join('\n', template)
.Replace("%class_name%", fqn.PascalizedName);
await _context.CreateFile(filePath, code);
}

View File

@ -2,11 +2,6 @@
public static class StringExtensions
{
public static string[] FullyQualifiedName(this string name)
{
return name.Split(':').Select(s => s.Trim()).ToArray();
}
public static string DeduplicateDots(this string path)
{
while (path.Contains(".."))

View File

@ -23,11 +23,10 @@ public sealed partial class Api : IFeature
private static readonly string[] MainTemplate =
[
"from fastapi import FastAPI",
"",
$"from {FeatureName}.routers import hello",
"",
"app = FastAPI()",
"",
$"from {FeatureName}.routers import hello",
"app.include_router(prefix=\"/hello\", router=hello.router)"
];