From 414e712f515f5b18c8d118921efeb52f52f3d280 Mon Sep 17 00:00:00 2001 From: Stevan Freeborn <65925598+StevanFreeborn@users.noreply.github.com> Date: Fri, 14 Mar 2025 22:02:22 -0500 Subject: [PATCH] feat: add app settings manager to do the reading and writing --- src/AltGen.API/AltGen.API.csproj | 1 + .../Unit/AddConfigCommandTests.cs | 91 +++++----------- .../Unit/AppSettingsManagerTests.cs | 100 ++++++++++++++++++ .../Unit/AppSettingsTests.cs | 10 +- .../Unit/ListConfigCommandTests.cs | 68 +++--------- .../Unit/RemoveConfigCommandTests.cs | 67 ++++-------- src/AltGen.Console/AltGen.Console.csproj | 1 + src/AltGen.Console/Config/AddConfigCommand.cs | 25 ++--- .../Config/AppSettingsManager.cs | 30 ++++++ .../Config/IAppSettingsManager.cs | 8 ++ .../Config/ListConfigCommand.cs | 16 ++- .../Config/RemoveConfigCommand.cs | 23 ++-- src/AltGen.Console/Generate/IAltGenService.cs | 2 +- src/AltGen.Console/Program.cs | 1 + 14 files changed, 229 insertions(+), 214 deletions(-) create mode 100644 src/AltGen.Console.Tests/Unit/AppSettingsManagerTests.cs create mode 100644 src/AltGen.Console/Config/AppSettingsManager.cs create mode 100644 src/AltGen.Console/Config/IAppSettingsManager.cs diff --git a/src/AltGen.API/AltGen.API.csproj b/src/AltGen.API/AltGen.API.csproj index d73d24c..3aabe5f 100644 --- a/src/AltGen.API/AltGen.API.csproj +++ b/src/AltGen.API/AltGen.API.csproj @@ -11,6 +11,7 @@ + diff --git a/src/AltGen.Console.Tests/Unit/AddConfigCommandTests.cs b/src/AltGen.Console.Tests/Unit/AddConfigCommandTests.cs index 15e3344..a7af256 100644 --- a/src/AltGen.Console.Tests/Unit/AddConfigCommandTests.cs +++ b/src/AltGen.Console.Tests/Unit/AddConfigCommandTests.cs @@ -2,35 +2,28 @@ namespace AltGen.Console.Tests.Unit; public class AddConfigCommandTests : IDisposable { - readonly Mock _fileSystem = new(); + readonly Mock _mockSettingsManager = new(); readonly TestConsole _testConsole = new(); readonly AddConfigCommand _sut; public AddConfigCommandTests() { - _sut = new AddConfigCommand(_testConsole, _fileSystem.Object); + _sut = new AddConfigCommand(_testConsole, _mockSettingsManager.Object); } [Fact] public async Task ExecuteAsync_WhenSettingsDoNotExist_ItShouldCreateSettings() { - var testSettingsPath = "appsettings.json"; var expectedAppSettings = new AppSettings([ new("provider", "key", false) ]); - var expectedJson = JsonSerializer.Serialize(expectedAppSettings, JsonOptions.Default); - - _fileSystem - .Setup(static x => x.Path.Combine(It.IsAny(), It.IsAny())) - .Returns(testSettingsPath); - - _fileSystem - .Setup(static x => x.File.Exists(It.IsAny())) + _mockSettingsManager + .Setup(static x => x.AppSettingsExist()) .Returns(false); - var commandSettings = new AddConfigCommand.Settings(_fileSystem.Object) + var commandSettings = new AddConfigCommand.Settings() { Provider = "provider", Key = "key", @@ -40,39 +33,36 @@ public class AddConfigCommandTests : IDisposable result.Should().Be(0); - _fileSystem - .Verify( - x => x.File.WriteAllTextAsync(testSettingsPath, expectedJson, default), - Times.Once - ); + _mockSettingsManager.Verify( + static x => x.SaveAppSettingsAsync(It.Is( + static x => x.Providers[0].Provider == "provider" && + x.Providers[0].Key == "key" && + x.Providers[0].Default == false + )), + Times.Once + ); } [Fact] public async Task ExecuteAsync_WhenSettingsExist_ItShouldUpdateSettings() { - var testSettingsPath = "appsettings.json"; var existingAppSettings = new AppSettings([ new("existing", "existing", false) ]); - var existingJson = JsonSerializer.Serialize(existingAppSettings, JsonOptions.Default); + var expectedAppSettings = new AppSettings([ new("existing", "key", true) ]); - var expectedJson = JsonSerializer.Serialize(expectedAppSettings, JsonOptions.Default); - _fileSystem - .Setup(static x => x.Path.Combine(It.IsAny(), It.IsAny())) - .Returns(testSettingsPath); - - _fileSystem - .Setup(static x => x.File.Exists(It.IsAny())) + _mockSettingsManager + .Setup(static x => x.AppSettingsExist()) .Returns(true); - _fileSystem - .Setup(static x => x.File.ReadAllTextAsync(It.IsAny(), default)) - .ReturnsAsync(existingJson); + _mockSettingsManager + .Setup(static x => x.GetAppSettingsAsync()) + .ReturnsAsync(existingAppSettings); - var commandSettings = new AddConfigCommand.Settings(_fileSystem.Object) + var commandSettings = new AddConfigCommand.Settings() { Provider = "existing", Key = "key", @@ -83,39 +73,14 @@ public class AddConfigCommandTests : IDisposable result.Should().Be(0); - _fileSystem - .Verify( - x => x.File.WriteAllTextAsync(testSettingsPath, expectedJson, default), - Times.Once - ); - } - - [Fact] - public async Task ExecuteAsync_WhenSettingsExistButCanNotBeDeserialized_ItShouldThrow() - { - var testSettingsPath = "appsettings.json"; - - _fileSystem - .Setup(static x => x.Path.Combine(It.IsAny(), It.IsAny())) - .Returns(testSettingsPath); - - _fileSystem - .Setup(static x => x.File.Exists(It.IsAny())) - .Returns(true); - - _fileSystem - .Setup(static x => x.File.ReadAllTextAsync(It.IsAny(), default)) - .ReturnsAsync("null"); - - var commandSettings = new AddConfigCommand.Settings(_fileSystem.Object) - { - Provider = "provider", - Key = "key", - }; - - var act = async () => await _sut.ExecuteAsync(null!, commandSettings); - - await act.Should().ThrowAsync(); + _mockSettingsManager.Verify( + static x => x.SaveAppSettingsAsync(It.Is( + static x => x.Providers[0].Provider == "existing" && + x.Providers[0].Key == "key" && + x.Providers[0].Default == true + )), + Times.Once + ); } public void Dispose() diff --git a/src/AltGen.Console.Tests/Unit/AppSettingsManagerTests.cs b/src/AltGen.Console.Tests/Unit/AppSettingsManagerTests.cs new file mode 100644 index 0000000..164d6a9 --- /dev/null +++ b/src/AltGen.Console.Tests/Unit/AppSettingsManagerTests.cs @@ -0,0 +1,100 @@ +namespace AltGen.Console.Tests.Unit; + +public class AppSettingsManagerTests +{ + readonly Mock _mockFileSystem = new(); + readonly AppSettingsManager _sut; + + public AppSettingsManagerTests() + { + _mockFileSystem + .Setup(static x => x.Path.Combine(It.IsAny(), It.IsAny())) + .Returns("path"); + + _sut = new AppSettingsManager(_mockFileSystem.Object); + } + + [Fact] + public void AppSettingsExist_WhenSettingsDoNotExist_ItShouldReturnFalse() + { + _mockFileSystem + .Setup(static x => x.Path.Exists(It.IsAny())) + .Returns(false); + + var result = _sut.AppSettingsExist(); + + result.Should().BeFalse(); + } + + [Fact] + public void AppSettingsExist_WhenSettingsExist_ItShouldReturnTrue() + { + _mockFileSystem + .Setup(static x => x.Path.Exists(It.IsAny())) + .Returns(true); + + var result = _sut.AppSettingsExist(); + + result.Should().BeTrue(); + } + + [Fact] + public async Task GetAppSettingsAsync_WhenSettingsExist_ItShouldReturnSettings() + { + var testSettings = new AppSettings([ + new("provider", "key", false) + ]); + + var json = JsonSerializer.Serialize(testSettings, JsonOptions.Default); + + _mockFileSystem + .Setup(static x => x.File.ReadAllTextAsync(It.IsAny(), default)) + .ReturnsAsync(json); + + var result = await _sut.GetAppSettingsAsync(); + + result.Should().BeEquivalentTo(testSettings); + } + + [Fact] + public async Task GetAppSettingsAsync_WhenDeserializingSettingsIsNull_ItShouldReturnEmptySettings() + { + _mockFileSystem + .Setup(static x => x.File.ReadAllTextAsync(It.IsAny(), default)) + .ReturnsAsync("null"); + + var result = await _sut.GetAppSettingsAsync(); + + result.Should().BeEquivalentTo(new AppSettings([])); + } + + [Fact] + public async Task GetAppSettingsAsync_WhenSettingsDoNotExist_ItShouldThrow() + { + _mockFileSystem + .Setup(static x => x.File.ReadAllTextAsync(It.IsAny(), default)) + .ThrowsAsync(new FileNotFoundException()); + + var action = _sut.GetAppSettingsAsync; + + await action.Should().ThrowAsync(); + } + + [Fact] + public async Task SaveAppSettingsAsync_WhenCalled_ItShouldSaveSettings() + { + _mockFileSystem + .Setup(static x => x.File.WriteAllTextAsync(It.IsAny(), It.IsAny(), default)) + .Returns(Task.CompletedTask); + + var testSettings = new AppSettings([ + new("provider", "key", false) + ]); + + var json = JsonSerializer.Serialize(testSettings, JsonOptions.Default); + + await _sut.SaveAppSettingsAsync(testSettings); + + _mockFileSystem.Verify(x => x.File.WriteAllTextAsync(It.IsAny(), json, default), Times.Once); + } +} \ No newline at end of file diff --git a/src/AltGen.Console.Tests/Unit/AppSettingsTests.cs b/src/AltGen.Console.Tests/Unit/AppSettingsTests.cs index bb5b868..e50e9ed 100644 --- a/src/AltGen.Console.Tests/Unit/AppSettingsTests.cs +++ b/src/AltGen.Console.Tests/Unit/AppSettingsTests.cs @@ -2,14 +2,12 @@ namespace AltGen.Console.Tests.Unit; public class AppSettingsTests { - readonly Mock _fileSystemMock = new(); - [Fact] public void AddOrUpdateProvider_WhenProviderDoesNotExist_ItShouldAddProvider() { var providerSettings = new ProviderSettings("provider", "key", true); - var commandSettings = new AddConfigCommand.Settings(_fileSystemMock.Object) + var commandSettings = new AddConfigCommand.Settings() { Provider = providerSettings.Provider, Key = providerSettings.Key, @@ -29,7 +27,7 @@ public class AppSettingsTests var providerSettings = new ProviderSettings("provider", "key", true); var existingProviderSettings = new ProviderSettings("provider", "key", false); - var commandSettings = new AddConfigCommand.Settings(_fileSystemMock.Object) + var commandSettings = new AddConfigCommand.Settings() { Provider = providerSettings.Provider, Key = providerSettings.Key, @@ -48,7 +46,7 @@ public class AppSettingsTests var providerSettings = new ProviderSettings("claude", "key", true); var existingProviderSettings = new ProviderSettings("gemini", "key", true); - var commandSettings = new AddConfigCommand.Settings(_fileSystemMock.Object) + var commandSettings = new AddConfigCommand.Settings() { Provider = providerSettings.Provider, Key = providerSettings.Key, @@ -69,7 +67,7 @@ public class AppSettingsTests { var existingProviderSettings = new ProviderSettings("provider", "key", true); - var commandSettings = new RemoveConfigCommand.Settings(_fileSystemMock.Object) + var commandSettings = new RemoveConfigCommand.Settings() { Provider = existingProviderSettings.Provider, }; diff --git a/src/AltGen.Console.Tests/Unit/ListConfigCommandTests.cs b/src/AltGen.Console.Tests/Unit/ListConfigCommandTests.cs index d17cf11..d3120fd 100644 --- a/src/AltGen.Console.Tests/Unit/ListConfigCommandTests.cs +++ b/src/AltGen.Console.Tests/Unit/ListConfigCommandTests.cs @@ -2,26 +2,20 @@ namespace AltGen.Console.Tests.Unit; public class ListConfigCommandTests : IDisposable { - readonly Mock _fileSystem = new(); + readonly Mock _mockSettingsManager = new(); readonly TestConsole _testConsole = new(); readonly ListConfigCommand _sut; public ListConfigCommandTests() { - _sut = new ListConfigCommand(_testConsole, _fileSystem.Object); + _sut = new ListConfigCommand(_testConsole, _mockSettingsManager.Object); } [Fact] public async Task ExecuteAsync_WhenSettingsDoNotExist_ItShouldOutputNoSettings() { - var testSettingsPath = "appsettings.json"; - - _fileSystem - .Setup(static x => x.Path.Combine(It.IsAny(), It.IsAny())) - .Returns(testSettingsPath); - - _fileSystem - .Setup(static x => x.File.Exists(It.IsAny())) + _mockSettingsManager + .Setup(static x => x.AppSettingsExist()) .Returns(false); var result = await _sut.ExecuteAsync(null!); @@ -37,23 +31,17 @@ public class ListConfigCommandTests : IDisposable [Fact] public async Task ExecuteAsync_WhenSettingsExist_ItShouldOutputSettings() { - var testSettingsPath = "appsettings.json"; var testSettings = new AppSettings([ new("provider", "key", false) ]); - var testSettingsJson = JsonSerializer.Serialize(testSettings, JsonOptions.Default); - _fileSystem - .Setup(static x => x.Path.Combine(It.IsAny(), It.IsAny())) - .Returns(testSettingsPath); - - _fileSystem - .Setup(static x => x.File.Exists(It.IsAny())) + _mockSettingsManager + .Setup(static x => x.AppSettingsExist()) .Returns(true); - _fileSystem - .Setup(static x => x.File.ReadAllTextAsync(It.IsAny(), default)) - .ReturnsAsync(testSettingsJson); + _mockSettingsManager + .Setup(static x => x.GetAppSettingsAsync()) + .ReturnsAsync(testSettings); var result = await _sut.ExecuteAsync(null!); @@ -68,23 +56,17 @@ public class ListConfigCommandTests : IDisposable [Fact] public async Task ExecuteAsync_WhenSettingsExistAndDefault_ItShouldOutputSettings() { - var testSettingsPath = "appsettings.json"; var testSettings = new AppSettings([ new("provider", "key", true) ]); - var testSettingsJson = JsonSerializer.Serialize(testSettings, JsonOptions.Default); - _fileSystem - .Setup(static x => x.Path.Combine(It.IsAny(), It.IsAny())) - .Returns(testSettingsPath); - - _fileSystem - .Setup(static x => x.File.Exists(It.IsAny())) + _mockSettingsManager + .Setup(static x => x.AppSettingsExist()) .Returns(true); - _fileSystem - .Setup(static x => x.File.ReadAllTextAsync(It.IsAny(), default)) - .ReturnsAsync(testSettingsJson); + _mockSettingsManager + .Setup(static x => x.GetAppSettingsAsync()) + .ReturnsAsync(testSettings); var result = await _sut.ExecuteAsync(null!); @@ -96,28 +78,6 @@ public class ListConfigCommandTests : IDisposable .Contain("provider key (default)"); } - [Fact] - public async Task ExecuteAsync_WhenSettingsCanNotBeDeserialized_ItShouldThrowConfigException() - { - var testSettingsPath = "appsettings.json"; - - _fileSystem - .Setup(static x => x.Path.Combine(It.IsAny(), It.IsAny())) - .Returns(testSettingsPath); - - _fileSystem - .Setup(static x => x.File.Exists(It.IsAny())) - .Returns(true); - - _fileSystem - .Setup(static x => x.File.ReadAllTextAsync(It.IsAny(), default)) - .ReturnsAsync("null"); - - var action = async () => await _sut.ExecuteAsync(null!); - - await action.Should().ThrowAsync(); - } - public void Dispose() { _testConsole.Dispose(); diff --git a/src/AltGen.Console.Tests/Unit/RemoveConfigCommandTests.cs b/src/AltGen.Console.Tests/Unit/RemoveConfigCommandTests.cs index 3b8fed3..e49c1ee 100644 --- a/src/AltGen.Console.Tests/Unit/RemoveConfigCommandTests.cs +++ b/src/AltGen.Console.Tests/Unit/RemoveConfigCommandTests.cs @@ -2,29 +2,23 @@ namespace AltGen.Console.Tests.Unit; public class RemoveConfigCommandTests : IDisposable { - readonly Mock _fileSystem = new(); + readonly Mock _mockSettingsManager = new(); readonly TestConsole _testConsole = new(); readonly RemoveConfigCommand _sut; public RemoveConfigCommandTests() { - _sut = new RemoveConfigCommand(_fileSystem.Object, _testConsole); + _sut = new RemoveConfigCommand(_testConsole, _mockSettingsManager.Object); } [Fact] public async Task ExecuteAsync_WhenSettingsDoNotExist_ItShouldThrow() { - var testSettingsPath = "appsettings.json"; - - _fileSystem - .Setup(static x => x.Path.Combine(It.IsAny(), It.IsAny())) - .Returns(testSettingsPath); - - _fileSystem - .Setup(static x => x.Path.Exists(It.IsAny())) + _mockSettingsManager + .Setup(static x => x.AppSettingsExist()) .Returns(false); - var commandSettings = new RemoveConfigCommand.Settings(_fileSystem.Object) + var commandSettings = new RemoveConfigCommand.Settings() { Provider = "provider", }; @@ -38,23 +32,17 @@ public class RemoveConfigCommandTests : IDisposable [Fact] public async Task ExecuteAsync_WhenProviderDoesNotExist_ItShouldDoNothing() { - var testSettingsPath = "appsettings.json"; var testSettings = new AppSettings([]); - var testSettingsJson = JsonSerializer.Serialize(testSettings, JsonOptions.Default); - _fileSystem - .Setup(static x => x.Path.Combine(It.IsAny(), It.IsAny())) - .Returns(testSettingsPath); - - _fileSystem - .Setup(static x => x.Path.Exists(It.IsAny())) + _mockSettingsManager + .Setup(static x => x.AppSettingsExist()) .Returns(true); - _fileSystem - .Setup(static x => x.File.ReadAllTextAsync(It.IsAny(), default)) - .ReturnsAsync(testSettingsJson); + _mockSettingsManager + .Setup(static x => x.GetAppSettingsAsync()) + .ReturnsAsync(testSettings); - var commandSettings = new RemoveConfigCommand.Settings(_fileSystem.Object) + var commandSettings = new RemoveConfigCommand.Settings() { Provider = "provider", }; @@ -63,35 +51,27 @@ public class RemoveConfigCommandTests : IDisposable result.Should().Be(0); - _fileSystem - .Verify( - x => x.File.WriteAllTextAsync(testSettingsPath, testSettingsJson, default), - Times.Once - ); + _mockSettingsManager.Verify(x => x.SaveAppSettingsAsync(testSettings), Times.Once); } [Fact] public async Task ExecuteAsync_WhenProviderExists_ItShouldRemoveProviderFromSettings() { - var testSettingsPath = "appsettings.json"; var testSettings = new AppSettings([ new("provider", "key", false) ]); - var testSettingsJson = JsonSerializer.Serialize(testSettings, JsonOptions.Default); - _fileSystem - .Setup(static x => x.Path.Combine(It.IsAny(), It.IsAny())) - .Returns(testSettingsPath); + var expectedSettings = new AppSettings([]); - _fileSystem - .Setup(static x => x.Path.Exists(It.IsAny())) + _mockSettingsManager + .Setup(static x => x.AppSettingsExist()) .Returns(true); - _fileSystem - .Setup(static x => x.File.ReadAllTextAsync(It.IsAny(), default)) - .ReturnsAsync(testSettingsJson); + _mockSettingsManager + .Setup(static x => x.GetAppSettingsAsync()) + .ReturnsAsync(testSettings); - var commandSettings = new RemoveConfigCommand.Settings(_fileSystem.Object) + var commandSettings = new RemoveConfigCommand.Settings() { Provider = "provider", }; @@ -100,14 +80,7 @@ public class RemoveConfigCommandTests : IDisposable result.Should().Be(0); - var expectedSettings = new AppSettings([]); - var expectedSettingsJson = JsonSerializer.Serialize(expectedSettings, JsonOptions.Default); - - _fileSystem - .Verify( - x => x.File.WriteAllTextAsync(testSettingsPath, expectedSettingsJson, default), - Times.Once - ); + _mockSettingsManager.Verify(x => x.SaveAppSettingsAsync(expectedSettings), Times.Once); } public void Dispose() diff --git a/src/AltGen.Console/AltGen.Console.csproj b/src/AltGen.Console/AltGen.Console.csproj index f192040..089a558 100644 --- a/src/AltGen.Console/AltGen.Console.csproj +++ b/src/AltGen.Console/AltGen.Console.csproj @@ -17,6 +17,7 @@ + diff --git a/src/AltGen.Console/Config/AddConfigCommand.cs b/src/AltGen.Console/Config/AddConfigCommand.cs index ca51f94..5d69f08 100644 --- a/src/AltGen.Console/Config/AddConfigCommand.cs +++ b/src/AltGen.Console/Config/AddConfigCommand.cs @@ -2,16 +2,14 @@ namespace AltGen.Console.Config; sealed class AddConfigCommand( IAnsiConsole console, - IFileSystem fileSystem + IAppSettingsManager settingsManager ) : AsyncCommand { readonly IAnsiConsole _console = console; - readonly IFileSystem _fileSystem = fileSystem; + readonly IAppSettingsManager _settingsManager = settingsManager; - public class Settings(IFileSystem filesystem) : CommandSettings + public class Settings : CommandSettings { - readonly IFileSystem _fileSystem = filesystem; - [CommandArgument(1, "")] [Description("The provider to configure.")] public string Provider { get; init; } = string.Empty; @@ -23,32 +21,23 @@ sealed class AddConfigCommand( [CommandOption("-d|--default")] [Description("Set the provider as the default.")] public bool Default { get; init; } - - public string SettingsPath => _fileSystem.Path.Combine(AppContext.BaseDirectory, AppSettings.SettingsFileName); } public override async Task ExecuteAsync(CommandContext context, Settings settings) { - var settingsExist = _fileSystem.File.Exists(settings.SettingsPath); - - if (settingsExist is false) + if (_settingsManager.AppSettingsExist() is false) { var appSettings = new AppSettings([ new(settings.Provider, settings.Key, settings.Default) ]); - - var json = JsonSerializer.Serialize(appSettings, JsonOptions.Default); - await _fileSystem.File.WriteAllTextAsync(settings.SettingsPath, json); + await _settingsManager.SaveAppSettingsAsync(appSettings); _console.MarkupLine($"[bold]{settings.Provider}[/] has been configured."); return 0; } - var existingJson = await _fileSystem.File.ReadAllTextAsync(settings.SettingsPath); - var existingAppSettings = JsonSerializer.Deserialize(existingJson, JsonOptions.Default) - ?? throw new ConfigException("Failed to deserialize settings."); + var existingAppSettings = await _settingsManager.GetAppSettingsAsync(); var updatedAppSettings = existingAppSettings.AddOrUpdateProvider(settings); - var udpatedJson = JsonSerializer.Serialize(updatedAppSettings, JsonOptions.Default); - await _fileSystem.File.WriteAllTextAsync(settings.SettingsPath, udpatedJson); + await _settingsManager.SaveAppSettingsAsync(updatedAppSettings); _console.MarkupLine($"[bold]{settings.Provider}[/] has been configured."); return 0; } diff --git a/src/AltGen.Console/Config/AppSettingsManager.cs b/src/AltGen.Console/Config/AppSettingsManager.cs new file mode 100644 index 0000000..db8ae4e --- /dev/null +++ b/src/AltGen.Console/Config/AppSettingsManager.cs @@ -0,0 +1,30 @@ +namespace AltGen.Console.Config; + +class AppSettingsManager(IFileSystem fileSystem) : IAppSettingsManager +{ + const string SettingsFileName = "appsettings.json"; + readonly IFileSystem _fileSystem = fileSystem; + + public bool AppSettingsExist() + { + return _fileSystem.Path.Exists(SettingsFileName); + } + + public async Task GetAppSettingsAsync() + { + var existingJson = await _fileSystem.File.ReadAllTextAsync(GetSettingsPath()); + var existingAppSettings = JsonSerializer.Deserialize(existingJson, JsonOptions.Default) ?? new AppSettings([]); + return existingAppSettings; + } + + public async Task SaveAppSettingsAsync(AppSettings appSettings) + { + var json = JsonSerializer.Serialize(appSettings, JsonOptions.Default); + await _fileSystem.File.WriteAllTextAsync(GetSettingsPath(), json); + } + + string GetSettingsPath() + { + return _fileSystem.Path.Combine(AppContext.BaseDirectory, SettingsFileName); + } +} \ No newline at end of file diff --git a/src/AltGen.Console/Config/IAppSettingsManager.cs b/src/AltGen.Console/Config/IAppSettingsManager.cs new file mode 100644 index 0000000..67a5886 --- /dev/null +++ b/src/AltGen.Console/Config/IAppSettingsManager.cs @@ -0,0 +1,8 @@ +namespace AltGen.Console.Config; + +interface IAppSettingsManager +{ + bool AppSettingsExist(); + Task GetAppSettingsAsync(); + Task SaveAppSettingsAsync(AppSettings appSettings); +} \ No newline at end of file diff --git a/src/AltGen.Console/Config/ListConfigCommand.cs b/src/AltGen.Console/Config/ListConfigCommand.cs index 31d1918..8f42182 100644 --- a/src/AltGen.Console/Config/ListConfigCommand.cs +++ b/src/AltGen.Console/Config/ListConfigCommand.cs @@ -1,25 +1,23 @@ namespace AltGen.Console.Config; -sealed class ListConfigCommand(IAnsiConsole console, IFileSystem fileSystem) : AsyncCommand +sealed class ListConfigCommand( + IAnsiConsole console, + IAppSettingsManager settingsManager +) : AsyncCommand { readonly IAnsiConsole _console = console; - readonly IFileSystem _fileSystem = fileSystem; + readonly IAppSettingsManager _settingsManager = settingsManager; public override async Task ExecuteAsync(CommandContext context) { - var settingsPath = _fileSystem.Path.Combine(AppContext.BaseDirectory, AppSettings.SettingsFileName); - var settingsExist = _fileSystem.File.Exists(settingsPath); - - if (settingsExist is false) + if (_settingsManager.AppSettingsExist() is false) { _console.MarkupLine("No settings found."); return 0; } - var settingsJson = await _fileSystem.File.ReadAllTextAsync(settingsPath); - var appSettings = JsonSerializer.Deserialize(settingsJson, JsonOptions.Default) - ?? throw new ConfigException("Failed to deserialize settings."); + var appSettings = await _settingsManager.GetAppSettingsAsync(); foreach (var provider in appSettings.Providers) { diff --git a/src/AltGen.Console/Config/RemoveConfigCommand.cs b/src/AltGen.Console/Config/RemoveConfigCommand.cs index 7bc0540..925f408 100644 --- a/src/AltGen.Console/Config/RemoveConfigCommand.cs +++ b/src/AltGen.Console/Config/RemoveConfigCommand.cs @@ -1,39 +1,30 @@ namespace AltGen.Console.Config; sealed class RemoveConfigCommand( - IFileSystem fileSystem, - IAnsiConsole console + IAnsiConsole console, + IAppSettingsManager settingsManager ) : AsyncCommand { - readonly IFileSystem _fileSystem = fileSystem; readonly IAnsiConsole _console = console; + readonly IAppSettingsManager _settingsManager = settingsManager; - public class Settings(IFileSystem fileSystem) : CommandSettings + public class Settings : CommandSettings { - readonly IFileSystem _fileSystem = fileSystem; - [CommandArgument(1, "")] [Description("The provider to remove.")] public string Provider { get; init; } = string.Empty; - - public string SettingsPath => _fileSystem.Path.Combine(AppContext.BaseDirectory, AppSettings.SettingsFileName); } public override async Task ExecuteAsync(CommandContext context, Settings settings) { - var exists = _fileSystem.Path.Exists(settings.SettingsPath); - - if (exists is false) + if (_settingsManager.AppSettingsExist() is false) { throw new ConfigException("No existing settings found."); } - var settingsJson = await _fileSystem.File.ReadAllTextAsync(settings.SettingsPath); - var appSettings = JsonSerializer.Deserialize(settingsJson, JsonOptions.Default) - ?? throw new ConfigException("Failed to deserialize app settings."); + var appSettings = await _settingsManager.GetAppSettingsAsync(); var updatedAppSettings = appSettings.RemoveProvider(settings); - var updatedJson = JsonSerializer.Serialize(updatedAppSettings, JsonOptions.Default); - await _fileSystem.File.WriteAllTextAsync(settings.SettingsPath, updatedJson); + await _settingsManager.SaveAppSettingsAsync(updatedAppSettings); _console.MarkupLine($"[bold]{settings.Provider}[/] has been removed."); return 0; } diff --git a/src/AltGen.Console/Generate/IAltGenService.cs b/src/AltGen.Console/Generate/IAltGenService.cs index 1b2b14b..81101a0 100644 --- a/src/AltGen.Console/Generate/IAltGenService.cs +++ b/src/AltGen.Console/Generate/IAltGenService.cs @@ -1,4 +1,4 @@ interface IAltGenService { Task GenerateAltTextAsync(GenerateAltTextRequest req); -} +} \ No newline at end of file diff --git a/src/AltGen.Console/Program.cs b/src/AltGen.Console/Program.cs index 48aaed7..cc4380e 100644 --- a/src/AltGen.Console/Program.cs +++ b/src/AltGen.Console/Program.cs @@ -3,6 +3,7 @@ .ConfigureServices(static (_, services) => { services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(AnsiConsole.Console); services.AddHttpClient() .AddStandardResilienceHandler();