Skip to content

Commit

Permalink
Added pages/components for NuGet packages and fixed upload issues
Browse files Browse the repository at this point in the history
  • Loading branch information
ricardoboss committed Dec 31, 2024
1 parent a080893 commit eef20c2
Show file tree
Hide file tree
Showing 44 changed files with 1,405 additions and 157 deletions.
25 changes: 25 additions & 0 deletions .idea/.idea.PubNet/.idea/jsonSchemas.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ public class DartPackageVersionDto : PackageVersionDto
{
public static DartPackageVersionDto MapFrom(DartPackageVersion version, Uri archiveUrl, string archiveSha256)
{
return new()
return new DartPackageVersionDto
{
Version = version.Version,
ArchiveUrl = archiveUrl,
Expand Down
43 changes: 41 additions & 2 deletions Backend/PubNet.API.DTO/Packages/Nuget/NugetPackageVersionDto.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,54 @@
using PubNet.Database.Entities.Nuget;
using PubNet.API.DTO.Packages.Nuget.Spec;
using PubNet.Database.Entities.Nuget;

namespace PubNet.API.DTO.Packages.Nuget;

public class NugetPackageVersionDto : PackageVersionDto
{
public required string PackageId { get; init; }

public string? Title { get; init; }

public string? Description { get; init; }

public string? Authors { get; init; }

public string? IconUrl { get; init; }

public string? ProjectUrl { get; init; }

public string? Copyright { get; init; }

public string? Tags { get; init; }

public string? ReadmeFile { get; init; }

public string? IconFile { get; init; }

public NugetRepositoryMetadataDto? RepositoryMetadata { get; init; }

public List<NugetPackageDependencyGroupDto>? DependencyGroups { get; init; }

public static NugetPackageVersionDto MapFrom(NugetPackageVersion version)
{
return new()
return new NugetPackageVersionDto
{
PackageId = version.NuspecId!,
Version = version.Version,
PublishedAt = version.PublishedAt,
Title = version.Title,
Description = version.Description,
Authors = version.Authors,
IconUrl = version.IconUrl,
ProjectUrl = version.ProjectUrl,
Copyright = version.Copyright,
Tags = version.Tags,
ReadmeFile = version.ReadmeFile,
IconFile = version.IconFile,
RepositoryMetadata = version.RepositoryMetadata is null
? null
: NugetRepositoryMetadataDto.MapFrom(version.RepositoryMetadata),
DependencyGroups = version.DependencyGroups?.Select(NugetPackageDependencyGroupDto.MapFrom).ToList(),
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using NuGet.Packaging.Core;
using Riok.Mapperly.Abstractions;

namespace PubNet.API.DTO.Packages.Nuget;

[Mapper]
public partial class NugetRepositoryMetadataDto
{
public static partial NugetRepositoryMetadataDto MapFrom(RepositoryMetadata metadata);

Check warning on line 9 in Backend/PubNet.API.DTO/Packages/Nuget/NugetRepositoryMetadataDto.cs

View workflow job for this annotation

GitHub Actions / Build & Test using 8.x on windows-latest

The member Type on the mapping source type NuGet.Packaging.Core.RepositoryMetadata is not mapped to any member on the mapping target type PubNet.API.DTO.Packages.Nuget.NugetRepositoryMetadataDto

Check warning on line 9 in Backend/PubNet.API.DTO/Packages/Nuget/NugetRepositoryMetadataDto.cs

View workflow job for this annotation

GitHub Actions / Build & Test using 8.x on windows-latest

The member Url on the mapping source type NuGet.Packaging.Core.RepositoryMetadata is not mapped to any member on the mapping target type PubNet.API.DTO.Packages.Nuget.NugetRepositoryMetadataDto

Check warning on line 9 in Backend/PubNet.API.DTO/Packages/Nuget/NugetRepositoryMetadataDto.cs

View workflow job for this annotation

GitHub Actions / Build & Test using 8.x on windows-latest

The member Branch on the mapping source type NuGet.Packaging.Core.RepositoryMetadata is not mapped to any member on the mapping target type PubNet.API.DTO.Packages.Nuget.NugetRepositoryMetadataDto

Check warning on line 9 in Backend/PubNet.API.DTO/Packages/Nuget/NugetRepositoryMetadataDto.cs

View workflow job for this annotation

GitHub Actions / Build & Test using 8.x on windows-latest

The member Commit on the mapping source type NuGet.Packaging.Core.RepositoryMetadata is not mapped to any member on the mapping target type PubNet.API.DTO.Packages.Nuget.NugetRepositoryMetadataDto

Check warning on line 9 in Backend/PubNet.API.DTO/Packages/Nuget/NugetRepositoryMetadataDto.cs

View workflow job for this annotation

GitHub Actions / Build & Test using 8.x on windows-latest

No members are mapped in the object mapping from NuGet.Packaging.Core.RepositoryMetadata to PubNet.API.DTO.Packages.Nuget.NugetRepositoryMetadataDto (https://mapperly.riok.app/docs/configuration/analyzer-diagnostics/RMG066)
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
using NuGet.Packaging.Core;
using Riok.Mapperly.Abstractions;

namespace PubNet.API.DTO.Packages.Nuget.Spec;

/// <summary>
/// If the <c>range</c> property is excluded or an empty string, the client should default to the version range
/// <c>(, )</c>. That is, any version of the dependency is allowed. The value of <c>*</c> is not allowed for the
/// <c>range</c> property.
/// </summary>
public class NugetPackageDependencyDto
[Mapper]
public partial class NugetPackageDependencyDto
{
public static partial NugetPackageDependencyDto MapFrom(PackageDependency dependency);

Check warning on line 14 in Backend/PubNet.API.DTO/Packages/Nuget/Spec/NugetPackageDependencyDto.cs

View workflow job for this annotation

GitHub Actions / Build & Test using 8.x on windows-latest

The member Range on the mapping target type PubNet.API.DTO.Packages.Nuget.Spec.NugetPackageDependencyDto was not found on the mapping source type NuGet.Packaging.Core.PackageDependency

Check warning on line 14 in Backend/PubNet.API.DTO/Packages/Nuget/Spec/NugetPackageDependencyDto.cs

View workflow job for this annotation

GitHub Actions / Build & Test using 8.x on windows-latest

The member Registration on the mapping target type PubNet.API.DTO.Packages.Nuget.Spec.NugetPackageDependencyDto was not found on the mapping source type NuGet.Packaging.Core.PackageDependency

Check warning on line 14 in Backend/PubNet.API.DTO/Packages/Nuget/Spec/NugetPackageDependencyDto.cs

View workflow job for this annotation

GitHub Actions / Build & Test using 8.x on windows-latest

The member Include on the mapping source type NuGet.Packaging.Core.PackageDependency is not mapped to any member on the mapping target type PubNet.API.DTO.Packages.Nuget.Spec.NugetPackageDependencyDto

Check warning on line 14 in Backend/PubNet.API.DTO/Packages/Nuget/Spec/NugetPackageDependencyDto.cs

View workflow job for this annotation

GitHub Actions / Build & Test using 8.x on windows-latest

The member Exclude on the mapping source type NuGet.Packaging.Core.PackageDependency is not mapped to any member on the mapping target type PubNet.API.DTO.Packages.Nuget.Spec.NugetPackageDependencyDto

/// <summary>
/// The ID of the package dependency.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
using NuGet.Packaging;
using Riok.Mapperly.Abstractions;

namespace PubNet.API.DTO.Packages.Nuget.Spec;

/// <summary>
Expand All @@ -11,8 +14,11 @@ namespace PubNet.API.DTO.Packages.Nuget.Spec;
/// package.
/// </para>
/// </summary>
public class NugetPackageDependencyGroupDto
[Mapper]
public partial class NugetPackageDependencyGroupDto
{
public static partial NugetPackageDependencyGroupDto MapFrom(PackageDependencyGroup group);

/// <summary>
/// The target framework that these dependencies are applicable to.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ namespace PubNet.API.DTO.Packages.Nuget.Spec;
/// <seealso cref="NugetPackageRegistrationPageDto"/>
public class NugetPackageRegistrationIndexDto
{
public static NugetPackageRegistrationIndexDto FromNugetPackage(NugetPackage package)
public static NugetPackageRegistrationIndexDto MapFrom(NugetPackage package)
{
var items = package.Versions.Select(v => new NugetPackageRegistrationLeafDto
{
Id = "",
CatalogEntry = new NugetCatalogEntryDto
{
Id = "null",
Id = "",
PackageId = v.Package.Name,
Version = v.Version,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ public async Task<NugetPackageVersion> CreateAsync(Author author, byte[] nupkg,
Versions = [],
};

var version = ReadPackageVersion(package, nupkg);
var version = await ReadPackageVersion(package, nupkg, cancellationToken);

package.Name = version.NuspecId ?? throw new InvalidOperationException("Package ID is missing");
package.Name = version.NuspecId!;
package.Versions.Add(version);
package.LatestVersion = version;
package.LatestVersionId = version.Id;
Expand All @@ -43,10 +43,7 @@ public async Task<NugetPackageVersion> CreateAsync(Author author, byte[] nupkg,
public async Task<NugetPackageVersion> AddVersionAsync(NugetPackage package, byte[] nupkg,
CancellationToken cancellationToken = default)
{
var version = ReadPackageVersion(package, nupkg);

_ = await archiveStorage.StoreArchiveAsync(package.Author.UserName, package.Name, version.Version, nupkg,
cancellationToken);
var version = await ReadPackageVersion(package, nupkg, cancellationToken);

await context.NugetPackageVersions.AddAsync(version, cancellationToken);

Expand All @@ -61,14 +58,16 @@ public async Task<NugetPackageVersion> AddVersionAsync(NugetPackage package, byt
return version;
}

private static NugetPackageVersion ReadPackageVersion(NugetPackage package, byte[] nupkg)
private async Task<NugetPackageVersion> ReadPackageVersion(NugetPackage package, byte[] nupkg,
CancellationToken cancellationToken)
{
using var packageStream = new MemoryStream(nupkg);

using var reader = new PackageArchiveReader(packageStream);
var nuspec = reader.NuspecReader;

var id = nuspec.GetId().ToNullIfEmpty();
var id = nuspec.GetId().ToNullIfEmpty() ??
throw new InvalidOperationException("Package ID is missing or empty");
var version = nuspec.GetVersion();
var title = nuspec.GetTitle().ToNullIfEmpty();
var description = nuspec.GetDescription().ToNullIfEmpty();
Expand Down Expand Up @@ -102,6 +101,9 @@ private static NugetPackageVersion ReadPackageVersion(NugetPackage package, byte
DependencyGroups = dependencyGroups.ToArray(),
};

_ = await archiveStorage.StoreArchiveAsync(package.Author.UserName, id, version.ToString(), nupkg,
cancellationToken);

return versionEntity;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.EntityFrameworkCore;
using System.Diagnostics.CodeAnalysis;
using Microsoft.EntityFrameworkCore;
using PubNet.API.Abstractions.CQRS.Queries.Packages;
using PubNet.API.DTO.Packages.Nuget;
using PubNet.Database.Context;
Expand All @@ -8,12 +9,21 @@ namespace PubNet.API.Services.CQRS.Queries.Packages;

public class NugetPackageDao(PubNetContext context) : INugetPackageDao
{
public Task<NugetPackage?> TryGetByPackageIdAsync(string packageId, CancellationToken cancellationToken = default)
[SuppressMessage("Performance",
"CA1862:Use the \'StringComparison\' method overloads to perform case-insensitive string comparisons",
Justification = "Doesn't work with EF Core")]
public async Task<NugetPackage?> TryGetByPackageIdAsync(string packageId,
CancellationToken cancellationToken = default)
{
return Task.FromResult(context.NugetPackages.SingleOrDefault(p => p.Name == packageId));
var normalizedPackageId = packageId.ToLowerInvariant();

return await context.NugetPackages
.SingleOrDefaultAsync(p => p.Name.ToLower() == normalizedPackageId,
cancellationToken);
}

public async Task<NugetPackageListDto> SearchAsync(string? q = null, int? skip = null, int? take = null, CancellationToken cancellationToken = default)
public async Task<NugetPackageListDto> SearchAsync(string? q = null, int? skip = null, int? take = null,
CancellationToken cancellationToken = default)
{
var query = context.NugetPackages.AsQueryable();

Expand All @@ -30,7 +40,7 @@ public async Task<NugetPackageListDto> SearchAsync(string? q = null, int? skip =

var packages = await query.ToListAsync(cancellationToken);

return new()
return new NugetPackageListDto
{
TotalHits = total,
Packages = packages.Select(p => NugetPackageDto.MapFrom(p)),
Expand Down
24 changes: 12 additions & 12 deletions Backend/PubNet.API/Controllers/Authors/AuthorsByNameController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public async Task<DartPackageListDto> GetAuthorDartPackagesAsync(string username
{
var author = await authorDao.TryFindByUsernameAsync(username, cancellationToken);
if (author is null)
return new()
return new DartPackageListDto
{
TotalHits = 0,
Packages = Array.Empty<DartPackageDto>(),
Expand All @@ -62,7 +62,7 @@ public async Task<DartPackageListDto> GetAuthorDartPackagesAsync(string username
var searchResults = packages.ToList();
var packageDtos = searchResults.Select(p => DartPackageDto.MapFrom(p, archiveProvider.GetArchiveUriAndHash));

return new()
return new DartPackageListDto
{
TotalHits = filteredCount,
Packages = packageDtos,
Expand All @@ -76,7 +76,7 @@ public async Task<NugetPackageListDto> GetAuthorNugetPackagesAsync(string userna
{
var author = await authorDao.TryFindByUsernameAsync(username, cancellationToken);
if (author is null)
return new()
return new NugetPackageListDto
{
TotalHits = 0,
Packages = Array.Empty<NugetPackageDto>(),
Expand All @@ -87,18 +87,18 @@ public async Task<NugetPackageListDto> GetAuthorNugetPackagesAsync(string userna
if (q is not null)
packages = packages.Where(p => p.Name.Contains(q, StringComparison.OrdinalIgnoreCase));

var filteredCount = await packages.CountAsync(cancellationToken);
var filteredCount = packages.Count();

if (skip is not null)
packages = packages.Skip(skip.Value);

if (take is not null)
packages = packages.Take(take.Value);

var searchResults = await packages.ToListAsync(cancellationToken);
var searchResults = packages.ToList();
var packageDtos = searchResults.Select(p => NugetPackageDto.MapFrom(p));

return new()
return new NugetPackageListDto
{
TotalHits = filteredCount,
Packages = packageDtos,
Expand All @@ -112,14 +112,14 @@ public async Task<PackageListCollectionDto> GetAuthorPackagesAsync(string userna
{
var author = await authorDao.TryFindByUsernameAsync(username, cancellationToken);
if (author is null)
return new()
return new PackageListCollectionDto
{
Dart = new()
Dart = new DartPackageListDto
{
TotalHits = 0,
Packages = Array.Empty<DartPackageDto>(),
},
Nuget = new()
Nuget = new NugetPackageListDto
{
TotalHits = 0,
Packages = Array.Empty<NugetPackageDto>(),
Expand All @@ -132,14 +132,14 @@ public async Task<PackageListCollectionDto> GetAuthorPackagesAsync(string userna
var nugetPackageDtos =
author.NugetPackages.Select(p => NugetPackageDto.MapFrom(p));

return new()
return new PackageListCollectionDto
{
Dart = new()
Dart = new DartPackageListDto
{
TotalHits = author.DartPackages.Count,
Packages = dartPackageDtos,
},
Nuget = new()
Nuget = new NugetPackageListDto
{
TotalHits = author.NugetPackages.Count,
Packages = nugetPackageDtos,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Microsoft.AspNetCore.Mvc;
using PubNet.API.Abstractions.CQRS.Queries.Packages;
using PubNet.API.DTO.Errors;
using PubNet.API.DTO.Packages.Nuget.Spec;

namespace PubNet.API.Controllers.Packages.Nuget;
Expand All @@ -11,15 +12,19 @@ public class NugetPackageRegistrationsByIdController(INugetPackageDao nugetPacka
/// <summary>
/// Used by dotnet to gather information about a specific package.
/// </summary>
/// <param name="id"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
/// <param name="id">The package ID</param>
/// <param name="cancellationToken">A token to cancel the asynchronous operation.</param>
/// <returns>A <see cref="NugetPackageRegistrationIndexDto"/> that contains the information needed to upload the package.</returns>
[HttpGet("index.json")]
public async Task<NugetPackageRegistrationIndexDto?> GetPackageRegistrationsIndexAsync(string id, CancellationToken cancellationToken = default)
[ProducesResponseType<NugetPackageRegistrationIndexDto>(StatusCodes.Status200OK)]
[ProducesResponseType<NotFoundErrorDto>(StatusCodes.Status404NotFound)]
public async Task<IActionResult> GetPackageRegistrationsIndexAsync(string id,
CancellationToken cancellationToken = default)
{
var package = await nugetPackageDao.TryGetByPackageIdAsync(id, cancellationToken);

return package is null ? null : NugetPackageRegistrationIndexDto.FromNugetPackage(package);
return package is null
? NotFoundDto("package-not-found", "Package not found")
: Ok(NugetPackageRegistrationIndexDto.MapFrom(package));
}
}
Loading

0 comments on commit eef20c2

Please sign in to comment.