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

View File

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

View File

@ -1,5 +1,6 @@
using System.CommandLine; using System.CommandLine;
using Humanizer; using Humanizer;
using MycroForge.CLI.CodeGen;
using MycroForge.Core.Contract; using MycroForge.Core.Contract;
using MycroForge.CLI.Extensions; using MycroForge.CLI.Extensions;
using MycroForge.Core; using MycroForge.Core;
@ -42,29 +43,30 @@ public partial class MycroForge
private async Task ExecuteAsync(string name) private async Task ExecuteAsync(string name)
{ {
var fqn = new FullyQualifiedName(name);
var folderPath = $"{Features.Api.FeatureName}/routers"; var folderPath = $"{Features.Api.FeatureName}/routers";
_context.AssertDirectoryExists(folderPath); _context.AssertDirectoryExists(folderPath);
if (name.FullyQualifiedName() is { Length: 2 } fullName) if (fqn.HasPath)
{ folderPath = Path.Combine(folderPath, fqn.Path);
folderPath = Path.Combine(folderPath, fullName[0]);
name = fullName[1];
}
var moduleImportPath = folderPath.Replace('\\', '.').Replace('/', '.'); var fileName = $"{fqn.SnakeCasedName}.py";
var moduleName = name.Underscore().ToLower();
var fileName = $"{moduleName}.py";
var filePath = Path.Combine(folderPath, fileName); var filePath = Path.Combine(folderPath, fileName);
await _context.CreateFile(filePath, Template); await _context.CreateFile(filePath, Template);
var moduleImportPath = folderPath
.Replace('\\', '.')
.Replace('/', '.');
var main = await _context.ReadFile("main.py"); var main = await _context.ReadFile("main.py");
main += string.Join('\n', main = new MainModifier(main)
$"\n\nfrom {moduleImportPath} import {moduleName}", .Initialize()
$"app.include_router(prefix=\"/{name.Kebaberize()}\", router={moduleName}.router)" .Import(from: moduleImportPath, import: fqn.SnakeCasedName)
); .IncludeRouter(prefix: name.Kebaberize(), router: fqn.SnakeCasedName)
.Rewrite();
await _context.WriteFile("main.py", main); 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) private async Task ExecuteAsync(string name, IEnumerable<string> columns)
{ {
var fqn = new FullyQualifiedName(name);
var folderPath = $"{Features.Db.FeatureName}/entities"; var folderPath = $"{Features.Db.FeatureName}/entities";
_context.AssertDirectoryExists(Features.Db.FeatureName); _context.AssertDirectoryExists(Features.Db.FeatureName);
if (name.FullyQualifiedName() is { Length: 2 } fullName) if (fqn.HasPath)
{ folderPath = Path.Combine(folderPath, fqn.Path);
folderPath = Path.Combine(folderPath, fullName[0]);
name = fullName[1];
}
var _columns = GetColumnDefinitions(columns.ToArray()); var _columns = GetColumnDefinitions(columns.ToArray());
var className = name.Underscore().Pascalize();
var typeImports = string.Join(", ", _columns.Select(c => c.OrmType.Split('(').First()).Distinct()); var typeImports = string.Join(", ", _columns.Select(c => c.OrmType.Split('(').First()).Distinct());
var columnDefinitions = string.Join("\n\t", _columns.Select(ColumnToString)); var columnDefinitions = string.Join("\n\t", _columns.Select(ColumnToString));
var code = string.Join('\n', Template); var code = string.Join('\n', Template);
code = code.Replace("%type_imports%", typeImports); code = code.Replace("%type_imports%", typeImports);
code = code.Replace("%class_name%", className); code = code.Replace("%class_name%", fqn.PascalizedName);
code = code.Replace("%table_name%", name.Underscore().ToLower().Pluralize()); code = code.Replace("%table_name%", fqn.SnakeCasedName.Pluralize());
code = code.Replace("%column_definitions%", columnDefinitions); code = code.Replace("%column_definitions%", columnDefinitions);
var fileName = $"{name.Underscore().ToLower()}.py"; var fileName = $"{fqn.SnakeCasedName}.py";
var filePath = Path.Combine(folderPath, fileName); var filePath = Path.Combine(folderPath, fileName);
await _context.CreateFile(filePath, code); await _context.CreateFile(filePath, code);
@ -104,11 +101,11 @@ public partial class MycroForge
.ToLower(); .ToLower();
var env = await _context.ReadFile($"{Features.Db.FeatureName}/env.py"); 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); await _context.WriteFile($"{Features.Db.FeatureName}/env.py", env);
var main = await _context.ReadFile("main.py"); 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); await _context.WriteFile("main.py", main);
} }

View File

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

View File

@ -2,11 +2,6 @@
public static class StringExtensions 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) public static string DeduplicateDots(this string path)
{ {
while (path.Contains("..")) while (path.Contains(".."))

View File

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