From 461c0891bbe74d6fbfe8d8b795d01a47472274e7 Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Tue, 25 Aug 2020 19:33:53 -0500 Subject: [PATCH] =?UTF-8?q?feat(directory):=20=E2=9C=A8=F0=9F=9A=A7=20port?= =?UTF-8?q?=20forward=20data=20seeding=20logic?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- services/FilterLists.sln | 19 ++++++++++ .../Persistence/Queries/Entities/Dependent.cs | 3 +- .../Queries/Entities/FilterList.cs | 30 ++++++++------- .../Queries/Entities/FilterListLanguage.cs | 3 +- .../Queries/Entities/FilterListMaintainer.cs | 3 +- .../Queries/Entities/FilterListSyntax.cs | 3 +- .../Queries/Entities/FilterListTag.cs | 3 +- .../Persistence/Queries/Entities/Fork.cs | 3 +- .../Persistence/Queries/Entities/Language.cs | 2 +- .../Persistence/Queries/Entities/License.cs | 11 ++++++ .../Queries/Entities/Maintainer.cs | 11 ++++++ .../Persistence/Queries/Entities/Merge.cs | 3 +- .../Persistence/Queries/Entities/Software.cs | 11 ++++++ .../Queries/Entities/SoftwareSyntax.cs | 3 +- .../Persistence/Queries/Entities/Syntax.cs | 11 ++++++ .../Persistence/Queries/Entities/Tag.cs | 14 ++++++- .../Persistence/SeedExtensions.cs | 38 +++++++++++++++++++ 17 files changed, 139 insertions(+), 32 deletions(-) create mode 100644 services/directory/src/FilterLists.Directory.Infrastructure/Persistence/SeedExtensions.cs diff --git a/services/FilterLists.sln b/services/FilterLists.sln index ab7ed9e66..08a4ef9b4 100644 --- a/services/FilterLists.sln +++ b/services/FilterLists.sln @@ -23,6 +23,24 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution FilterLists.sln.DotSettings = FilterLists.sln.DotSettings EndProjectSection EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Data", "Data", "{8F419098-3EEB-4B4B-99A8-70555FA93DAF}" + ProjectSection(SolutionItems) = preProject + directory\data\Dependent.json = directory\data\Dependent.json + directory\data\FilterList.json = directory\data\FilterList.json + directory\data\FilterListLanguage.json = directory\data\FilterListLanguage.json + directory\data\FilterListMaintainer.json = directory\data\FilterListMaintainer.json + directory\data\FilterListTag.json = directory\data\FilterListTag.json + directory\data\Fork.json = directory\data\Fork.json + directory\data\Language.json = directory\data\Language.json + directory\data\License.json = directory\data\License.json + directory\data\Maintainer.json = directory\data\Maintainer.json + directory\data\Merge.json = directory\data\Merge.json + directory\data\Software.json = directory\data\Software.json + directory\data\SoftwareSyntax.json = directory\data\SoftwareSyntax.json + directory\data\Syntax.json = directory\data\Syntax.json + directory\data\Tag.json = directory\data\Tag.json + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -63,6 +81,7 @@ Global {CB1BCB34-C2A1-4E94-A90E-359FB4720B96} = {AE5D6471-1B6E-4B06-A313-34EF81F35342} {74C798F8-892A-40F2-8D2E-395E83853771} = {AE5D6471-1B6E-4B06-A313-34EF81F35342} {4F7D51FE-A1F3-4473-A8C3-D57EBDD8E60E} = {AE5D6471-1B6E-4B06-A313-34EF81F35342} + {8F419098-3EEB-4B4B-99A8-70555FA93DAF} = {AE5D6471-1B6E-4B06-A313-34EF81F35342} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {758B57EF-7505-4BE2-90A2-E2DE2EC32909} diff --git a/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/Dependent.cs b/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/Dependent.cs index 75ec063f5..30c7bf0aa 100644 --- a/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/Dependent.cs +++ b/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/Dependent.cs @@ -17,9 +17,7 @@ internal class DependentTypeConfiguration : IEntityTypeConfiguration public virtual void Configure(EntityTypeBuilder builder) { _ = builder ?? throw new ArgumentNullException(nameof(builder)); - builder.ToTable(nameof(Dependent) + "s"); - builder.HasKey(d => new {d.DependencyFilterListId, d.DependentFilterListId}); builder.HasOne(d => d.DependencyFilterList) .WithMany(fl => fl.DependentFilterLists) @@ -27,6 +25,7 @@ public virtual void Configure(EntityTypeBuilder builder) builder.HasOne(d => d.DependentFilterList) .WithMany(fl => fl.DependencyFilterLists) .HasForeignKey(d => d.DependentFilterListId); + builder.HasDataJsonFile(); } } } \ No newline at end of file diff --git a/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/FilterList.cs b/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/FilterList.cs index 375a221fe..b48a6fcd4 100644 --- a/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/FilterList.cs +++ b/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/FilterList.cs @@ -39,21 +39,23 @@ internal class FilterListTypeConfiguration : IEntityTypeConfiguration builder) { _ = builder ?? throw new ArgumentNullException(nameof(builder)); - builder.OwnsMany(fl => fl.SegmentViewUrls, - o => - { - o.ToTable(nameof(SegmentViewUrl) + "s"); - o.HasKey("Id"); - o.HasIndex(nameof(FilterList) + "Id", nameof(SegmentViewUrl.Position)).IsUnique(); - o.OwnsMany(p => p.SegmentViewUrlMirrors, - m => - { - m.ToTable(nameof(SegmentViewUrlMirror) + "s"); - m.Property("Id"); - m.HasKey("Id"); - }); - }); + o => + { + o.ToTable(nameof(SegmentViewUrl) + "s"); + o.HasKey("Id"); + o.HasIndex(nameof(FilterList) + "Id", nameof(SegmentViewUrl.Position)).IsUnique(); + o.OwnsMany(p => p.SegmentViewUrlMirrors, + m => + { + m.ToTable(nameof(SegmentViewUrlMirror) + "s"); + m.Property("Id"); + m.HasKey("Id"); + }) + .HasDataJsonFile(); + }) + .HasDataJsonFile(); + builder.HasDataJsonFile(); } } } \ No newline at end of file diff --git a/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/FilterListLanguage.cs b/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/FilterListLanguage.cs index 1902e32ba..bbf3a8353 100644 --- a/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/FilterListLanguage.cs +++ b/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/FilterListLanguage.cs @@ -17,10 +17,9 @@ internal class FilterListLanguageTypeConfiguration : IEntityTypeConfiguration builder) { _ = builder ?? throw new ArgumentNullException(nameof(builder)); - builder.ToTable(nameof(FilterListLanguage) + "s"); - builder.HasKey(fll => new {fll.FilterListId, fll.LanguageIso6391}); + builder.HasDataJsonFile(); } } } \ No newline at end of file diff --git a/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/FilterListMaintainer.cs b/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/FilterListMaintainer.cs index cfc618a26..a150d02ba 100644 --- a/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/FilterListMaintainer.cs +++ b/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/FilterListMaintainer.cs @@ -17,10 +17,9 @@ internal class FilterListMaintainerTypeConfiguration : IEntityTypeConfiguration< public virtual void Configure(EntityTypeBuilder builder) { _ = builder ?? throw new ArgumentNullException(nameof(builder)); - builder.ToTable(nameof(FilterListMaintainer) + "s"); - builder.HasKey(flm => new {flm.FilterListId, flm.MaintainerId}); + builder.HasDataJsonFile(); } } } \ No newline at end of file diff --git a/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/FilterListSyntax.cs b/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/FilterListSyntax.cs index 3d621a4ea..bf58dd631 100644 --- a/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/FilterListSyntax.cs +++ b/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/FilterListSyntax.cs @@ -17,10 +17,9 @@ internal class FilterListSyntaxTypeConfiguration : IEntityTypeConfiguration builder) { _ = builder ?? throw new ArgumentNullException(nameof(builder)); - builder.ToTable(nameof(FilterListSyntax) + "es"); - builder.HasKey(fls => new {fls.FilterListId, fls.SyntaxId}); + builder.HasDataJsonFile(); } } } \ No newline at end of file diff --git a/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/FilterListTag.cs b/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/FilterListTag.cs index 660dbc6bd..878b7fc4e 100644 --- a/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/FilterListTag.cs +++ b/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/FilterListTag.cs @@ -17,10 +17,9 @@ internal class FilterListTagTypeConfiguration : IEntityTypeConfiguration builder) { _ = builder ?? throw new ArgumentNullException(nameof(builder)); - builder.ToTable(nameof(FilterListTag) + "s"); - builder.HasKey(flt => new {flt.FilterListId, flt.TagId}); + builder.HasDataJsonFile(); } } } \ No newline at end of file diff --git a/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/Fork.cs b/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/Fork.cs index ab58246f2..91242ff2d 100644 --- a/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/Fork.cs +++ b/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/Fork.cs @@ -17,9 +17,7 @@ internal class ForkTypeConfiguration : IEntityTypeConfiguration public virtual void Configure(EntityTypeBuilder builder) { _ = builder ?? throw new ArgumentNullException(nameof(builder)); - builder.ToTable(nameof(Fork) + "s"); - builder.HasKey(f => new {f.UpstreamFilterListId, f.ForkFilterListId}); builder.HasOne(f => f.UpstreamFilterList) .WithMany(fl => fl.ForkFilterLists) @@ -27,6 +25,7 @@ public virtual void Configure(EntityTypeBuilder builder) builder.HasOne(f => f.ForkFilterList) .WithMany(fl => fl.UpstreamFilterLists) .HasForeignKey(f => f.ForkFilterListId); + builder.HasDataJsonFile(); } } } \ No newline at end of file diff --git a/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/Language.cs b/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/Language.cs index 1b45d4c63..e15c290c7 100644 --- a/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/Language.cs +++ b/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/Language.cs @@ -17,8 +17,8 @@ internal class LanguageTypeConfiguration : IEntityTypeConfiguration public virtual void Configure(EntityTypeBuilder builder) { _ = builder ?? throw new ArgumentNullException(nameof(builder)); - builder.HasKey(l => l.Iso6391); + builder.HasDataJsonFile(); } } } \ No newline at end of file diff --git a/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/License.cs b/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/License.cs index ee03271e2..3d4386b66 100644 --- a/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/License.cs +++ b/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/License.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; namespace FilterLists.Directory.Infrastructure.Persistence.Queries.Entities { @@ -11,4 +13,13 @@ public class License public Uri? Url { get; private set; } public IReadOnlyCollection FilterLists { get; private set; } = new HashSet(); } + + internal class LicenseTypeConfiguration : IEntityTypeConfiguration + { + public virtual void Configure(EntityTypeBuilder builder) + { + _ = builder ?? throw new ArgumentNullException(nameof(builder)); + builder.HasDataJsonFile(); + } + } } \ No newline at end of file diff --git a/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/Maintainer.cs b/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/Maintainer.cs index ad75c0413..47f168287 100644 --- a/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/Maintainer.cs +++ b/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/Maintainer.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; namespace FilterLists.Directory.Infrastructure.Persistence.Queries.Entities { @@ -12,4 +14,13 @@ public class Maintainer public string? TwitterHandle { get; private set; } public IReadOnlyCollection FilterListMaintainers { get; private set; } = new HashSet(); } + + internal class MaintainerTypeConfiguration : IEntityTypeConfiguration + { + public virtual void Configure(EntityTypeBuilder builder) + { + _ = builder ?? throw new ArgumentNullException(nameof(builder)); + builder.HasDataJsonFile(); + } + } } \ No newline at end of file diff --git a/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/Merge.cs b/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/Merge.cs index 18d70f924..c0fdd7419 100644 --- a/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/Merge.cs +++ b/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/Merge.cs @@ -17,9 +17,7 @@ internal class MergeTypeConfiguration : IEntityTypeConfiguration public virtual void Configure(EntityTypeBuilder builder) { _ = builder ?? throw new ArgumentNullException(nameof(builder)); - builder.ToTable(nameof(Merge) + "s"); - builder.HasKey(m => new {m.IncludedInFilterListId, m.IncludesFilterListId}); builder.HasOne(m => m.IncludedInFilterList) .WithMany(fl => fl.IncludesFilterLists) @@ -27,6 +25,7 @@ public virtual void Configure(EntityTypeBuilder builder) builder.HasOne(m => m.IncludesFilterList) .WithMany(fl => fl.IncludedInFilterLists) .HasForeignKey(m => m.IncludesFilterListId); + builder.HasDataJsonFile(); } } } \ No newline at end of file diff --git a/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/Software.cs b/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/Software.cs index b48a772e7..c7695f4e3 100644 --- a/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/Software.cs +++ b/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/Software.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; namespace FilterLists.Directory.Infrastructure.Persistence.Queries.Entities { @@ -13,4 +15,13 @@ public class Software public bool SupportsAbpUrlScheme { get; private set; } public IReadOnlyCollection SoftwareSyntaxes { get; private set; } = new HashSet(); } + + internal class SoftwareTypeConfiguration : IEntityTypeConfiguration + { + public virtual void Configure(EntityTypeBuilder builder) + { + _ = builder ?? throw new ArgumentNullException(nameof(builder)); + builder.HasDataJsonFile(); + } + } } \ No newline at end of file diff --git a/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/SoftwareSyntax.cs b/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/SoftwareSyntax.cs index 9d35c7a54..1f5f27730 100644 --- a/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/SoftwareSyntax.cs +++ b/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/SoftwareSyntax.cs @@ -17,10 +17,9 @@ internal class SoftwareSyntaxTypeConfiguration : IEntityTypeConfiguration builder) { _ = builder ?? throw new ArgumentNullException(nameof(builder)); - builder.ToTable(nameof(SoftwareSyntax) + "es"); - builder.HasKey(ss => new {ss.SoftwareId, ss.SyntaxId}); + builder.HasDataJsonFile(); } } } \ No newline at end of file diff --git a/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/Syntax.cs b/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/Syntax.cs index a4bddd20f..38520951e 100644 --- a/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/Syntax.cs +++ b/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/Syntax.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; namespace FilterLists.Directory.Infrastructure.Persistence.Queries.Entities { @@ -12,4 +14,13 @@ public class Syntax public IReadOnlyCollection FilterListSyntaxes { get; private set; } = new HashSet(); public IReadOnlyCollection SoftwareSyntaxes { get; private set; } = new HashSet(); } + + internal class SyntaxTypeConfiguration : IEntityTypeConfiguration + { + public virtual void Configure(EntityTypeBuilder builder) + { + _ = builder ?? throw new ArgumentNullException(nameof(builder)); + builder.HasDataJsonFile(); + } + } } \ No newline at end of file diff --git a/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/Tag.cs b/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/Tag.cs index 8073d3cd6..7b3076a84 100644 --- a/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/Tag.cs +++ b/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/Queries/Entities/Tag.cs @@ -1,4 +1,7 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; namespace FilterLists.Directory.Infrastructure.Persistence.Queries.Entities { @@ -9,4 +12,13 @@ public class Tag public string? Description { get; private set; } public IReadOnlyCollection FilterListTags { get; private set; } = new HashSet(); } + + internal class TagTypeConfiguration : IEntityTypeConfiguration + { + public virtual void Configure(EntityTypeBuilder builder) + { + _ = builder ?? throw new ArgumentNullException(nameof(builder)); + builder.HasDataJsonFile(); + } + } } \ No newline at end of file diff --git a/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/SeedExtensions.cs b/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/SeedExtensions.cs new file mode 100644 index 000000000..a479273cc --- /dev/null +++ b/services/directory/src/FilterLists.Directory.Infrastructure/Persistence/SeedExtensions.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.Json; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace FilterLists.Directory.Infrastructure.Persistence +{ + internal static class SeedExtensions + { + public static void HasDataJsonFile(this EntityTypeBuilder entityTypeBuilder) + { + _ = entityTypeBuilder ?? throw new ArgumentNullException(nameof(entityTypeBuilder)); + var entities = GetEntities(); + entityTypeBuilder.HasData((IEnumerable)entities); + } + + public static void HasDataJsonFile(this OwnedNavigationBuilder ownedNavigationBuilder) + { + _ = ownedNavigationBuilder ?? throw new ArgumentNullException(nameof(ownedNavigationBuilder)); + var entities = GetEntities(); + ownedNavigationBuilder.HasData((IEnumerable)entities); + } + + private static IEnumerable GetEntities() + { + var path = Path.Combine("../../../data", $"{typeof(TEntity).Name}.json"); + if (!File.Exists(path)) return new HashSet(); + + var entitiesJson = File.ReadAllText(path); + var entities = JsonSerializer.Deserialize>(entitiesJson, new JsonSerializerOptions + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase + }); + return entities; + } + } +} \ No newline at end of file