mycroforge/MycroForge.CLI/Commands/MycroForge.Init.cs
mdnapo 02a82589ae - Refactored init & features
- Extended documentation
2024-07-14 22:27:32 +02:00

117 lines
4.3 KiB
C#

using System.CommandLine;
using MycroForge.Core.Contract;
using MycroForge.CLI.Features;
using MycroForge.Core;
namespace MycroForge.CLI.Commands;
public partial class MycroForge
{
public partial class Init : Command, ISubCommandOf<MycroForge>
{
private static readonly string[] DefaultFeatures =
[
Features.Git.FeatureName,
Features.GitIgnore.FeatureName,
Features.Api.FeatureName,
Features.Db.FeatureName
];
private static readonly Argument<string> NameArgument =
new(name: "name", description: "The name of your project");
private static readonly Option<IEnumerable<string>> WithoutOption =
new Option<IEnumerable<string>>(name: "--without", description: "Features to exclude")
{
AllowMultipleArgumentsPerToken = true
}.FromAmong(DefaultFeatures);
private static readonly Option<int> ApiPortOption =
new(name: "--api-port", description: "The API port");
private static readonly Option<int> DbhPortOption = new(
aliases: ["--database-host-port", "--dbh-port"],
description: "The database host port"
);
private static readonly Option<int> DbuPortOption = new(
aliases: ["--database-ui-port", "--dbu-port"],
description: "The database UI port"
);
private readonly ProjectContext _context;
private readonly List<IFeature> _features;
private readonly OptionsContainer _optionsContainer;
public Init(ProjectContext context, OptionsContainer optionsContainer, IEnumerable<IFeature> features) :
base("init", "Initialize a new project")
{
_context = context;
_optionsContainer = optionsContainer;
_features = features.ToList();
AddArgument(NameArgument);
AddOption(WithoutOption);
AddOption(ApiPortOption);
AddOption(DbhPortOption);
AddOption(DbuPortOption);
this.SetHandler(ExecuteAsync, new Binder());
}
private async Task ExecuteAsync(Options options)
{
// Validate excluded features
var withoutList = (options.Without ?? Enumerable.Empty<string>()).ToList();
foreach (var feature in withoutList)
if (_features.All(f => f.Name != feature))
throw new Exception($"Feature {feature} does not exist.");
// Create the project directory and change the directory for the ProjectContext
var projectRoot = await CreateDirectory(options.Name);
_context.ChangeRootDirectory(projectRoot);
// Create the entrypoint file
await _context.CreateFile("main.py");
// Create the venv
await _context.Bash($"python3 -m venv {Path.Combine(projectRoot, ".venv")}");
// Pass feature arguments to the ArgsContainer
_optionsContainer.Set(options.ApiOptions);
_optionsContainer.Set(options.DbOptions);
// 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");
}
private async Task<string> CreateDirectory(string name)
{
var directory = Path.Combine(Directory.GetCurrentDirectory(), name);
if (Directory.Exists(directory))
throw new Exception($"Directory {directory} already exists.");
Console.WriteLine($"Creating directory {directory}");
Directory.CreateDirectory(directory);
await _context.Bash($"chmod -R 777 {directory}");
return directory;
}
}
}