Skip to content

Commit

Permalink
feat: Update target framework from net6.0 to net8.0
Browse files Browse the repository at this point in the history
  • Loading branch information
VMelnalksnis committed Dec 2, 2024
1 parent 7f32649 commit fd670b7
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 51 deletions.
8 changes: 6 additions & 2 deletions Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
<Project>

<PropertyGroup>
<TargetFrameworks>netstandard2.0;net6.0</TargetFrameworks>
<TargetFrameworks>netstandard2.0;net8.0</TargetFrameworks>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<DebugType>portable</DebugType>
<EnableTrimAnalyzer>true</EnableTrimAnalyzer>

<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
Expand All @@ -22,6 +21,11 @@
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
</PropertyGroup>

<PropertyGroup Condition="'$(TargetFramework)' != 'netstandard2.0'">
<IsAotCompatible>true</IsAotCompatible>
<EnableConfigurationBindingGenerator>true</EnableConfigurationBindingGenerator>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="DotNet.ReproducibleBuilds">
<PrivateAssets>all</PrivateAssets>
Expand Down
20 changes: 10 additions & 10 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@
<PackageVersion Include="IsExternalInit" Version="1.0.3"/>
<PackageVersion Include="Jetbrains.Annotations" Version="2024.3.0"/>
<PackageVersion Include="JunitXml.TestLogger" Version="4.1.0"/>
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="8.0.0"/>
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="8.0.0"/>
<PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="8.0.0"/>
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.2"/>
<PackageVersion Include="Microsoft.Extensions.Http" Version="8.0.1"/>
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="8.0.1"/>
<PackageVersion Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="8.0.0"/>
<PackageVersion Include="Microsoft.Extensions.Options.DataAnnotations" Version="8.0.0"/>
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="9.0.0"/>
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="9.0.0"/>
<PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="9.0.0"/>
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.0"/>
<PackageVersion Include="Microsoft.Extensions.Http" Version="9.0.0"/>
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="9.0.0"/>
<PackageVersion Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="9.0.0"/>
<PackageVersion Include="Microsoft.Extensions.Options.DataAnnotations" Version="9.0.0"/>
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.12.0"/>
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3"/>
<PackageVersion Include="NodaTime" Version="3.2.0"/>
Expand All @@ -29,8 +29,8 @@
<PackageVersion Include="System.ComponentModel.Annotations" Version="5.0.0"/>
<PackageVersion Include="System.Linq.Async" Version="6.0.1"/>
<PackageVersion Include="System.Net.Http" Version="4.3.4"/>
<PackageVersion Include="System.Net.Http.Json" Version="8.0.1"/>
<PackageVersion Include="System.Text.Json" Version="8.0.5"/>
<PackageVersion Include="System.Net.Http.Json" Version="9.0.0"/>
<PackageVersion Include="System.Text.Json" Version="9.0.0"/>
<PackageVersion Include="System.Text.RegularExpressions" Version="4.3.1"/>
<PackageVersion Include="StyleCop.Analyzers" Version="1.2.0-beta.556"/>
<PackageVersion Include="Testcontainers.Redis" Version="3.4.0"/>
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ For use outside of ASP.NET Core, see the
2. Register required services (see [tests](tests/VMelnalksnis.PaperlessDotNet.DependencyInjection.Tests/ServiceCollectionExtensionsTests.cs))
```csharp
serviceCollection
.AddSingleton<IClock>(SystemClock.Instance)
.AddSingleton(DateTimeZoneProviders.Tzdb)
.AddPaperlessDotNet(Configuration);
.AddPaperlessDotNet();
```

3. Use `IPaperlessClient` to access all endpoints, or one of the specific clients defined in `IPaperlessClient`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,6 @@
using VMelnalksnis.PaperlessDotNet.Tags;
using VMelnalksnis.PaperlessDotNet.Tasks;

#if NET6_0_OR_GREATER
using System.Net.Mime;
#endif

namespace VMelnalksnis.PaperlessDotNet.DependencyInjection;

/// <summary>Methods for configuring <see cref="IPaperlessClient"/> within <see cref="IServiceCollection"/>.</summary>
Expand All @@ -40,13 +36,34 @@ static ServiceCollectionExtensions()

/// <summary>Adds all required services for <see cref="IPaperlessClient"/>, excluding external dependencies.</summary>
/// <param name="serviceCollection">The service collection in which to register the services.</param>
/// <param name="configuration">The configuration to which to bind options models.</param>
/// <param name="config">A delegate that is used to configure <see cref="PaperlessJsonSerializerOptions"/>.</param>
/// <returns>The <see cref="IHttpClientBuilder"/> for the <see cref="HttpClient"/> used by <see cref="IPaperlessClient"/>.</returns>
#if NET6_0_OR_GREATER
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026", Justification = $"{nameof(PaperlessOptions)} contains only system types.")]
#if NETSTANDARD2_0
[SuppressMessage("Trimming", "IL2026", Justification = $"{nameof(PaperlessOptions)} contains only system types.")]
#else
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026", Justification = $"{nameof(PaperlessOptions)} contains only system types.")]
#endif
public static IHttpClientBuilder AddPaperlessDotNet(
this IServiceCollection serviceCollection,
Action<PaperlessJsonSerializerOptions>? config = null)
{
serviceCollection
.AddOptions<PaperlessOptions>()
.BindConfiguration(PaperlessOptions.Name)
.ValidateDataAnnotations();

Check warning on line 53 in source/VMelnalksnis.PaperlessDotNet.DependencyInjection/ServiceCollectionExtensions.cs

View check run for this annotation

Codecov / codecov/patch

source/VMelnalksnis.PaperlessDotNet.DependencyInjection/ServiceCollectionExtensions.cs#L50-L53

Added lines #L50 - L53 were not covered by tests

return serviceCollection.AddClient(config);

Check warning on line 55 in source/VMelnalksnis.PaperlessDotNet.DependencyInjection/ServiceCollectionExtensions.cs

View check run for this annotation

Codecov / codecov/patch

source/VMelnalksnis.PaperlessDotNet.DependencyInjection/ServiceCollectionExtensions.cs#L55

Added line #L55 was not covered by tests
}

/// <summary>Adds all required services for <see cref="IPaperlessClient"/>, excluding external dependencies.</summary>
/// <param name="serviceCollection">The service collection in which to register the services.</param>
/// <param name="configuration">The configuration to which to bind options models.</param>
/// <param name="config">A delegate that is used to configure <see cref="PaperlessJsonSerializerOptions"/>.</param>
/// <returns>The <see cref="IHttpClientBuilder"/> for the <see cref="HttpClient"/> used by <see cref="IPaperlessClient"/>.</returns>
#if NETSTANDARD2_0
[SuppressMessage("Trimming", "IL2026", Justification = $"{nameof(PaperlessOptions)} contains only system types.")]
#else
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026", Justification = $"{nameof(PaperlessOptions)} contains only system types.")]
#endif
public static IHttpClientBuilder AddPaperlessDotNet(
this IServiceCollection serviceCollection,
Expand All @@ -58,6 +75,13 @@ public static IHttpClientBuilder AddPaperlessDotNet(
.Bind(configuration.GetSection(PaperlessOptions.Name))
.ValidateDataAnnotations();

return serviceCollection.AddClient(config);
}

private static IHttpClientBuilder AddClient(
this IServiceCollection serviceCollection,
Action<PaperlessJsonSerializerOptions>? config)
{
return serviceCollection
.AddSingleton<PaperlessJsonSerializerOptions>(provider =>
{
Expand Down Expand Up @@ -98,11 +122,7 @@ public static IHttpClientBuilder AddPaperlessDotNet(

client.BaseAddress = options.BaseAddress;
client.DefaultRequestHeaders.UserAgent.Add(_userAgent);
#if NET6_0_OR_GREATER
client.DefaultRequestHeaders.Add("Accept", $"{MediaTypeNames.Application.Json}; version=2");
#else
client.DefaultRequestHeaders.Add("Accept", "application/json; version=2");
#endif
client.DefaultRequestHeaders.Authorization = new("Token", options.Token);
});
}
Expand Down
18 changes: 9 additions & 9 deletions source/VMelnalksnis.PaperlessDotNet/Documents/DocumentClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -122,31 +122,31 @@ public async Task<DocumentMetadata> GetMetadata(int id, CancellationToken cancel
/// <inheritdoc />
public async Task<DocumentContent> Download(int id, CancellationToken cancellationToken = default)
{
return await DownloadContentCore(Routes.Documents.DownloadUri(id), cancellationToken);
return await DownloadContentCore(Routes.Documents.DownloadUri(id), cancellationToken).ConfigureAwait(false);
}

/// <inheritdoc />
public async Task<DocumentContent> DownloadOriginal(int id, CancellationToken cancellationToken = default)
{
return await DownloadContentCore(Routes.Documents.DownloadOriginalUri(id), cancellationToken);
return await DownloadContentCore(Routes.Documents.DownloadOriginalUri(id), cancellationToken).ConfigureAwait(false);
}

/// <inheritdoc />
public async Task<DocumentContent> DownloadPreview(int id, CancellationToken cancellationToken = default)
{
return await DownloadContentCore(Routes.Documents.DownloadPreview(id), cancellationToken);
return await DownloadContentCore(Routes.Documents.DownloadPreview(id), cancellationToken).ConfigureAwait(false);
}

/// <inheritdoc />
public async Task<DocumentContent> DownloadOriginalPreview(int id, CancellationToken cancellationToken = default)
{
return await DownloadContentCore(Routes.Documents.DownloadOriginalPreview(id), cancellationToken);
return await DownloadContentCore(Routes.Documents.DownloadOriginalPreview(id), cancellationToken).ConfigureAwait(false);

Check warning on line 143 in source/VMelnalksnis.PaperlessDotNet/Documents/DocumentClient.cs

View check run for this annotation

Codecov / codecov/patch

source/VMelnalksnis.PaperlessDotNet/Documents/DocumentClient.cs#L143

Added line #L143 was not covered by tests
}

/// <inheritdoc />
public async Task<DocumentContent> DownloadThumbnail(int id, CancellationToken cancellationToken = default)
{
return await DownloadContentCore(Routes.Documents.DownloadThumbnail(id), cancellationToken);
return await DownloadContentCore(Routes.Documents.DownloadThumbnail(id), cancellationToken).ConfigureAwait(false);
}

/// <inheritdoc />
Expand Down Expand Up @@ -180,7 +180,7 @@ public async Task<DocumentCreationResult> Create(DocumentCreation document)
content.Add(new StringContent(storagePath.ToString()), "storage_path");
}

foreach (var tag in document.TagIds ?? Array.Empty<int>())
foreach (var tag in document.TagIds ?? [])
{
content.Add(new StringContent(tag.ToString()), "tags");
}
Expand Down Expand Up @@ -317,10 +317,10 @@ private async Task<DocumentContent> DownloadContentCore(Uri requestUri, Cancella
var headers = response.Content.Headers;

return new(
#if NET6_0_OR_GREATER
await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false),
#else
#if NETSTANDARD2_0
await response.Content.ReadAsStreamAsync().ConfigureAwait(false),
#else
await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false),
#endif
headers.ContentDisposition,
headers.ContentType!);
Expand Down
12 changes: 6 additions & 6 deletions source/VMelnalksnis.PaperlessDotNet/PaperlessOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ public sealed class PaperlessOptions
/// <summary>The name of the configuration section.</summary>
public const string Name = "Paperless";

/// <summary>Gets the base address of the Paperless API.</summary>
/// <summary>Gets or sets the base address of the Paperless API.</summary>
[Required]
public Uri BaseAddress { get; init; } = null!;
public Uri BaseAddress { get; set; } = null!;

/// <summary>Gets the authentication token to use with all requests.</summary>
/// <summary>Gets or sets the authentication token to use with all requests.</summary>
[Required]
public string Token { get; init; } = null!;
public string Token { get; set; } = null!;

/// <summary> Gets the time delay between each polling of tasks in milliseconds.</summary>
/// <summary> Gets or sets the time delay between each polling of tasks in milliseconds.</summary>
[Required]
public TimeSpan TaskPollingDelay { get; init; } = TimeSpan.FromMilliseconds(100);
public TimeSpan TaskPollingDelay { get; set; } = TimeSpan.FromMilliseconds(100);
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,42 @@ namespace VMelnalksnis.PaperlessDotNet.DependencyInjection.Tests;

public sealed class ServiceCollectionExtensionsTests
{
private readonly IConfiguration _configuration = new ConfigurationBuilder()
.AddInMemoryCollection(new List<KeyValuePair<string, string?>>
{
new($"{PaperlessOptions.Name}:{nameof(PaperlessOptions.BaseAddress)}", "https://localhost:5002/"),
new($"{PaperlessOptions.Name}:{nameof(PaperlessOptions.Token)}", Guid.NewGuid().ToString("N")),
})
.Build();

[Fact]
public void AddPaperlessDotNet_ShouldRegisterRequiredServices()
public void AddPaperlessDotNet_ExplicitConfiguration_ShouldRegisterRequiredServices()
{
var configuration = new ConfigurationBuilder()
.AddInMemoryCollection(new List<KeyValuePair<string, string?>>
{
new($"{PaperlessOptions.Name}:{nameof(PaperlessOptions.BaseAddress)}", "https://localhost:5002/"),
new($"{PaperlessOptions.Name}:{nameof(PaperlessOptions.Token)}", Guid.NewGuid().ToString("N")),
})
.Build();
var serviceCollection = new ServiceCollection();

serviceCollection
.AddSingleton<IClock>(SystemClock.Instance)
.AddSingleton(DateTimeZoneProviders.Tzdb)
.AddPaperlessDotNet(_configuration);

using var serviceProvider = serviceCollection.BuildServiceProvider();
var paperlessClient = serviceProvider.GetRequiredService<IPaperlessClient>();

paperlessClient.Should().NotBeNull();
}

[Fact]
public void AddPaperlessDotNet_ShouldRegisterRequiredServices()
{
var serviceCollection = new ServiceCollection();

serviceCollection
.AddSingleton(_configuration)
.AddSingleton<IClock>(SystemClock.Instance)
.AddSingleton(DateTimeZoneProviders.Tzdb)
.AddPaperlessDotNet(configuration);
.AddPaperlessDotNet();

var serviceProvider = serviceCollection.BuildServiceProvider();
using var serviceProvider = serviceCollection.BuildServiceProvider();
var paperlessClient = serviceProvider.GetRequiredService<IPaperlessClient>();

paperlessClient.Should().NotBeNull();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
// Licensed under the Apache License 2.0.
// See LICENSE file in the project root for full license information.

// Fails due to float inaccuracy in .NET 3.1/5
#if !(NETCOREAPP3_1 || NET5_0)
// Fails due to float inaccuracy in all target frameworks that use the .NET Standard version
#if NET8_0_OR_GREATER
using System.Text.Json;
using System.Text.Json.Serialization.Metadata;

Expand Down

0 comments on commit fd670b7

Please sign in to comment.