Refactored FullyQualifiedName functionality
This commit is contained in:
parent
02a82589ae
commit
be6b3691b4
@ -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)",
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
28
MycroForge.CLI/Commands/FullyQualifiedName.cs
Normal file
28
MycroForge.CLI/Commands/FullyQualifiedName.cs
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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(".."))
|
||||||
|
@ -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)"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user