diff --git a/src/Artemis.Core/DryIoc/ContainerExtensions.cs b/src/Artemis.Core/DryIoc/ContainerExtensions.cs index 8aa35b65f..5e057e049 100644 --- a/src/Artemis.Core/DryIoc/ContainerExtensions.cs +++ b/src/Artemis.Core/DryIoc/ContainerExtensions.cs @@ -31,11 +31,9 @@ public static class ContainerExtensions // Bind storage container.RegisterDelegate(() => StorageManager.CreateRepository(Constants.DataFolder), Reuse.Singleton); - container.Register(Reuse.Singleton); container.RegisterMany(storageAssembly, type => type.IsAssignableTo(), Reuse.Singleton); // Bind migrations - container.RegisterMany(storageAssembly, type => type.IsAssignableTo(), Reuse.Singleton, nonPublicServiceTypes: true); container.RegisterMany(storageAssembly, type => type.IsAssignableTo(), Reuse.Singleton, nonPublicServiceTypes: true); container.RegisterMany(coreAssembly, type => type.IsAssignableTo(), Reuse.Singleton); diff --git a/src/Artemis.Core/Models/Surface/ArtemisDeviceInputIdentifier.cs b/src/Artemis.Core/Models/Surface/ArtemisDeviceInputIdentifier.cs index 6d101cdf7..410134624 100644 --- a/src/Artemis.Core/Models/Surface/ArtemisDeviceInputIdentifier.cs +++ b/src/Artemis.Core/Models/Surface/ArtemisDeviceInputIdentifier.cs @@ -14,7 +14,7 @@ public class ArtemisDeviceInputIdentifier /// used by /// /// A value used to identify the device - internal ArtemisDeviceInputIdentifier(string inputProvider, object identifier) + internal ArtemisDeviceInputIdentifier(string inputProvider, string identifier) { InputProvider = inputProvider; Identifier = identifier; @@ -28,5 +28,5 @@ public class ArtemisDeviceInputIdentifier /// /// Gets or sets a value used to identify the device /// - public object Identifier { get; set; } + public string Identifier { get; set; } } \ No newline at end of file diff --git a/src/Artemis.Core/Plugins/Settings/IPluginSetting.cs b/src/Artemis.Core/Plugins/Settings/IPluginSetting.cs index 57a454420..a33844c1f 100644 --- a/src/Artemis.Core/Plugins/Settings/IPluginSetting.cs +++ b/src/Artemis.Core/Plugins/Settings/IPluginSetting.cs @@ -1,4 +1,5 @@ using System; +using System.Text.Json; namespace Artemis.Core; @@ -7,6 +8,11 @@ namespace Artemis.Core; /// public interface IPluginSetting { + /// + /// The JSON serializer options used when serializing settings + /// + protected static readonly JsonSerializerOptions SerializerOptions = CoreJson.GetJsonSerializerOptions(); + /// /// The name of the setting, unique to this plugin /// diff --git a/src/Artemis.Core/Plugins/Settings/PluginSetting.cs b/src/Artemis.Core/Plugins/Settings/PluginSetting.cs index 8f14d542f..390566c76 100644 --- a/src/Artemis.Core/Plugins/Settings/PluginSetting.cs +++ b/src/Artemis.Core/Plugins/Settings/PluginSetting.cs @@ -1,5 +1,6 @@ using System; using System.Text.Json; +using System.Text.Json.Nodes; using Artemis.Storage.Entities.Plugins; using Artemis.Storage.Repositories.Interfaces; @@ -23,7 +24,7 @@ public class PluginSetting : CorePropertyChanged, IPluginSetting Name = pluginSettingEntity.Name; try { - _value = CoreJson.Deserialize(pluginSettingEntity.Value)!; + _value = pluginSettingEntity.Value.Deserialize(IPluginSetting.SerializerOptions) ?? default!; } catch (JsonException) { @@ -76,7 +77,7 @@ public class PluginSetting : CorePropertyChanged, IPluginSetting public string Name { get; } /// - public bool HasChanged => CoreJson.Serialize(Value) != _pluginSettingEntity.Value; + public bool HasChanged => !JsonNode.DeepEquals(JsonSerializer.SerializeToNode(Value, IPluginSetting.SerializerOptions), _pluginSettingEntity.Value); /// public bool AutoSave { get; set; } @@ -84,7 +85,7 @@ public class PluginSetting : CorePropertyChanged, IPluginSetting /// public void RejectChanges() { - Value = CoreJson.Deserialize(_pluginSettingEntity.Value); + Value = _pluginSettingEntity.Value.Deserialize(IPluginSetting.SerializerOptions) ?? default!; } /// @@ -93,8 +94,8 @@ public class PluginSetting : CorePropertyChanged, IPluginSetting if (!HasChanged) return; - _pluginSettingEntity.Value = CoreJson.Serialize(Value); - _pluginRepository.SaveSetting(_pluginSettingEntity); + _pluginSettingEntity.Value = JsonSerializer.SerializeToNode(Value, IPluginSetting.SerializerOptions) ?? new JsonObject(); + _pluginRepository.SaveChanges(); OnSettingSaved(); } diff --git a/src/Artemis.Core/Services/Input/Events/InputProviderIdentifierEventArgs.cs b/src/Artemis.Core/Services/Input/Events/InputProviderIdentifierEventArgs.cs index cbc41d950..a6660b1a3 100644 --- a/src/Artemis.Core/Services/Input/Events/InputProviderIdentifierEventArgs.cs +++ b/src/Artemis.Core/Services/Input/Events/InputProviderIdentifierEventArgs.cs @@ -12,7 +12,7 @@ public class InputProviderIdentifierEventArgs : EventArgs /// /// A value that can be used to identify this device /// The type of device this identifier belongs to - public InputProviderIdentifierEventArgs(object identifier, InputDeviceType deviceType) + public InputProviderIdentifierEventArgs(string identifier, InputDeviceType deviceType) { Identifier = identifier; DeviceType = deviceType; @@ -21,7 +21,7 @@ public class InputProviderIdentifierEventArgs : EventArgs /// /// Gets a value that can be used to identify this device /// - public object Identifier { get; } + public string Identifier { get; } /// /// Gets the type of device this identifier belongs to diff --git a/src/Artemis.Core/Services/Input/InputProvider.cs b/src/Artemis.Core/Services/Input/InputProvider.cs index 8db4dec76..e5af94e48 100644 --- a/src/Artemis.Core/Services/Input/InputProvider.cs +++ b/src/Artemis.Core/Services/Input/InputProvider.cs @@ -113,7 +113,7 @@ public abstract class InputProvider : IDisposable /// /// A value that can be used to identify this device /// The type of device this identifier belongs to - protected virtual void OnIdentifierReceived(object identifier, InputDeviceType deviceType) + protected virtual void OnIdentifierReceived(string identifier, InputDeviceType deviceType) { IdentifierReceived?.Invoke(this, new InputProviderIdentifierEventArgs(identifier, deviceType)); } diff --git a/src/Artemis.Core/Services/Interfaces/IPluginManagementService.cs b/src/Artemis.Core/Services/Interfaces/IPluginManagementService.cs index bbc4afe7a..932e3f507 100644 --- a/src/Artemis.Core/Services/Interfaces/IPluginManagementService.cs +++ b/src/Artemis.Core/Services/Interfaces/IPluginManagementService.cs @@ -145,19 +145,7 @@ public interface IPluginManagementService : IArtemisService, IDisposable /// /// DeviceProvider GetDeviceProviderByDevice(IRGBDevice device); - - /// - /// Queues the provided plugin to be deleted the next time Artemis starts, before plugins are loaded - /// - /// The plugin to delete - void QueuePluginDeletion(Plugin plugin); - - /// - /// Removes the provided plugin for the deletion queue it was added to via - /// - /// The plugin to dequeue - void DequeuePluginDeletion(Plugin plugin); - + /// /// Occurs when built-in plugins are being loaded /// diff --git a/src/Artemis.Core/Services/PluginManagementService.cs b/src/Artemis.Core/Services/PluginManagementService.cs index 67e3083e4..2f5d69638 100644 --- a/src/Artemis.Core/Services/PluginManagementService.cs +++ b/src/Artemis.Core/Services/PluginManagementService.cs @@ -30,22 +30,18 @@ internal class PluginManagementService : IPluginManagementService private readonly ILogger _logger; private readonly IPluginRepository _pluginRepository; private readonly List _plugins; - private readonly IQueuedActionRepository _queuedActionRepository; private FileSystemWatcher? _hotReloadWatcher; private bool _disposed; private bool _isElevated; - public PluginManagementService(IContainer container, ILogger logger, IPluginRepository pluginRepository, IDeviceRepository deviceRepository, IQueuedActionRepository queuedActionRepository) + public PluginManagementService(IContainer container, ILogger logger, IPluginRepository pluginRepository, IDeviceRepository deviceRepository) { _container = container; _logger = logger; _pluginRepository = pluginRepository; _deviceRepository = deviceRepository; - _queuedActionRepository = queuedActionRepository; _plugins = new List(); - - ProcessPluginDeletionQueue(); - + StartHotReload(); } @@ -800,59 +796,7 @@ internal class PluginManagementService : IPluginManagementService } #endregion - - #region Queued actions - - public void QueuePluginDeletion(Plugin plugin) - { - _queuedActionRepository.Add(new QueuedActionEntity - { - Type = "DeletePlugin", - CreatedAt = DateTimeOffset.Now, - Parameters = new Dictionary - { - {"pluginGuid", plugin.Guid.ToString()}, - {"plugin", plugin.ToString()}, - {"directory", plugin.Directory.FullName} - } - }); - } - - public void DequeuePluginDeletion(Plugin plugin) - { - QueuedActionEntity? queuedActionEntity = _queuedActionRepository.GetByType("DeletePlugin").FirstOrDefault(q => q.Parameters["pluginGuid"].Equals(plugin.Guid.ToString())); - if (queuedActionEntity != null) - _queuedActionRepository.Remove(queuedActionEntity); - } - - private void ProcessPluginDeletionQueue() - { - foreach (QueuedActionEntity queuedActionEntity in _queuedActionRepository.GetByType("DeletePlugin")) - { - string? directory = queuedActionEntity.Parameters["directory"].ToString(); - try - { - if (Directory.Exists(directory)) - { - _logger.Information("Queued plugin deletion - deleting folder - {plugin}", queuedActionEntity.Parameters["plugin"]); - Directory.Delete(directory!, true); - } - else - { - _logger.Information("Queued plugin deletion - folder already deleted - {plugin}", queuedActionEntity.Parameters["plugin"]); - } - - _queuedActionRepository.Remove(queuedActionEntity); - } - catch (Exception e) - { - _logger.Warning(e, "Queued plugin deletion failed - {plugin}", queuedActionEntity.Parameters["plugin"]); - } - } - } - - #endregion - + #region Storage private void SavePlugin(Plugin plugin) diff --git a/src/Artemis.Storage/Artemis.Storage.csproj b/src/Artemis.Storage/Artemis.Storage.csproj index b01c7ef62..83b31c461 100644 --- a/src/Artemis.Storage/Artemis.Storage.csproj +++ b/src/Artemis.Storage/Artemis.Storage.csproj @@ -8,6 +8,7 @@ + diff --git a/src/Artemis.Storage/ArtemisDbContext.cs b/src/Artemis.Storage/ArtemisDbContext.cs new file mode 100644 index 000000000..a49717bd9 --- /dev/null +++ b/src/Artemis.Storage/ArtemisDbContext.cs @@ -0,0 +1,37 @@ +using Artemis.Storage.Entities.General; +using Artemis.Storage.Entities.Plugins; +using Artemis.Storage.Entities.Profile; +using Artemis.Storage.Entities.Surface; +using Artemis.Storage.Entities.Workshop; +using Microsoft.EntityFrameworkCore; + +namespace Artemis.Storage; + +public class ArtemisDbContext : DbContext +{ + public DbSet Devices => Set(); + public DbSet Entries => Set(); + public DbSet Plugins => Set(); + public DbSet PluginSettings => Set(); + public DbSet ProfileCategories => Set(); + public DbSet Profiles => Set(); + public DbSet Releases => Set(); + + /// + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.Entity() + .OwnsOne(d => d.InputIdentifiers, builder => builder.ToJson()) + .OwnsOne(d => d.InputMappings, builder => builder.ToJson()); + + modelBuilder.Entity() + .OwnsOne(e => e.Metadata, builder => builder.ToJson()); + + modelBuilder.Entity() + .OwnsOne(s => s.Value, builder => builder.ToJson()); + + modelBuilder.Entity() + .OwnsOne(c => c.ProfileConfiguration, builder => builder.ToJson()) + .OwnsOne(c => c.Profile, builder => builder.ToJson()); + } +} \ No newline at end of file diff --git a/src/Artemis.Storage/Entities/General/QueuedActionEntity.cs b/src/Artemis.Storage/Entities/General/QueuedActionEntity.cs deleted file mode 100644 index 942a6501d..000000000 --- a/src/Artemis.Storage/Entities/General/QueuedActionEntity.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace Artemis.Storage.Entities.General; - -public class QueuedActionEntity -{ - public QueuedActionEntity() - { - Parameters = new Dictionary(); - } - - public Guid Id { get; set; } - public string Type { get; set; } = string.Empty; - public DateTimeOffset CreatedAt { get; set; } - - public Dictionary Parameters { get; set; } -} \ No newline at end of file diff --git a/src/Artemis.Storage/Entities/Plugins/PluginSettingEntity.cs b/src/Artemis.Storage/Entities/Plugins/PluginSettingEntity.cs index 1d604c28a..8be8cefb5 100644 --- a/src/Artemis.Storage/Entities/Plugins/PluginSettingEntity.cs +++ b/src/Artemis.Storage/Entities/Plugins/PluginSettingEntity.cs @@ -1,4 +1,5 @@ using System; +using System.Text.Json.Nodes; namespace Artemis.Storage.Entities.Plugins; @@ -11,5 +12,5 @@ public class PluginSettingEntity public Guid PluginGuid { get; set; } public string Name { get; set; } = string.Empty; - public string Value { get; set; } = string.Empty; + public JsonNode Value { get; set; } = new JsonObject(); } \ No newline at end of file diff --git a/src/Artemis.Storage/Entities/Profile/ProfileCategoryEntity.cs b/src/Artemis.Storage/Entities/Profile/ProfileCategoryEntity.cs index 126845b38..7bdee9ecf 100644 --- a/src/Artemis.Storage/Entities/Profile/ProfileCategoryEntity.cs +++ b/src/Artemis.Storage/Entities/Profile/ProfileCategoryEntity.cs @@ -12,5 +12,12 @@ public class ProfileCategoryEntity public bool IsSuspended { get; set; } public int Order { get; set; } - public List ProfileConfigurations { get; set; } = new(); + public List ProfileConfigurations { get; set; } = new(); +} + +public class ProfileContainerEntity +{ + public byte[] Icon { get; set; } = Array.Empty(); + public ProfileConfigurationEntity ProfileConfiguration { get; set; } = new(); + public ProfileEntity Profile { get; set; } = new(); } \ No newline at end of file diff --git a/src/Artemis.Storage/Entities/Profile/ProfileConfigurationEntity.cs b/src/Artemis.Storage/Entities/Profile/ProfileConfigurationEntity.cs index aa20adf7f..9157d460c 100644 --- a/src/Artemis.Storage/Entities/Profile/ProfileConfigurationEntity.cs +++ b/src/Artemis.Storage/Entities/Profile/ProfileConfigurationEntity.cs @@ -27,5 +27,5 @@ public class ProfileConfigurationEntity public Guid ProfileId { get; set; } public bool FadeInAndOut { get; set; } - public int Version { get; set; } = StorageMigrationService.PROFILE_VERSION; + public int Version { get; set; } } \ No newline at end of file diff --git a/src/Artemis.Storage/Entities/Surface/DeviceEntity.cs b/src/Artemis.Storage/Entities/Surface/DeviceEntity.cs index 5075131c2..374a20941 100644 --- a/src/Artemis.Storage/Entities/Surface/DeviceEntity.cs +++ b/src/Artemis.Storage/Entities/Surface/DeviceEntity.cs @@ -42,5 +42,5 @@ public class InputMappingEntity public class DeviceInputIdentifierEntity { public string InputProvider { get; set; } = string.Empty; - public object Identifier { get; set; } = string.Empty; + public string Identifier { get; set; } = string.Empty; } \ No newline at end of file diff --git a/src/Artemis.Storage/Entities/Workshop/EntryEntity.cs b/src/Artemis.Storage/Entities/Workshop/EntryEntity.cs index 4be84d9e8..73a063003 100644 --- a/src/Artemis.Storage/Entities/Workshop/EntryEntity.cs +++ b/src/Artemis.Storage/Entities/Workshop/EntryEntity.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Text.Json.Nodes; namespace Artemis.Storage.Entities.Workshop; @@ -17,5 +18,5 @@ public class EntryEntity public string ReleaseVersion { get; set; } = string.Empty; public DateTimeOffset InstalledAt { get; set; } - public Dictionary? Metadata { get; set; } + public Dictionary? Metadata { get; set; } } \ No newline at end of file diff --git a/src/Artemis.Storage/Migrations/IStorageMigration.cs b/src/Artemis.Storage/Migrations/IStorageMigration.cs deleted file mode 100644 index 4382a837d..000000000 --- a/src/Artemis.Storage/Migrations/IStorageMigration.cs +++ /dev/null @@ -1,9 +0,0 @@ -using LiteDB; - -namespace Artemis.Storage.Migrations; - -public interface IStorageMigration -{ - int UserVersion { get; } - void Apply(LiteRepository repository); -} \ No newline at end of file diff --git a/src/Artemis.Storage/Migrations/Storage/M0020AvaloniaReset.cs b/src/Artemis.Storage/Migrations/Storage/M0020AvaloniaReset.cs deleted file mode 100644 index 293fc1ff7..000000000 --- a/src/Artemis.Storage/Migrations/Storage/M0020AvaloniaReset.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using LiteDB; - -namespace Artemis.Storage.Migrations.Storage; - -public class M0020AvaloniaReset : IStorageMigration -{ - public int UserVersion => 20; - - public void Apply(LiteRepository repository) - { - repository.Database.Commit(); - - List collectionNames = repository.Database.GetCollectionNames().ToList(); - foreach (string collectionName in collectionNames) - repository.Database.DropCollection(collectionName); - } -} \ No newline at end of file diff --git a/src/Artemis.Storage/Migrations/Storage/M0021GradientNodes.cs b/src/Artemis.Storage/Migrations/Storage/M0021GradientNodes.cs deleted file mode 100644 index 2bb90a45c..000000000 --- a/src/Artemis.Storage/Migrations/Storage/M0021GradientNodes.cs +++ /dev/null @@ -1,90 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Artemis.Storage.Entities.Profile; -using Artemis.Storage.Entities.Profile.Nodes; -using LiteDB; - -namespace Artemis.Storage.Migrations.Storage; - -public class M0021GradientNodes : IStorageMigration -{ - private void MigrateDataBinding(PropertyEntity property) - { - NodeScriptEntity? script = property.DataBinding?.NodeScript; - NodeEntity? exitNode = script?.Nodes.FirstOrDefault(s => s.IsExitNode); - if (script == null || exitNode == null) - return; - - // Create a new node at the same position of the exit node - NodeEntity gradientNode = new() - { - Id = Guid.NewGuid(), - Type = "ColorGradientNode", - ProviderId = "Artemis.Plugins.Nodes.General.GeneralNodesProvider-d9e1ee78", - Name = "Color Gradient", - Description = "Outputs a color gradient with the given colors", - X = exitNode.X, - Y = exitNode.Y, - Storage = property.Value // Copy the value of the property into the node storage - }; - script.Nodes.Add(gradientNode); - - // Move all connections of the exit node to the new node - foreach (NodeConnectionEntity connection in script.Connections) - { - if (connection.SourceNode == exitNode.Id) - { - connection.SourceNode = gradientNode.Id; - connection.SourcePinId++; - } - } - - // Connect the data binding node to the source node - script.Connections.Add(new NodeConnectionEntity - { - SourceType = "ColorGradient", - SourceNode = exitNode.Id, - SourcePinCollectionId = -1, - SourcePinId = 0, - TargetType = "ColorGradient", - TargetNode = gradientNode.Id, - TargetPinCollectionId = -1, - TargetPinId = 0 - }); - - // Move the exit node to the right - exitNode.X += 300; - exitNode.Y += 30; - } - - private void MigrateDataBinding(PropertyGroupEntity? propertyGroup) - { - if (propertyGroup == null) - return; - - foreach (PropertyGroupEntity propertyGroupPropertyGroup in propertyGroup.PropertyGroups) - MigrateDataBinding(propertyGroupPropertyGroup); - - foreach (PropertyEntity property in propertyGroup.Properties) - { - if (property.Value.StartsWith("[{\"Color\":\"") && property.DataBinding?.NodeScript != null && property.DataBinding.IsEnabled) - MigrateDataBinding(property); - } - } - - public int UserVersion => 21; - - public void Apply(LiteRepository repository) - { - // Find all color gradient data bindings, there's no really good way to do this so infer it from the value - List profiles = repository.Query().ToList(); - foreach (ProfileEntity profileEntity in profiles) - { - foreach (LayerEntity layer in profileEntity.Layers.Where(le => le.LayerBrush != null)) - MigrateDataBinding(layer.LayerBrush?.PropertyGroup); - - repository.Update(profileEntity); - } - } -} \ No newline at end of file diff --git a/src/Artemis.Storage/Migrations/Storage/M0022TransitionNodes.cs b/src/Artemis.Storage/Migrations/Storage/M0022TransitionNodes.cs deleted file mode 100644 index 791b95ea9..000000000 --- a/src/Artemis.Storage/Migrations/Storage/M0022TransitionNodes.cs +++ /dev/null @@ -1,86 +0,0 @@ -using System.Collections.Generic; -using Artemis.Storage.Entities.Profile; -using Artemis.Storage.Entities.Profile.Abstract; -using Artemis.Storage.Entities.Profile.Conditions; -using Artemis.Storage.Entities.Profile.Nodes; -using LiteDB; - -namespace Artemis.Storage.Migrations.Storage; - -public class M0022TransitionNodes : IStorageMigration -{ - private void MigrateNodeScript(NodeScriptEntity? nodeScript) - { - if (nodeScript == null) - return; - - foreach (NodeEntity node in nodeScript.Nodes) - { - if (node.Type == "NumericEasingNode") - node.Type = "NumericTransitionNode"; - else if (node.Type == "ColorGradientEasingNode") - node.Type = "ColorGradientTransitionNode"; - else if (node.Type == "SKColorEasingNode") - node.Type = "SKColorTransitionNode"; - else if (node.Type == "EasingTypeNode") - node.Type = "EasingFunctionNode"; - } - } - - private void MigratePropertyGroup(PropertyGroupEntity? propertyGroup) - { - if (propertyGroup == null) - return; - - foreach (PropertyGroupEntity childPropertyGroup in propertyGroup.PropertyGroups) - MigratePropertyGroup(childPropertyGroup); - foreach (PropertyEntity property in propertyGroup.Properties) - MigrateNodeScript(property.DataBinding?.NodeScript); - } - - private void MigrateDisplayCondition(IConditionEntity? conditionEntity) - { - if (conditionEntity is EventConditionEntity eventConditionEntity) - MigrateNodeScript(eventConditionEntity.Script); - else if (conditionEntity is StaticConditionEntity staticConditionEntity) - MigrateNodeScript(staticConditionEntity.Script); - } - - public int UserVersion => 22; - - public void Apply(LiteRepository repository) - { - // Migrate profile configuration display conditions - List categories = repository.Query().ToList(); - foreach (ProfileCategoryEntity profileCategoryEntity in categories) - { - foreach (ProfileConfigurationEntity profileConfigurationEntity in profileCategoryEntity.ProfileConfigurations) - MigrateNodeScript(profileConfigurationEntity.ActivationCondition); - repository.Update(profileCategoryEntity); - } - - // Migrate profile display conditions and data bindings - List profiles = repository.Query().ToList(); - foreach (ProfileEntity profileEntity in profiles) - { - foreach (LayerEntity layer in profileEntity.Layers) - { - MigratePropertyGroup(layer.LayerBrush?.PropertyGroup); - MigratePropertyGroup(layer.GeneralPropertyGroup); - MigratePropertyGroup(layer.TransformPropertyGroup); - foreach (LayerEffectEntity layerEffectEntity in layer.LayerEffects) - MigratePropertyGroup(layerEffectEntity.PropertyGroup); - MigrateDisplayCondition(layer.DisplayCondition); - } - - foreach (FolderEntity folder in profileEntity.Folders) - { - foreach (LayerEffectEntity folderLayerEffect in folder.LayerEffects) - MigratePropertyGroup(folderLayerEffect.PropertyGroup); - MigrateDisplayCondition(folder.DisplayCondition); - } - - repository.Update(profileEntity); - } - } -} \ No newline at end of file diff --git a/src/Artemis.Storage/Migrations/Storage/M0023LayoutProviders.cs b/src/Artemis.Storage/Migrations/Storage/M0023LayoutProviders.cs deleted file mode 100644 index 5296d5842..000000000 --- a/src/Artemis.Storage/Migrations/Storage/M0023LayoutProviders.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System.Collections.Generic; -using LiteDB; - -namespace Artemis.Storage.Migrations.Storage; - -public class M0023LayoutProviders : IStorageMigration -{ - public int UserVersion => 23; - - public void Apply(LiteRepository repository) - { - ILiteCollection deviceEntities = repository.Database.GetCollection("DeviceEntity"); - List toUpdate = new(); - - foreach (BsonDocument bsonDocument in deviceEntities.FindAll()) - { - if (bsonDocument.TryGetValue("CustomLayoutPath", out BsonValue customLayoutPath) && customLayoutPath.IsString && !string.IsNullOrEmpty(customLayoutPath.AsString)) - { - bsonDocument.Add("LayoutType", new BsonValue("CustomPath")); - bsonDocument.Add("LayoutParameter", new BsonValue(customLayoutPath.AsString)); - } - else if (bsonDocument.TryGetValue("DisableDefaultLayout", out BsonValue disableDefaultLayout) && disableDefaultLayout.AsBoolean) - bsonDocument.Add("LayoutType", new BsonValue("None")); - else - bsonDocument.Add("LayoutType", new BsonValue("Default")); - - bsonDocument.Remove("CustomLayoutPath"); - bsonDocument.Remove("DisableDefaultLayout"); - toUpdate.Add(bsonDocument); - } - - deviceEntities.Update(toUpdate); - } -} \ No newline at end of file diff --git a/src/Artemis.Storage/Migrations/Storage/M0024NodeProviders.cs b/src/Artemis.Storage/Migrations/Storage/M0024NodeProviders.cs deleted file mode 100644 index c09c0f1fc..000000000 --- a/src/Artemis.Storage/Migrations/Storage/M0024NodeProviders.cs +++ /dev/null @@ -1,107 +0,0 @@ -using System.Collections.Generic; -using Artemis.Storage.Entities.Profile; -using LiteDB; - -namespace Artemis.Storage.Migrations.Storage; - -public class M0024NodeProviders : IStorageMigration -{ - public int UserVersion => 24; - - public void Apply(LiteRepository repository) - { - ILiteCollection categoryCollection = repository.Database.GetCollection("ProfileCategoryEntity"); - List categoriesToUpdate = new(); - foreach (BsonDocument profileCategoryBson in categoryCollection.FindAll()) - { - BsonArray? profiles = profileCategoryBson["ProfileConfigurations"]?.AsArray; - if (profiles != null) - { - foreach (BsonValue profile in profiles) - profile["Version"] = 1; - categoriesToUpdate.Add(profileCategoryBson); - } - } - categoryCollection.Update(categoriesToUpdate); - - ILiteCollection collection = repository.Database.GetCollection("ProfileEntity"); - List profilesToUpdate = new(); - foreach (BsonDocument profileBson in collection.FindAll()) - { - BsonArray? folders = profileBson["Folders"]?.AsArray; - BsonArray? layers = profileBson["Layers"]?.AsArray; - - if (folders != null) - { - foreach (BsonValue folder in folders) - MigrateProfileElement(folder.AsDocument); - } - - if (layers != null) - { - foreach (BsonValue layer in layers) - { - MigrateProfileElement(layer.AsDocument); - MigratePropertyGroup(layer.AsDocument["GeneralPropertyGroup"].AsDocument); - MigratePropertyGroup(layer.AsDocument["TransformPropertyGroup"].AsDocument); - MigratePropertyGroup(layer.AsDocument["LayerBrush"]?["PropertyGroup"].AsDocument); - } - } - - profilesToUpdate.Add(profileBson); - } - - collection.Update(profilesToUpdate); - } - - private void MigrateProfileElement(BsonDocument profileElement) - { - BsonArray? layerEffects = profileElement["LayerEffects"]?.AsArray; - if (layerEffects != null) - { - foreach (BsonValue layerEffect in layerEffects) - MigratePropertyGroup(layerEffect.AsDocument["PropertyGroup"].AsDocument); - } - - BsonValue? displayCondition = profileElement["DisplayCondition"]; - if (displayCondition != null) - MigrateNodeScript(displayCondition.AsDocument["Script"].AsDocument); - } - - private void MigratePropertyGroup(BsonDocument? propertyGroup) - { - if (propertyGroup == null || propertyGroup.Keys.Count == 0) - return; - - BsonArray? properties = propertyGroup["Properties"]?.AsArray; - BsonArray? propertyGroups = propertyGroup["PropertyGroups"]?.AsArray; - - if (properties != null) - { - foreach (BsonValue property in properties) - MigrateNodeScript(property.AsDocument["DataBinding"]?["NodeScript"]?.AsDocument); - } - - if (propertyGroups != null) - { - foreach (BsonValue childPropertyGroup in propertyGroups) - MigratePropertyGroup(childPropertyGroup.AsDocument); - } - } - - private void MigrateNodeScript(BsonDocument? nodeScript) - { - if (nodeScript == null || nodeScript.Keys.Count == 0) - return; - - BsonArray? nodes = nodeScript["Nodes"]?.AsArray; - if (nodes == null) - return; - - foreach (BsonValue node in nodes) - { - node.AsDocument["Type"] = node.AsDocument["Type"]?.AsString?.Replace("Artemis.VisualScripting.Nodes", "Artemis.Plugins.Nodes.General.Nodes"); - node.AsDocument["ProviderId"] = "Artemis.Plugins.Nodes.General.GeneralNodesProvider-d9e1ee78"; - } - } -} \ No newline at end of file diff --git a/src/Artemis.Storage/Migrations/Storage/M0025NodeProvidersProfileConfig.cs b/src/Artemis.Storage/Migrations/Storage/M0025NodeProvidersProfileConfig.cs deleted file mode 100644 index 46d8c3fe7..000000000 --- a/src/Artemis.Storage/Migrations/Storage/M0025NodeProvidersProfileConfig.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System.Collections.Generic; -using LiteDB; - -namespace Artemis.Storage.Migrations.Storage; - -public class M0025NodeProvidersProfileConfig : IStorageMigration -{ - public int UserVersion => 25; - - public void Apply(LiteRepository repository) - { - ILiteCollection categoryCollection = repository.Database.GetCollection("ProfileCategoryEntity"); - List toUpdate = new(); - foreach (BsonDocument profileCategoryBson in categoryCollection.FindAll()) - { - BsonArray? profiles = profileCategoryBson["ProfileConfigurations"]?.AsArray; - if (profiles != null) - { - foreach (BsonValue profile in profiles) - { - profile["Version"] = 2; - MigrateNodeScript(profile["ActivationCondition"]?.AsDocument); - } - toUpdate.Add(profileCategoryBson); - } - } - - categoryCollection.Update(toUpdate); - } - - private void MigrateNodeScript(BsonDocument? nodeScript) - { - if (nodeScript == null || nodeScript.Keys.Count == 0) - return; - - BsonArray? nodes = nodeScript["Nodes"]?.AsArray; - if (nodes == null) - return; - - foreach (BsonValue node in nodes) - { - node.AsDocument["Type"] = node.AsDocument["Type"]?.AsString?.Replace("Artemis.VisualScripting.Nodes", "Artemis.Plugins.Nodes.General.Nodes"); - node.AsDocument["ProviderId"] = "Artemis.Plugins.Nodes.General.GeneralNodesProvider-d9e1ee78"; - } - } -} \ No newline at end of file diff --git a/src/Artemis.Storage/Migrations/Storage/M0026NodeStorage.cs b/src/Artemis.Storage/Migrations/Storage/M0026NodeStorage.cs deleted file mode 100644 index f181f9698..000000000 --- a/src/Artemis.Storage/Migrations/Storage/M0026NodeStorage.cs +++ /dev/null @@ -1,119 +0,0 @@ -using System.Collections.Generic; -using Artemis.Storage.Migrations.Profile; -using LiteDB; -using Serilog; - -namespace Artemis.Storage.Migrations.Storage; - -public class M0026NodeStorage : IStorageMigration -{ - private readonly ILogger _logger; - - public M0026NodeStorage(ILogger logger) - { - _logger = logger; - } - public int UserVersion => 26; - - public void Apply(LiteRepository repository) - { - ILiteCollection categoryCollection = repository.Database.GetCollection("ProfileCategoryEntity"); - List toUpdate = new(); - foreach (BsonDocument profileCategoryBson in categoryCollection.FindAll()) - { - BsonArray? profiles = profileCategoryBson["ProfileConfigurations"]?.AsArray; - if (profiles != null) - { - foreach (BsonValue profile in profiles) - { - profile["Version"] = 4; - MigrateNodeScript(profile["ActivationCondition"]?.AsDocument); - } - - toUpdate.Add(profileCategoryBson); - } - } - - categoryCollection.Update(toUpdate); - - ILiteCollection collection = repository.Database.GetCollection("ProfileEntity"); - List profilesToUpdate = new(); - foreach (BsonDocument profileBson in collection.FindAll()) - { - BsonArray? folders = profileBson["Folders"]?.AsArray; - BsonArray? layers = profileBson["Layers"]?.AsArray; - - if (folders != null) - { - foreach (BsonValue folder in folders) - MigrateProfileElement(folder.AsDocument); - } - - if (layers != null) - { - foreach (BsonValue layer in layers) - { - MigrateProfileElement(layer.AsDocument); - MigratePropertyGroup(layer.AsDocument["GeneralPropertyGroup"].AsDocument); - MigratePropertyGroup(layer.AsDocument["TransformPropertyGroup"].AsDocument); - MigratePropertyGroup(layer.AsDocument["LayerBrush"]?["PropertyGroup"].AsDocument); - } - } - - profilesToUpdate.Add(profileBson); - } - - collection.Update(profilesToUpdate); - } - - private void MigrateProfileElement(BsonDocument profileElement) - { - BsonArray? layerEffects = profileElement["LayerEffects"]?.AsArray; - if (layerEffects != null) - { - foreach (BsonValue layerEffect in layerEffects) - MigratePropertyGroup(layerEffect.AsDocument["PropertyGroup"].AsDocument); - } - - BsonValue? displayCondition = profileElement["DisplayCondition"]; - if (displayCondition != null) - MigrateNodeScript(displayCondition.AsDocument["Script"].AsDocument); - } - - private void MigratePropertyGroup(BsonDocument? propertyGroup) - { - if (propertyGroup == null || propertyGroup.Keys.Count == 0) - return; - - BsonArray? properties = propertyGroup["Properties"]?.AsArray; - BsonArray? propertyGroups = propertyGroup["PropertyGroups"]?.AsArray; - - if (properties != null) - { - foreach (BsonValue property in properties) - MigrateNodeScript(property.AsDocument["DataBinding"]?["NodeScript"]?.AsDocument); - } - - if (propertyGroups != null) - { - foreach (BsonValue childPropertyGroup in propertyGroups) - MigratePropertyGroup(childPropertyGroup.AsDocument); - } - } - - private void MigrateNodeScript(BsonDocument? nodeScript) - { - if (nodeScript == null || nodeScript.Keys.Count == 0) - return; - - BsonArray? nodes = nodeScript["Nodes"]?.AsArray; - if (nodes == null) - return; - - foreach (BsonValue node in nodes) - { - // Migrate the storage of the node - node["Storage"] = M0004NodeStorage.MigrateNodeStorageJson(node.AsDocument["Storage"]?.AsString, _logger); - } - } -} \ No newline at end of file diff --git a/src/Artemis.Storage/Repositories/DeviceRepository.cs b/src/Artemis.Storage/Repositories/DeviceRepository.cs index 47a947333..d438da17a 100644 --- a/src/Artemis.Storage/Repositories/DeviceRepository.cs +++ b/src/Artemis.Storage/Repositories/DeviceRepository.cs @@ -1,47 +1,43 @@ using System.Collections.Generic; +using System.Linq; using Artemis.Storage.Entities.Surface; using Artemis.Storage.Repositories.Interfaces; -using LiteDB; namespace Artemis.Storage.Repositories; internal class DeviceRepository : IDeviceRepository { - private readonly LiteRepository _repository; + private readonly ArtemisDbContext _dbContext; - public DeviceRepository(LiteRepository repository) + public DeviceRepository(ArtemisDbContext dbContext) { - _repository = repository; - _repository.Database.GetCollection().EnsureIndex(s => s.Id); + _dbContext = dbContext; } public void Add(DeviceEntity deviceEntity) { - _repository.Insert(deviceEntity); + _dbContext.Devices.Add(deviceEntity); + SaveChanges(); } public void Remove(DeviceEntity deviceEntity) { - _repository.Delete(deviceEntity.Id); + _dbContext.Devices.Remove(deviceEntity); + SaveChanges(); } public DeviceEntity? Get(string id) { - return _repository.FirstOrDefault(s => s.Id == id); + return _dbContext.Devices.FirstOrDefault(d => d.Id == id); } public List GetAll() { - return _repository.Query().Include(s => s.InputIdentifiers).ToList(); + return _dbContext.Devices.ToList(); } - public void Save(DeviceEntity deviceEntity) + public void SaveChanges() { - _repository.Upsert(deviceEntity); - } - - public void Save(IEnumerable deviceEntities) - { - _repository.Upsert(deviceEntities); + _dbContext.SaveChanges(); } } \ No newline at end of file diff --git a/src/Artemis.Storage/Repositories/EntryRepository.cs b/src/Artemis.Storage/Repositories/EntryRepository.cs index 81775f967..8f719eb52 100644 --- a/src/Artemis.Storage/Repositories/EntryRepository.cs +++ b/src/Artemis.Storage/Repositories/EntryRepository.cs @@ -1,54 +1,49 @@ using System; using System.Collections.Generic; +using System.Linq; using Artemis.Storage.Entities.Workshop; using Artemis.Storage.Repositories.Interfaces; -using LiteDB; namespace Artemis.Storage.Repositories; internal class EntryRepository : IEntryRepository { - private readonly LiteRepository _repository; + private readonly ArtemisDbContext _dbContext; - public EntryRepository(LiteRepository repository) + public EntryRepository(ArtemisDbContext dbContext) { - _repository = repository; - _repository.Database.GetCollection().EnsureIndex(s => s.Id); - _repository.Database.GetCollection().EnsureIndex(s => s.EntryId); + _dbContext = dbContext; } public void Add(EntryEntity entryEntity) { - _repository.Insert(entryEntity); + _dbContext.Entries.Add(entryEntity); + SaveChanges(); } public void Remove(EntryEntity entryEntity) { - _repository.Delete(entryEntity.Id); + _dbContext.Entries.Remove(entryEntity); + SaveChanges(); } public EntryEntity? Get(Guid id) { - return _repository.FirstOrDefault(s => s.Id == id); + return _dbContext.Entries.FirstOrDefault(s => s.Id == id); } public EntryEntity? GetByEntryId(long entryId) { - return _repository.FirstOrDefault(s => s.EntryId == entryId); + return _dbContext.Entries.FirstOrDefault(s => s.EntryId == entryId); } public List GetAll() { - return _repository.Query().ToList(); + return _dbContext.Entries.ToList(); } - public void Save(EntryEntity entryEntity) + public void SaveChanges() { - _repository.Upsert(entryEntity); - } - - public void Save(IEnumerable entryEntities) - { - _repository.Upsert(entryEntities); + _dbContext.SaveChanges(); } } \ No newline at end of file diff --git a/src/Artemis.Storage/Repositories/Interfaces/IDeviceRepository.cs b/src/Artemis.Storage/Repositories/Interfaces/IDeviceRepository.cs index 50fd1df86..172f23e61 100644 --- a/src/Artemis.Storage/Repositories/Interfaces/IDeviceRepository.cs +++ b/src/Artemis.Storage/Repositories/Interfaces/IDeviceRepository.cs @@ -9,6 +9,5 @@ public interface IDeviceRepository : IRepository void Remove(DeviceEntity deviceEntity); DeviceEntity? Get(string id); List GetAll(); - void Save(DeviceEntity deviceEntity); - void Save(IEnumerable deviceEntities); + void SaveChanges(); } \ No newline at end of file diff --git a/src/Artemis.Storage/Repositories/Interfaces/IEntryRepository.cs b/src/Artemis.Storage/Repositories/Interfaces/IEntryRepository.cs index 59d610f95..0e16c6dde 100644 --- a/src/Artemis.Storage/Repositories/Interfaces/IEntryRepository.cs +++ b/src/Artemis.Storage/Repositories/Interfaces/IEntryRepository.cs @@ -11,6 +11,5 @@ public interface IEntryRepository : IRepository EntryEntity? Get(Guid id); EntryEntity? GetByEntryId(long entryId); List GetAll(); - void Save(EntryEntity entryEntity); - void Save(IEnumerable entryEntities); + void SaveChanges(); } \ No newline at end of file diff --git a/src/Artemis.Storage/Repositories/Interfaces/IPluginRepository.cs b/src/Artemis.Storage/Repositories/Interfaces/IPluginRepository.cs index c180ee33f..d6d766344 100644 --- a/src/Artemis.Storage/Repositories/Interfaces/IPluginRepository.cs +++ b/src/Artemis.Storage/Repositories/Interfaces/IPluginRepository.cs @@ -7,11 +7,9 @@ public interface IPluginRepository : IRepository { void AddPlugin(PluginEntity pluginEntity); PluginEntity? GetPluginByGuid(Guid pluginGuid); - void SavePlugin(PluginEntity pluginEntity); - void AddSetting(PluginSettingEntity pluginSettingEntity); PluginSettingEntity? GetSettingByGuid(Guid pluginGuid); PluginSettingEntity? GetSettingByNameAndGuid(string name, Guid pluginGuid); - void SaveSetting(PluginSettingEntity pluginSettingEntity); void RemoveSettings(Guid pluginGuid); + void SaveChanges(); } \ No newline at end of file diff --git a/src/Artemis.Storage/Repositories/Interfaces/IProfileCategoryRepository.cs b/src/Artemis.Storage/Repositories/Interfaces/IProfileCategoryRepository.cs index 878040e2c..cf3dccee6 100644 --- a/src/Artemis.Storage/Repositories/Interfaces/IProfileCategoryRepository.cs +++ b/src/Artemis.Storage/Repositories/Interfaces/IProfileCategoryRepository.cs @@ -11,8 +11,6 @@ public interface IProfileCategoryRepository : IRepository void Remove(ProfileCategoryEntity profileCategoryEntity); List GetAll(); ProfileCategoryEntity? Get(Guid id); - Stream? GetProfileIconStream(Guid id); - void SaveProfileIconStream(ProfileConfigurationEntity profileConfigurationEntity, Stream stream); - ProfileCategoryEntity IsUnique(string name, Guid? id); - void Save(ProfileCategoryEntity profileCategoryEntity); + bool IsUnique(string name, Guid? id); + void SaveChanges(); } \ No newline at end of file diff --git a/src/Artemis.Storage/Repositories/Interfaces/IProfileRepository.cs b/src/Artemis.Storage/Repositories/Interfaces/IProfileRepository.cs index 8430b82c4..5133c0328 100644 --- a/src/Artemis.Storage/Repositories/Interfaces/IProfileRepository.cs +++ b/src/Artemis.Storage/Repositories/Interfaces/IProfileRepository.cs @@ -6,9 +6,9 @@ namespace Artemis.Storage.Repositories.Interfaces; public interface IProfileRepository : IRepository { - void Add(ProfileEntity profileEntity); - void Remove(ProfileEntity profileEntity); - List GetAll(); - ProfileEntity? Get(Guid id); - void Save(ProfileEntity profileEntity); + void Add(ProfileContainerEntity profileContainerEntity); + void Remove(ProfileContainerEntity profileContainerEntity); + List GetAll(); + ProfileContainerEntity? Get(Guid id); + void SaveChanges(); } \ No newline at end of file diff --git a/src/Artemis.Storage/Repositories/Interfaces/IQueuedActionRepository.cs b/src/Artemis.Storage/Repositories/Interfaces/IQueuedActionRepository.cs deleted file mode 100644 index cb5852eaa..000000000 --- a/src/Artemis.Storage/Repositories/Interfaces/IQueuedActionRepository.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Collections.Generic; -using Artemis.Storage.Entities.General; - -namespace Artemis.Storage.Repositories.Interfaces; - -public interface IQueuedActionRepository : IRepository -{ - void Add(QueuedActionEntity queuedActionEntity); - void Remove(QueuedActionEntity queuedActionEntity); - List GetAll(); - List GetByType(string type); - bool IsTypeQueued(string type); - void ClearByType(string type); -} \ No newline at end of file diff --git a/src/Artemis.Storage/Repositories/PluginRepository.cs b/src/Artemis.Storage/Repositories/PluginRepository.cs index 02a8985c0..190530bbc 100644 --- a/src/Artemis.Storage/Repositories/PluginRepository.cs +++ b/src/Artemis.Storage/Repositories/PluginRepository.cs @@ -1,59 +1,53 @@ using System; +using System.Linq; using Artemis.Storage.Entities.Plugins; using Artemis.Storage.Repositories.Interfaces; -using LiteDB; namespace Artemis.Storage.Repositories; internal class PluginRepository : IPluginRepository { - private readonly LiteRepository _repository; + private readonly ArtemisDbContext _dbContext; - public PluginRepository(LiteRepository repository) + public PluginRepository(ArtemisDbContext dbContext) { - _repository = repository; - - _repository.Database.GetCollection().EnsureIndex(s => new {s.Name, s.PluginGuid}, true); + _dbContext = dbContext; } public void AddPlugin(PluginEntity pluginEntity) { - _repository.Insert(pluginEntity); + _dbContext.Plugins.Add(pluginEntity); + SaveChanges(); } public PluginEntity? GetPluginByGuid(Guid pluginGuid) { - return _repository.FirstOrDefault(p => p.Id == pluginGuid); + return _dbContext.Plugins.FirstOrDefault(p => p.Id == pluginGuid); } - - public void SavePlugin(PluginEntity pluginEntity) - { - _repository.Upsert(pluginEntity); - } - + public void AddSetting(PluginSettingEntity pluginSettingEntity) { - _repository.Insert(pluginSettingEntity); + _dbContext.PluginSettings.Add(pluginSettingEntity); + SaveChanges(); } public PluginSettingEntity? GetSettingByGuid(Guid pluginGuid) { - return _repository.FirstOrDefault(p => p.PluginGuid == pluginGuid); + return _dbContext.PluginSettings.FirstOrDefault(p => p.PluginGuid == pluginGuid); } public PluginSettingEntity? GetSettingByNameAndGuid(string name, Guid pluginGuid) { - return _repository.FirstOrDefault(p => p.Name == name && p.PluginGuid == pluginGuid); + return _dbContext.PluginSettings.FirstOrDefault(p => p.Name == name && p.PluginGuid == pluginGuid); } - - public void SaveSetting(PluginSettingEntity pluginSettingEntity) - { - _repository.Upsert(pluginSettingEntity); - } - - /// + public void RemoveSettings(Guid pluginGuid) { - _repository.DeleteMany(s => s.PluginGuid == pluginGuid); + _dbContext.PluginSettings.RemoveRange(_dbContext.PluginSettings.Where(s => s.PluginGuid == pluginGuid)); + } + + public void SaveChanges() + { + _dbContext.SaveChanges(); } } \ No newline at end of file diff --git a/src/Artemis.Storage/Repositories/ProfileCategoryRepository.cs b/src/Artemis.Storage/Repositories/ProfileCategoryRepository.cs index 8036b9d7a..7d0ef11bc 100644 --- a/src/Artemis.Storage/Repositories/ProfileCategoryRepository.cs +++ b/src/Artemis.Storage/Repositories/ProfileCategoryRepository.cs @@ -1,93 +1,53 @@ using System; using System.Collections.Generic; -using System.IO; +using System.Linq; using Artemis.Storage.Entities.Profile; using Artemis.Storage.Repositories.Interfaces; -using LiteDB; +using Microsoft.EntityFrameworkCore; namespace Artemis.Storage.Repositories; internal class ProfileCategoryRepository : IProfileCategoryRepository { - private readonly ILiteStorage _profileIcons; - private readonly LiteRepository _repository; + private readonly ArtemisDbContext _dbContext; - public ProfileCategoryRepository(LiteRepository repository) + public ProfileCategoryRepository(ArtemisDbContext dbContext) { - _repository = repository; - _repository.Database.GetCollection().EnsureIndex(s => s.Name, true); - _profileIcons = _repository.Database.GetStorage("profileIcons"); + _dbContext = dbContext; } public void Add(ProfileCategoryEntity profileCategoryEntity) { - _repository.Insert(profileCategoryEntity); + _dbContext.ProfileCategories.Add(profileCategoryEntity); + SaveChanges(); } public void Remove(ProfileCategoryEntity profileCategoryEntity) { - _repository.Delete(profileCategoryEntity.Id); + _dbContext.ProfileCategories.Remove(profileCategoryEntity); + SaveChanges(); } public List GetAll() { - List categories = _repository.Query().ToList(); - - // Update all profile versions to the current version, profile migrations don't apply to LiteDB so anything loadable is assumed to be up to date - foreach (ProfileCategoryEntity profileCategoryEntity in categories) - UpdateProfileVersions(profileCategoryEntity); - - return categories; + return _dbContext.ProfileCategories.Include(c => c.ProfileConfigurations).ToList(); } public ProfileCategoryEntity? Get(Guid id) { - ProfileCategoryEntity? result = _repository.FirstOrDefault(p => p.Id == id); - if (result == null) - return null; - - // Update all profile versions to the current version, profile migrations don't apply to LiteDB so anything loadable is assumed to be up to date - UpdateProfileVersions(result); - return result; + return _dbContext.ProfileCategories.Include(c => c.ProfileConfigurations).FirstOrDefault(c => c.Id == id); } - public ProfileCategoryEntity IsUnique(string name, Guid? id) + public bool IsUnique(string name, Guid? id) { name = name.Trim(); if (id == null) - return _repository.FirstOrDefault(p => p.Name == name); - return _repository.FirstOrDefault(p => p.Name == name && p.Id != id.Value); - } - - public void Save(ProfileCategoryEntity profileCategoryEntity) - { - _repository.Upsert(profileCategoryEntity); - } - - public Stream? GetProfileIconStream(Guid id) - { - if (!_profileIcons.Exists(id)) - return null; - - MemoryStream stream = new(); - _profileIcons.Download(id, stream); - return stream; - } - - public void SaveProfileIconStream(ProfileConfigurationEntity profileConfigurationEntity, Stream stream) - { - if (profileConfigurationEntity.FileIconId == Guid.Empty) - profileConfigurationEntity.FileIconId = Guid.NewGuid(); - - if (stream == null && _profileIcons.Exists(profileConfigurationEntity.FileIconId)) - _profileIcons.Delete(profileConfigurationEntity.FileIconId); - - _profileIcons.Upload(profileConfigurationEntity.FileIconId, profileConfigurationEntity.FileIconId + ".png", stream); + return _dbContext.ProfileCategories.Any(p => p.Name == name); + return _dbContext.ProfileCategories.Any(p => p.Name == name && p.Id != id.Value); } - private static void UpdateProfileVersions(ProfileCategoryEntity profileCategoryEntity) + public void SaveChanges() { - foreach (ProfileConfigurationEntity profileConfigurationEntity in profileCategoryEntity.ProfileConfigurations) - profileConfigurationEntity.Version = StorageMigrationService.PROFILE_VERSION; + _dbContext.SaveChanges(); } } \ No newline at end of file diff --git a/src/Artemis.Storage/Repositories/ProfileRepository.cs b/src/Artemis.Storage/Repositories/ProfileRepository.cs index 738099a32..0a2c1b88b 100644 --- a/src/Artemis.Storage/Repositories/ProfileRepository.cs +++ b/src/Artemis.Storage/Repositories/ProfileRepository.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using Artemis.Storage.Entities.Profile; using Artemis.Storage.Repositories.Interfaces; using LiteDB; @@ -8,36 +9,37 @@ namespace Artemis.Storage.Repositories; internal class ProfileRepository : IProfileRepository { - private readonly LiteRepository _repository; + private readonly ArtemisDbContext _dbContext; - public ProfileRepository(LiteRepository repository) + public ProfileRepository(ArtemisDbContext dbContext) { - _repository = repository; - _repository.Database.GetCollection().EnsureIndex(s => s.Name); + _dbContext = dbContext; } - public void Add(ProfileEntity profileEntity) + public void Add(ProfileContainerEntity profileContainerEntity) { - _repository.Insert(profileEntity); + _dbContext.Profiles.Add(profileContainerEntity); + SaveChanges(); } - public void Remove(ProfileEntity profileEntity) + public void Remove(ProfileContainerEntity profileContainerEntity) { - _repository.Delete(profileEntity.Id); + _dbContext.Profiles.Remove(profileContainerEntity); + SaveChanges(); } - public List GetAll() + public List GetAll() { - return _repository.Query().ToList(); + return _dbContext.Profiles.ToList(); } - public ProfileEntity? Get(Guid id) + public ProfileContainerEntity? Get(Guid id) { - return _repository.FirstOrDefault(p => p.Id == id); + return _dbContext.Profiles.FirstOrDefault(c => c.Profile.Id == id); } - public void Save(ProfileEntity profileEntity) + public void SaveChanges() { - _repository.Upsert(profileEntity); + _dbContext.SaveChanges(); } } \ No newline at end of file diff --git a/src/Artemis.Storage/Repositories/QueuedActionRepository.cs b/src/Artemis.Storage/Repositories/QueuedActionRepository.cs deleted file mode 100644 index cf2bc862d..000000000 --- a/src/Artemis.Storage/Repositories/QueuedActionRepository.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System.Collections.Generic; -using Artemis.Storage.Entities.General; -using Artemis.Storage.Repositories.Interfaces; -using LiteDB; - -namespace Artemis.Storage.Repositories; - -public class QueuedActionRepository : IQueuedActionRepository -{ - private readonly LiteRepository _repository; - - public QueuedActionRepository(LiteRepository repository) - { - _repository = repository; - _repository.Database.GetCollection().EnsureIndex(s => s.Type); - } - - #region Implementation of IQueuedActionRepository - - /// - public void Add(QueuedActionEntity queuedActionEntity) - { - _repository.Insert(queuedActionEntity); - } - - /// - public void Remove(QueuedActionEntity queuedActionEntity) - { - _repository.Delete(queuedActionEntity.Id); - } - - /// - public List GetAll() - { - return _repository.Query().ToList(); - } - - /// - public List GetByType(string type) - { - return _repository.Query().Where(q => q.Type == type).ToList(); - } - - /// - public bool IsTypeQueued(string type) - { - return _repository.Query().Where(q => q.Type == type).Count() > 0; - } - - /// - public void ClearByType(string type) - { - _repository.DeleteMany(q => q.Type == type); - } - - #endregion -} \ No newline at end of file diff --git a/src/Artemis.Storage/Repositories/ReleaseRepository.cs b/src/Artemis.Storage/Repositories/ReleaseRepository.cs index c5c18ae27..d7e320919 100644 --- a/src/Artemis.Storage/Repositories/ReleaseRepository.cs +++ b/src/Artemis.Storage/Repositories/ReleaseRepository.cs @@ -1,38 +1,38 @@ using System; +using System.Linq; using Artemis.Storage.Entities.General; using Artemis.Storage.Repositories.Interfaces; -using LiteDB; namespace Artemis.Storage.Repositories; public class ReleaseRepository : IReleaseRepository { - private readonly LiteRepository _repository; + private readonly ArtemisDbContext _dbContext; - public ReleaseRepository(LiteRepository repository) + public ReleaseRepository(ArtemisDbContext dbContext) { - _repository = repository; - _repository.Database.GetCollection().EnsureIndex(s => s.Version, true); + _dbContext = dbContext; } public bool SaveVersionInstallDate(string version) { - ReleaseEntity release = _repository.Query().Where(r => r.Version == version).FirstOrDefault(); + ReleaseEntity? release = _dbContext.Releases.FirstOrDefault(r => r.Version == version); if (release != null) return false; - _repository.Insert(new ReleaseEntity {Version = version, InstalledAt = DateTimeOffset.UtcNow}); + _dbContext.Releases.Add(new ReleaseEntity {Version = version, InstalledAt = DateTimeOffset.UtcNow}); + _dbContext.SaveChanges(); return true; } - public ReleaseEntity GetPreviousInstalledVersion() + public ReleaseEntity? GetPreviousInstalledVersion() { - return _repository.Query().OrderByDescending(r => r.InstalledAt).Skip(1).FirstOrDefault(); + return _dbContext.Releases.OrderByDescending(r => r.InstalledAt).Skip(1).FirstOrDefault(); } } public interface IReleaseRepository : IRepository { bool SaveVersionInstallDate(string version); - ReleaseEntity GetPreviousInstalledVersion(); + ReleaseEntity? GetPreviousInstalledVersion(); } \ No newline at end of file diff --git a/src/Artemis.Storage/StorageMigrationService.cs b/src/Artemis.Storage/StorageMigrationService.cs deleted file mode 100644 index eca2a7dde..000000000 --- a/src/Artemis.Storage/StorageMigrationService.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Artemis.Storage.Migrations; -using LiteDB; -using Serilog; - -namespace Artemis.Storage; - -public class StorageMigrationService -{ - public const int PROFILE_VERSION = 4; - - private readonly ILogger _logger; - private readonly IList _migrations; - private readonly LiteRepository _repository; - - public StorageMigrationService(ILogger logger, LiteRepository repository, IList migrations) - { - _logger = logger; - _repository = repository; - _migrations = migrations; - - ApplyPendingMigrations(); - } - - public void ApplyPendingMigrations() - { - foreach (IStorageMigration storageMigration in _migrations.OrderBy(m => m.UserVersion)) - { - if (_repository.Database.UserVersion >= storageMigration.UserVersion) - continue; - - _logger.Information("Applying storage migration {storageMigration} to update DB from v{oldVersion} to v{newVersion}", - storageMigration.GetType().Name, _repository.Database.UserVersion, storageMigration.UserVersion); - - _repository.Database.BeginTrans(); - try - { - storageMigration.Apply(_repository); - } - catch (Exception) - { - _repository.Database.Rollback(); - throw; - } - - _repository.Database.Commit(); - - _repository.Database.UserVersion = storageMigration.UserVersion; - } - } -} \ No newline at end of file diff --git a/src/Artemis.WebClient.Workshop/Models/InstalledEntry.cs b/src/Artemis.WebClient.Workshop/Models/InstalledEntry.cs index 90aa4108e..1f722cc5d 100644 --- a/src/Artemis.WebClient.Workshop/Models/InstalledEntry.cs +++ b/src/Artemis.WebClient.Workshop/Models/InstalledEntry.cs @@ -1,12 +1,16 @@ using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Nodes; using Artemis.Core; using Artemis.Storage.Entities.Workshop; +using Artemis.WebClient.Workshop.Exceptions; namespace Artemis.WebClient.Workshop.Models; public class InstalledEntry { - private Dictionary _metadata = new(); + private static readonly JsonSerializerOptions JsonSerializerOptions = CoreJson.GetJsonSerializerOptions(); + private Dictionary _metadata = new(); internal InstalledEntry(EntryEntity entity) { @@ -52,7 +56,7 @@ public class InstalledEntry ReleaseVersion = Entity.ReleaseVersion; InstalledAt = Entity.InstalledAt; - _metadata = Entity.Metadata != null ? new Dictionary(Entity.Metadata) : new Dictionary(); + _metadata = Entity.Metadata != null ? new Dictionary(Entity.Metadata) : new Dictionary(); } internal void Save() @@ -67,7 +71,7 @@ public class InstalledEntry Entity.ReleaseVersion = ReleaseVersion; Entity.InstalledAt = InstalledAt; - Entity.Metadata = new Dictionary(_metadata); + Entity.Metadata = new Dictionary(_metadata); } /// @@ -80,14 +84,29 @@ public class InstalledEntry /// if the metadata contains an element with the specified key; otherwise, . public bool TryGetMetadata(string key, [NotNullWhen(true)] out T? value) { - if (!_metadata.TryGetValue(key, out object? objectValue) || objectValue is not T result) + if (!_metadata.TryGetValue(key, out JsonNode? jsonNode)) { value = default; return false; } - value = result; - return true; + try + { + T? deserialized = jsonNode.Deserialize(JsonSerializerOptions); + if (deserialized != null) + { + value = deserialized; + return true; + } + + value = default; + return false; + } + catch (Exception) + { + value = default; + return false; + } } /// @@ -97,7 +116,8 @@ public class InstalledEntry /// The value to set. public void SetMetadata(string key, object value) { - _metadata[key] = value; + JsonNode? jsonNode = JsonSerializer.SerializeToNode(value, JsonSerializerOptions); + _metadata[key] = jsonNode ?? throw new ArtemisWorkshopException("Failed to serialize metadata value"); } /// diff --git a/src/Artemis.WebClient.Workshop/Services/WorkshopService.cs b/src/Artemis.WebClient.Workshop/Services/WorkshopService.cs index 95b90ccc5..6d2d36e9a 100644 --- a/src/Artemis.WebClient.Workshop/Services/WorkshopService.cs +++ b/src/Artemis.WebClient.Workshop/Services/WorkshopService.cs @@ -171,7 +171,7 @@ public class WorkshopService : IWorkshopService public void SaveInstalledEntry(InstalledEntry entry) { entry.Save(); - _entryRepository.Save(entry.Entity); + _entryRepository.SaveChanges(); } /// diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props index 214bbcd9c..f1830bf8a 100644 --- a/src/Directory.Packages.props +++ b/src/Directory.Packages.props @@ -29,6 +29,8 @@ + +