feat: initial config command implementation
This commit is contained in:
@@ -6,6 +6,9 @@ static class HostBuilderExtensions
|
||||
{
|
||||
var registrar = new TypeRegistrar(builder);
|
||||
var app = new CommandApp<GenerateCommand>(registrar);
|
||||
|
||||
app.Configure(static c => c.AddCommand<ConfigCommand>("config"));
|
||||
|
||||
return app;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace AltGen.Console.Config;
|
||||
|
||||
// TODO: We should refactor this so that
|
||||
// we have a config add and a config remove command
|
||||
// the config add will have basically the same code
|
||||
// as below but the config remove will just
|
||||
// accept a provider identifier and remove it
|
||||
|
||||
sealed class ConfigCommand(
|
||||
IAnsiConsole console,
|
||||
IFileSystem fileSystem,
|
||||
IConfiguration config
|
||||
) : AsyncCommand<ConfigCommand.Settings>
|
||||
{
|
||||
static readonly JsonSerializerOptions JsonOptions = new()
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
PropertyNameCaseInsensitive = true,
|
||||
WriteIndented = true
|
||||
};
|
||||
readonly IAnsiConsole _console = console;
|
||||
readonly IFileSystem _fileSystem = fileSystem;
|
||||
readonly IConfiguration _config = config;
|
||||
|
||||
public class Settings(IFileSystem filesystem) : CommandSettings
|
||||
{
|
||||
readonly IFileSystem _fileSystem = filesystem;
|
||||
|
||||
[CommandArgument(1, "<provider>")]
|
||||
[Description("The provider to configure.")]
|
||||
public string Provider { get; init; } = string.Empty;
|
||||
|
||||
[CommandArgument(2, "<key>")]
|
||||
[Description("The key for the provider.")]
|
||||
public string Key { get; init; } = string.Empty;
|
||||
|
||||
[CommandOption("-d|--default")]
|
||||
[Description("Set the provider as the default.")]
|
||||
public bool Default { get; init; }
|
||||
|
||||
public string SettingsPath => _fileSystem.Path.Combine(AppContext.BaseDirectory, "appsettings.json");
|
||||
}
|
||||
|
||||
public override async Task<int> ExecuteAsync(CommandContext context, Settings settings)
|
||||
{
|
||||
var settingsExist = _fileSystem.File.Exists(settings.SettingsPath);
|
||||
|
||||
if (settingsExist is false)
|
||||
{
|
||||
var appSettings = new AppSettings([
|
||||
new(settings.Provider, settings.Key, settings.Default)
|
||||
]);
|
||||
|
||||
var json = JsonSerializer.Serialize(appSettings, JsonOptions);
|
||||
await _fileSystem.File.WriteAllTextAsync(settings.SettingsPath, json);
|
||||
_console.MarkupLine($"[bold]{settings.Provider}[/] has been configured.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
var existingJson = await _fileSystem.File.ReadAllTextAsync(settings.SettingsPath);
|
||||
var existingAppSettings = JsonSerializer.Deserialize<AppSettings>(existingJson, JsonOptions)
|
||||
?? throw new ConfigException("Failed to deserialize settings.");
|
||||
var updatedAppSettings = existingAppSettings.Update(settings);
|
||||
var udpatedJson = JsonSerializer.Serialize(updatedAppSettings, JsonOptions);
|
||||
await _fileSystem.File.WriteAllTextAsync(settings.SettingsPath, udpatedJson);
|
||||
_console.MarkupLine($"[bold]{settings.Provider}[/] has been configured.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
record AppSettings(ProviderSettings[] Providers)
|
||||
{
|
||||
public AppSettings Update(ConfigCommand.Settings settings)
|
||||
{
|
||||
var updatedProviders = Providers.Select(p =>
|
||||
{
|
||||
if (p.Provider == settings.Provider)
|
||||
{
|
||||
return p with { Key = settings.Key, Default = settings.Default };
|
||||
}
|
||||
|
||||
if (p.Provider != settings.Provider && settings.Default)
|
||||
{
|
||||
return p with { Default = false };
|
||||
}
|
||||
|
||||
return p;
|
||||
});
|
||||
|
||||
var provider = Providers.FirstOrDefault(p => p.Provider == settings.Provider);
|
||||
|
||||
if (provider is null)
|
||||
{
|
||||
var newProvider = new ProviderSettings(settings.Provider, settings.Key, settings.Default);
|
||||
return this with { Providers = [.. updatedProviders, newProvider] };
|
||||
}
|
||||
|
||||
return this with { Providers = [.. updatedProviders] };
|
||||
}
|
||||
}
|
||||
|
||||
record ProviderSettings(string Provider, string Key, bool Default);
|
||||
|
||||
class ConfigException(string message) : Exception(message)
|
||||
{
|
||||
}
|
||||
@@ -1,16 +1,4 @@
|
||||
// TODO: Need to implement config
|
||||
// command. This should allow
|
||||
// the user to set default values
|
||||
// for provider keys and a default
|
||||
// provider.
|
||||
//
|
||||
// For example setting a providers key
|
||||
// i.e. altgen config gemini mykey
|
||||
//
|
||||
// Or setting provider as default
|
||||
// i.e. altgen config gemini mykey --default
|
||||
|
||||
await Host.CreateDefaultBuilder(args)
|
||||
await Host.CreateDefaultBuilder(args)
|
||||
.ConfigureLogging(static l => l.ClearProviders())
|
||||
.ConfigureServices(static (_, services) =>
|
||||
{
|
||||
@@ -20,4 +8,4 @@ await Host.CreateDefaultBuilder(args)
|
||||
.AddStandardResilienceHandler();
|
||||
})
|
||||
.BuildApp()
|
||||
.RunAsync(args);
|
||||
.RunAsync(args);
|
||||
@@ -4,12 +4,13 @@ global using System.Net.Http.Headers;
|
||||
global using System.Text.Json;
|
||||
|
||||
global using AltGen.Console.Common;
|
||||
global using AltGen.Console.Generated;
|
||||
global using AltGen.Console.Config;
|
||||
global using AltGen.Console.Generate;
|
||||
global using AltGen.Console.Generated;
|
||||
|
||||
global using Microsoft.Extensions.DependencyInjection;
|
||||
global using Microsoft.Extensions.Hosting;
|
||||
global using Microsoft.Extensions.Logging;
|
||||
|
||||
global using Spectre.Console;
|
||||
global using Spectre.Console.Cli;
|
||||
global using Spectre.Console.Cli;
|
||||
Reference in New Issue
Block a user