diff --git a/src/AVPRIndex/AVPRIndex.fsproj b/src/AVPRIndex/AVPRIndex.fsproj
index 1c7b46b..b26a55e 100644
--- a/src/AVPRIndex/AVPRIndex.fsproj
+++ b/src/AVPRIndex/AVPRIndex.fsproj
@@ -5,7 +5,23 @@
true
+
+ Kevin Schneider
+ Type system for the indexing backend of avpr.nfdi4plants.org
+ Type system for the indexing backend of avpr.nfdi4plants.org
+ MIT
+ C# F# ARC annotated-research-context rdm research-data-management validation
+ https://github.com/nfdi4plants/arc-validate-package-registry
+ https://github.com/nfdi4plants/arc-validate-package-registry
+ git
+ $([System.IO.File]::ReadAllText("$(MSBuildProjectDirectory)/RELEASE_NOTES.md"))
+ README.md
+ 0.0.1
+
+
+
+
diff --git a/src/AVPRIndex/Domain.fs b/src/AVPRIndex/Domain.fs
index 925a837..5dda8a0 100644
--- a/src/AVPRIndex/Domain.fs
+++ b/src/AVPRIndex/Domain.fs
@@ -39,9 +39,37 @@ module Domain =
)
| _ -> false
+ type OntologyAnnotation() =
+
+ member val Name = "" with get,set
+ member val TermSourceREF = "" with get,set
+ member val TermAccessionNumber = "" with get,set
+
+ override this.GetHashCode() =
+ hash (
+ this.Name,
+ this.TermSourceREF,
+ this.TermAccessionNumber
+ )
+
+ override this.Equals(other) =
+ match other with
+ | :? OntologyAnnotation as oa ->
+ (
+ this.Name,
+ this.TermSourceREF,
+ this.TermAccessionNumber
+ ) = (
+ oa.Name,
+ oa.TermSourceREF,
+ oa.TermAccessionNumber
+ )
+ | _ -> false
+
type ValidationPackageMetadata() =
// mandatory fields
member val Name = "" with get,set
+ member val Summary = "" with get,set
member val Description = "" with get,set
member val MajorVersion = 0 with get,set
member val MinorVersion = 0 with get,set
@@ -49,12 +77,13 @@ module Domain =
// optional fields
member val Publish = false with get,set
member val Authors: Author [] = Array.empty with get,set
- member val Tags: string [] = Array.empty with get,set
+ member val Tags: OntologyAnnotation [] = Array.empty with get,set
member val ReleaseNotes = "" with get,set
override this.GetHashCode() =
hash (
this.Name,
+ this.Summary,
this.Description,
this.MajorVersion,
this.MinorVersion,
@@ -70,6 +99,7 @@ module Domain =
| :? ValidationPackageMetadata as vpm ->
(
this.Name,
+ this.Summary,
this.Description,
this.MajorVersion,
this.MinorVersion,
@@ -80,6 +110,7 @@ module Domain =
this.ReleaseNotes
) = (
vpm.Name,
+ vpm.Summary,
vpm.Description,
vpm.MajorVersion,
vpm.MinorVersion,
diff --git a/src/AVPRIndex/README.md b/src/AVPRIndex/README.md
new file mode 100644
index 0000000..7d91980
--- /dev/null
+++ b/src/AVPRIndex/README.md
@@ -0,0 +1,5 @@
+# AVPR Index
+
+Type system for the indexing backend of https://avpr.nfdi4plants.org.
+
+This lib exposes the type system and utilities needed to parse and index arc validation packages with yaml frontmatter.
\ No newline at end of file
diff --git a/src/AVPRIndex/RELEASE_NOTES.md b/src/AVPRIndex/RELEASE_NOTES.md
new file mode 100644
index 0000000..e48f2bb
--- /dev/null
+++ b/src/AVPRIndex/RELEASE_NOTES.md
@@ -0,0 +1,3 @@
+## v0.0.1
+
+- Initial release for AVPR API v1
\ No newline at end of file
diff --git a/src/PackageRegistryService/Data/DataInitializer.cs b/src/PackageRegistryService/Data/DataInitializer.cs
index 5659bd7..ac66637 100644
--- a/src/PackageRegistryService/Data/DataInitializer.cs
+++ b/src/PackageRegistryService/Data/DataInitializer.cs
@@ -10,7 +10,7 @@
using static AVPRIndex.Frontmatter;
namespace PackageRegistryService.Data
-
+
{
public class DataInitializer
{
@@ -18,7 +18,7 @@ public static List ReadIndex()
{
var json = File.ReadAllText(@"Data/arc-validate-package-index.json");
var index = JsonSerializer.Deserialize>(json);
- return index;
+ return index ?? [];
}
public static void SeedData(ValidationPackageDb context)
{
@@ -39,6 +39,7 @@ public static void SeedData(ValidationPackageDb context)
return new ValidationPackage
{
Name = i.Metadata.Name,
+ Summary = i.Metadata.Summary,
Description = i.Metadata.Description,
MajorVersion = i.Metadata.MajorVersion,
MinorVersion = i.Metadata.MinorVersion,
diff --git a/src/PackageRegistryService/Data/arc-validate-package-index.json b/src/PackageRegistryService/Data/arc-validate-package-index.json
index 910ec9b..f8746bb 100644
--- a/src/PackageRegistryService/Data/arc-validate-package-index.json
+++ b/src/PackageRegistryService/Data/arc-validate-package-index.json
@@ -2,7 +2,7 @@
{
"RepoPath": "src/PackageRegistryService/StagingArea/invenio/invenio@1.0.0.fsx",
"FileName": "invenio@1.0.0.fsx",
- "LastUpdated": "2024-02-29T14:45:26+01:00",
+ "LastUpdated": "2024-02-29T14:45:24+01:00",
"ContentHash": "864458DA6C7B0F08A546210CFD3CCA4A",
"Metadata": {
"Name": "invenio",
@@ -74,7 +74,7 @@
{
"RepoPath": "src/PackageRegistryService/StagingArea/test/test@2.0.0.fsx",
"FileName": "test@2.0.0.fsx",
- "LastUpdated": "2024-02-29T14:45:26+01:00",
+ "LastUpdated": "2024-02-29T14:45:24+01:00",
"ContentHash": "40729E451689807AEFF17F5932843A4C",
"Metadata": {
"Name": "test",
@@ -121,7 +121,7 @@
{
"RepoPath": "src/PackageRegistryService/StagingArea/test/test@3.0.0.fsx",
"FileName": "test@3.0.0.fsx",
- "LastUpdated": "2024-02-29T14:45:26+01:00",
+ "LastUpdated": "2024-02-29T14:45:24+01:00",
"ContentHash": "0537642158095CE84F4FA8363225831E",
"Metadata": {
"Name": "test",
diff --git a/src/PackageRegistryService/Migrations/20240229124121_AddSummaryAndOntologyTags.Designer.cs b/src/PackageRegistryService/Migrations/20240229124121_AddSummaryAndOntologyTags.Designer.cs
new file mode 100644
index 0000000..0ec1b68
--- /dev/null
+++ b/src/PackageRegistryService/Migrations/20240229124121_AddSummaryAndOntologyTags.Designer.cs
@@ -0,0 +1,174 @@
+//
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+using PackageRegistryService.Models;
+
+#nullable disable
+
+namespace PackageRegistryService.Migrations
+{
+ [DbContext(typeof(ValidationPackageDb))]
+ [Migration("20240229124121_AddSummaryAndOntologyTags")]
+ partial class AddSummaryAndOntologyTags
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "8.0.1")
+ .HasAnnotation("Relational:MaxIdentifierLength", 63);
+
+ NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
+
+ modelBuilder.Entity("PackageRegistryService.Models.PackageContentHash", b =>
+ {
+ b.Property("PackageName")
+ .HasColumnType("text");
+
+ b.Property("PackageMajorVersion")
+ .HasColumnType("integer");
+
+ b.Property("PackageMinorVersion")
+ .HasColumnType("integer");
+
+ b.Property("PackagePatchVersion")
+ .HasColumnType("integer");
+
+ b.Property("Hash")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("PackageName", "PackageMajorVersion", "PackageMinorVersion", "PackagePatchVersion");
+
+ b.ToTable("Hashes");
+ });
+
+ modelBuilder.Entity("PackageRegistryService.Models.ValidationPackage", b =>
+ {
+ b.Property("Name")
+ .HasColumnType("text");
+
+ b.Property("MajorVersion")
+ .HasColumnType("integer");
+
+ b.Property("MinorVersion")
+ .HasColumnType("integer");
+
+ b.Property("PatchVersion")
+ .HasColumnType("integer");
+
+ b.Property("Description")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("PackageContent")
+ .IsRequired()
+ .HasColumnType("bytea");
+
+ b.Property("ReleaseDate")
+ .HasColumnType("date");
+
+ b.Property("ReleaseNotes")
+ .HasColumnType("text");
+
+ b.Property("Summary")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Name", "MajorVersion", "MinorVersion", "PatchVersion");
+
+ b.ToTable("ValidationPackages");
+ });
+
+ modelBuilder.Entity("PackageRegistryService.Models.ValidationPackage", b =>
+ {
+ b.OwnsMany("AVPRIndex.Domain+Author", "Authors", b1 =>
+ {
+ b1.Property("ValidationPackageName")
+ .HasColumnType("text");
+
+ b1.Property("ValidationPackageMajorVersion")
+ .HasColumnType("integer");
+
+ b1.Property("ValidationPackageMinorVersion")
+ .HasColumnType("integer");
+
+ b1.Property("ValidationPackagePatchVersion")
+ .HasColumnType("integer");
+
+ b1.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ b1.Property("Affiliation")
+ .HasColumnType("text");
+
+ b1.Property("AffiliationLink")
+ .HasColumnType("text");
+
+ b1.Property("Email")
+ .HasColumnType("text");
+
+ b1.Property("FullName")
+ .HasColumnType("text");
+
+ b1.HasKey("ValidationPackageName", "ValidationPackageMajorVersion", "ValidationPackageMinorVersion", "ValidationPackagePatchVersion", "Id");
+
+ b1.ToTable("ValidationPackages");
+
+ b1.ToJson("Authors");
+
+ b1.WithOwner()
+ .HasForeignKey("ValidationPackageName", "ValidationPackageMajorVersion", "ValidationPackageMinorVersion", "ValidationPackagePatchVersion");
+ });
+
+ b.OwnsMany("AVPRIndex.Domain+OntologyAnnotation", "Tags", b1 =>
+ {
+ b1.Property("ValidationPackageName")
+ .HasColumnType("text");
+
+ b1.Property("ValidationPackageMajorVersion")
+ .HasColumnType("integer");
+
+ b1.Property("ValidationPackageMinorVersion")
+ .HasColumnType("integer");
+
+ b1.Property("ValidationPackagePatchVersion")
+ .HasColumnType("integer");
+
+ b1.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ b1.Property("Name")
+ .HasColumnType("text");
+
+ b1.Property("TermAccessionNumber")
+ .HasColumnType("text");
+
+ b1.Property("TermSourceREF")
+ .HasColumnType("text");
+
+ b1.HasKey("ValidationPackageName", "ValidationPackageMajorVersion", "ValidationPackageMinorVersion", "ValidationPackagePatchVersion", "Id");
+
+ b1.ToTable("ValidationPackages");
+
+ b1.ToJson("Tags");
+
+ b1.WithOwner()
+ .HasForeignKey("ValidationPackageName", "ValidationPackageMajorVersion", "ValidationPackageMinorVersion", "ValidationPackagePatchVersion");
+ });
+
+ b.Navigation("Authors");
+
+ b.Navigation("Tags");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/src/PackageRegistryService/Migrations/20240229124121_AddSummaryAndOntologyTags.cs b/src/PackageRegistryService/Migrations/20240229124121_AddSummaryAndOntologyTags.cs
new file mode 100644
index 0000000..d6c5216
--- /dev/null
+++ b/src/PackageRegistryService/Migrations/20240229124121_AddSummaryAndOntologyTags.cs
@@ -0,0 +1,83 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace PackageRegistryService.Migrations
+{
+ ///
+ public partial class AddSummaryAndOntologyTags : Migration
+ {
+ ///
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+
+ migrationBuilder.Sql(@"
+ CREATE FUNCTION transform_tags(tags text[]) RETURNS jsonb AS $$
+ BEGIN
+ RETURN jsonb_agg(jsonb_build_object('Name', tag)) FROM unnest(tags) AS tag;
+ END;
+ $$ LANGUAGE plpgsql;
+ ");
+
+ migrationBuilder.Sql(@"
+ ALTER TABLE ""ValidationPackages""
+ ADD COLUMN ""TMP"" jsonb
+ ");
+
+ migrationBuilder.Sql(@"
+ UPDATE ""ValidationPackages""
+ SET ""TMP"" = transform_tags(""Tags"")
+ ");
+
+ migrationBuilder.Sql(@"
+ ALTER TABLE ""ValidationPackages""
+ DROP COLUMN ""Tags"";
+ ALTER TABLE ""ValidationPackages""
+ RENAME COLUMN ""TMP"" TO ""Tags"";
+ ");
+
+ migrationBuilder.AddColumn(
+ name: "Summary",
+ table: "ValidationPackages",
+ type: "text",
+ nullable: false,
+ defaultValue: "");
+ }
+
+ ///
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.Sql(@"
+ DROP FUNCTION IF EXISTS transform_tags(text[]);
+ ");
+
+ migrationBuilder.Sql(@"
+ ALTER TABLE ""ValidationPackages""
+ ADD COLUMN ""TMP"" text[]
+ ");
+
+ migrationBuilder.Sql(@"
+ UPDATE ""ValidationPackages""
+ SET ""TMP"" = (
+ SELECT array_agg(tag->>'Name') FROM jsonb_array_elements(""Tags"") AS tag
+ )
+ ");
+
+ migrationBuilder.Sql(@"
+ ALTER TABLE ""ValidationPackages""
+ DROP COLUMN ""Tags"";
+ ALTER TABLE ""ValidationPackages""
+ RENAME COLUMN ""TMP"" TO ""Tags"";
+ ");
+
+ migrationBuilder.AlterColumn(
+ name: "Tags",
+ table: "ValidationPackages",
+ type: "text[]",
+ nullable: true,
+ oldClrType: typeof(string),
+ oldType: "jsonb",
+ oldNullable: true);
+ }
+ }
+}
diff --git a/src/PackageRegistryService/Migrations/ValidationPackageDbModelSnapshot.cs b/src/PackageRegistryService/Migrations/ValidationPackageDbModelSnapshot.cs
index 1deb89c..6f92400 100644
--- a/src/PackageRegistryService/Migrations/ValidationPackageDbModelSnapshot.cs
+++ b/src/PackageRegistryService/Migrations/ValidationPackageDbModelSnapshot.cs
@@ -73,8 +73,9 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.Property("ReleaseNotes")
.HasColumnType("text");
- b.Property("Tags")
- .HasColumnType("text[]");
+ b.Property("Summary")
+ .IsRequired()
+ .HasColumnType("text");
b.HasKey("Name", "MajorVersion", "MinorVersion", "PatchVersion");
@@ -83,7 +84,7 @@ protected override void BuildModel(ModelBuilder modelBuilder)
modelBuilder.Entity("PackageRegistryService.Models.ValidationPackage", b =>
{
- b.OwnsMany("PackageRegistryService.Models.Author", "Authors", b1 =>
+ b.OwnsMany("AVPRIndex.Domain+Author", "Authors", b1 =>
{
b1.Property("ValidationPackageName")
.HasColumnType("text");
@@ -102,19 +103,15 @@ protected override void BuildModel(ModelBuilder modelBuilder)
.HasColumnType("integer");
b1.Property("Affiliation")
- .IsRequired()
.HasColumnType("text");
b1.Property("AffiliationLink")
- .IsRequired()
.HasColumnType("text");
b1.Property("Email")
- .IsRequired()
.HasColumnType("text");
b1.Property("FullName")
- .IsRequired()
.HasColumnType("text");
b1.HasKey("ValidationPackageName", "ValidationPackageMajorVersion", "ValidationPackageMinorVersion", "ValidationPackagePatchVersion", "Id");
@@ -127,7 +124,46 @@ protected override void BuildModel(ModelBuilder modelBuilder)
.HasForeignKey("ValidationPackageName", "ValidationPackageMajorVersion", "ValidationPackageMinorVersion", "ValidationPackagePatchVersion");
});
+ b.OwnsMany("AVPRIndex.Domain+OntologyAnnotation", "Tags", b1 =>
+ {
+ b1.Property("ValidationPackageName")
+ .HasColumnType("text");
+
+ b1.Property("ValidationPackageMajorVersion")
+ .HasColumnType("integer");
+
+ b1.Property("ValidationPackageMinorVersion")
+ .HasColumnType("integer");
+
+ b1.Property("ValidationPackagePatchVersion")
+ .HasColumnType("integer");
+
+ b1.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ b1.Property("Name")
+ .HasColumnType("text");
+
+ b1.Property("TermAccessionNumber")
+ .HasColumnType("text");
+
+ b1.Property("TermSourceREF")
+ .HasColumnType("text");
+
+ b1.HasKey("ValidationPackageName", "ValidationPackageMajorVersion", "ValidationPackageMinorVersion", "ValidationPackagePatchVersion", "Id");
+
+ b1.ToTable("ValidationPackages");
+
+ b1.ToJson("Tags");
+
+ b1.WithOwner()
+ .HasForeignKey("ValidationPackageName", "ValidationPackageMajorVersion", "ValidationPackageMinorVersion", "ValidationPackagePatchVersion");
+ });
+
b.Navigation("Authors");
+
+ b.Navigation("Tags");
});
#pragma warning restore 612, 618
}
diff --git a/src/PackageRegistryService/Models/ValidationPackage.cs b/src/PackageRegistryService/Models/ValidationPackage.cs
index ae5d360..9e815e3 100644
--- a/src/PackageRegistryService/Models/ValidationPackage.cs
+++ b/src/PackageRegistryService/Models/ValidationPackage.cs
@@ -20,9 +20,18 @@ public class ValidationPackage
[Key]
public required string Name { get; set; }
///
- /// Free text validation package description.
+ /// Single sentence validation package description.
///
/// MyPackage does the thing
+ public required string Summary { get; set; }
+ ///
+ /// Free text validation package description.
+ ///
+ ///
+ /// MyPackage does the thing.
+ /// It does it very good, it does it very well.
+ /// It does it very fast, it does it very swell.
+ ///
public required string Description { get; set; }
///
/// SemVer major version of the validation package.
@@ -54,7 +63,7 @@ public class ValidationPackage
///
///
///
- public string[]? Tags { get; set; }
+ public ICollection? Tags { get; set; }
///
///
///
diff --git a/src/PackageRegistryService/Models/ValidationPackageDb.cs b/src/PackageRegistryService/Models/ValidationPackageDb.cs
index 5898eae..eb8dfec 100644
--- a/src/PackageRegistryService/Models/ValidationPackageDb.cs
+++ b/src/PackageRegistryService/Models/ValidationPackageDb.cs
@@ -19,6 +19,10 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
.OwnsMany(v => v.Authors, a =>
{
a.ToJson();
+ })
+ .OwnsMany(v => v.Tags, t =>
+ {
+ t.ToJson();
});
}
}
diff --git a/src/PackageRegistryService/PackageRegistryService.csproj b/src/PackageRegistryService/PackageRegistryService.csproj
index b8aad75..fec1b0c 100644
--- a/src/PackageRegistryService/PackageRegistryService.csproj
+++ b/src/PackageRegistryService/PackageRegistryService.csproj
@@ -29,6 +29,7 @@
+
diff --git a/src/PackageRegistryService/Pages/Handlers/PackageHandlers.cs b/src/PackageRegistryService/Pages/Handlers/PackageHandlers.cs
index baae68b..a92a5d4 100644
--- a/src/PackageRegistryService/Pages/Handlers/PackageHandlers.cs
+++ b/src/PackageRegistryService/Pages/Handlers/PackageHandlers.cs
@@ -48,7 +48,7 @@ public static async Task
packageVersion: package.GetSemanticVersionString(),
packageContent: Encoding.UTF8.GetString(package.PackageContent),
packageReleaseDate: package.ReleaseDate,
- packageTags: package.Tags ?? [],
+ packageTags: (package.Tags ?? []).Select(t => t.Name).ToArray(),
packageDescription: package.Description,
packageReleaseNotes: package.ReleaseNotes ?? "",
packageAuthors: (package.Authors ?? []).ToArray(),
@@ -85,7 +85,7 @@ public static async Task> RenderLatest(stri
packageVersion: latestPackage.GetSemanticVersionString(),
packageContent: Encoding.UTF8.GetString(latestPackage.PackageContent),
packageReleaseDate: latestPackage.ReleaseDate,
- packageTags: latestPackage.Tags ?? [],
+ packageTags: (latestPackage.Tags ?? []).Select(t => t.Name).ToArray(),
packageDescription: latestPackage.Description,
packageReleaseNotes: latestPackage.ReleaseNotes ?? "",
packageAuthors: (latestPackage.Authors ?? []).ToArray(),
diff --git a/src/PackageRegistryService/Pages/Handlers/PackagesHandlers.cs b/src/PackageRegistryService/Pages/Handlers/PackagesHandlers.cs
index b1ca2a5..9c48544 100644
--- a/src/PackageRegistryService/Pages/Handlers/PackagesHandlers.cs
+++ b/src/PackageRegistryService/Pages/Handlers/PackagesHandlers.cs
@@ -37,7 +37,7 @@ public static async Task Render(ValidationPackageDb database)
return
new PackageSummary(
Name: group.Key,
- Tags: latestPackage.Tags ?? [],
+ Tags: (latestPackage.Tags ?? []).Select(t => t.Name).ToArray(),
Description: latestPackage.Description,
ReleaseDate: latestPackage.ReleaseDate,
LatestVersion: latestPackage.GetSemanticVersionString()