From c624e760b0d5524017da8a040d2fba7b5d0b808c Mon Sep 17 00:00:00 2001 From: ancplua Date: Tue, 12 May 2026 15:06:30 +0200 Subject: [PATCH 1/2] feat(sdk): adopt ANcpLua.NET.Sdk 3.4.27 across .NET projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Wire each .NET project to the appropriate ANcpLua.NET.Sdk flavor (3.4.27) through global.json's msbuild-sdks block, mirroring qyl's setup: - Paperless.Contracts → ANcpLua.NET.Sdk (library) - PaperlessREST, PaperlessUI.Blazor → ANcpLua.NET.Sdk.Web - PaperlessServices → ANcpLua.NET.Sdk (worker; UseMicrosoftTestingPlatform=false, explicit OutputType=Exe + M.E.X usings replace Microsoft.NET.Sdk.Worker's implicit defaults) - PaperlessREST.Tests → ANcpLua.NET.Sdk.Web + IsTestProject=true (WebApplicationFactory needs Web SDK; IsTestProject opts in Tests.targets) - PaperlessServices.Tests → ANcpLua.NET.Sdk.Test - Pipeline/Build.csproj stays on Microsoft.NET.Sdk by design (NUKE bootstrap self-contained, opts out of root CPVM) What the SDK brings (Common.props): AnalysisLevel=latest-all, EnforceCodeStyleInBuild, Features=strict, Deterministic, embedded source link, CentralPackageTransitivePinningEnabled, NuGetAudit=all+low, TreatWarningsAsErrors in CI/Release, and 9 auto-injected editorconfigs (Global, CodingStyle, Compiler, GeneratedFiles, NamingConvention, per-analyzer for NetAnalyzers/BannedApiAnalyzers/xunit/AwesomeAssertions/ANcpLua). Test projects also auto-receive AwesomeAssertions + xunit.v3.mtp-v2. JS frontends opt into the Debug solution config via in Paperless.slnx and bump Microsoft.VisualStudio.JavaScript.Sdk to 1.0.5483906 (latest on nuget.org); false keeps dotnet build inert for them so pnpm-lock.yaml is preserved (CI builds them via their own pnpm jobs per CLAUDE.md). Security: pin NuGet.Packaging 7.3.1 and System.Security.Cryptography.Xml 10.0.7 directly on Pipeline/Build.csproj (closes GHSA-g4vj-cjjj-v7hg, GHSA-37gx-xxp4-5rgx, GHSA-w3x6-4m5h-cxqf transitive through Nuke.Common); the same pins live in Directory.Packages.props so Paperless projects under CPVM get them via transitive pinning. Genuine bugs surfaced by latest-all are fixed in-tree: - xUnit1051: cancellation tokens threaded through Task.Delay calls in DocumentRepositoryIntegrationTests + ErrorOr<>.UploadDocumentAsync calls in DocumentServiceErrorMappingTests - CS1573: Document.CreateFromUpload XML doc gains - IDE0052 + IDE1006: unused TypedResults.NotFound()/NoContent() statics in TypedErrorOrAsyncExtensions inlined at use sites - IDE1006: ReportProcessor.Serializer renamed to s_serializer; SInitLock / SInitializedIndices renamed to s_initLock / s_initializedIndices in SearchIndexService - IDE0370: unneeded null-forgiving operators dropped on DocumentService TryMapStorageException return and ServiceCollectionExtensions.AddPostgres connection string Style/migration warnings (AL0025/AL0026/AL0039/RS0030 BannedSymbols, CA2000, CA1034, etc. — 371 sites mostly in test code) are surfaced as warnings but carved out of TreatWarningsAsErrors at Directory.Build.props via WarningsNotAsErrors, scheduled for follow-up cleanup PRs per qyl's pattern. Co-Authored-By: Claude Opus 4.7 (1M context) --- .nuke/build.schema.json | 3 ++- Directory.Build.props | 18 +++++++++---- Directory.Packages.props | 14 +++++++--- .../Paperless.Contracts.csproj | 6 +---- Paperless.slnx | 8 ++++-- .../DocumentRepositoryIntegrationTests.cs | 10 +++---- .../PaperlessREST.Tests.csproj | 26 +++++++------------ .../Unit/DocumentServiceErrorMappingTests.cs | 6 ++--- .../Application/ReportProcessor.cs | 4 +-- .../Application/Document.cs | 1 + .../Application/DocumentService.cs | 2 +- .../Extensions/ServiceCollectionExtensions.cs | 2 +- .../Extensions/TypedErrorOrAsyncExtensions.cs | 9 +++---- PaperlessREST/PaperlessREST.csproj | 13 ++-------- .../PaperlessServices.Tests.csproj | 19 ++++---------- .../Search/SearchIndexService.cs | 16 ++++++------ PaperlessServices/PaperlessServices.csproj | 18 ++++++++----- .../PaperlessUI.Angular.esproj | 4 ++- PaperlessUI.Blazor/PaperlessUI.Blazor.csproj | 6 ++--- PaperlessUI.React/PaperlessUI.React.esproj | 4 ++- Pipeline/Build.csproj | 5 ++++ global.json | 5 ++++ 22 files changed, 103 insertions(+), 96 deletions(-) diff --git a/.nuke/build.schema.json b/.nuke/build.schema.json index 9adfa48..1e9786b 100644 --- a/.nuke/build.schema.json +++ b/.nuke/build.schema.json @@ -46,7 +46,8 @@ "Restore", "SetupTestcontainers", "Test", - "UnitTests" + "UnitTests", + "Verify" ] }, "Verbosity": { diff --git a/Directory.Build.props b/Directory.Build.props index ae80255..8702b6e 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,9 +1,17 @@ - - - - true - + + + + $(WarningsNotAsErrors); + AL0025;AL0026;AL0039;AL0070;AL0081;AL0101;AL0114;AL0137; + RS0030; + CA1002;CA1032;CA1034;CA1052;CA1056;CA1307;CA1725;CA1819;CA1822;CA1823;CA1852;CA1859; + CA2000;CA2012;CA2201;CA5394; + IDE0370;IDE1006 + + diff --git a/Directory.Packages.props b/Directory.Packages.props index 025dfae..783c3bd 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -4,6 +4,9 @@ true + + true @@ -36,9 +39,7 @@ - - - + @@ -73,6 +74,13 @@ + + + + diff --git a/Paperless.Contracts/Paperless.Contracts.csproj b/Paperless.Contracts/Paperless.Contracts.csproj index d7dbfaa..e18270b 100644 --- a/Paperless.Contracts/Paperless.Contracts.csproj +++ b/Paperless.Contracts/Paperless.Contracts.csproj @@ -1,10 +1,6 @@ - + - net10.0 - preview - enable - enable Paperless.Contracts diff --git a/Paperless.slnx b/Paperless.slnx index 22e5342..88e2c15 100644 --- a/Paperless.slnx +++ b/Paperless.slnx @@ -5,7 +5,11 @@ - - + + + + + + diff --git a/PaperlessREST.Tests/Integration/DocumentRepositoryIntegrationTests.cs b/PaperlessREST.Tests/Integration/DocumentRepositoryIntegrationTests.cs index ce4e7d1..7698d0a 100644 --- a/PaperlessREST.Tests/Integration/DocumentRepositoryIntegrationTests.cs +++ b/PaperlessREST.Tests/Integration/DocumentRepositoryIntegrationTests.cs @@ -312,11 +312,11 @@ public async Task GetDocumentsPagedAsync_ReturnsNewestFirst() // Add documents with slight delays to ensure distinct GUIDv7s Document oldest = new DocumentBuilder().WithFileName($"{testPrefix}-old.pdf").Build(); await _repository.AddAsync(oldest, TestContext.Current.CancellationToken); - await Task.Delay(10); + await Task.Delay(10, TestContext.Current.CancellationToken); Document middle = new DocumentBuilder().WithFileName($"{testPrefix}-mid.pdf").Build(); await _repository.AddAsync(middle, TestContext.Current.CancellationToken); - await Task.Delay(10); + await Task.Delay(10, TestContext.Current.CancellationToken); Document newest = new DocumentBuilder().WithFileName($"{testPrefix}-new.pdf").Build(); await _repository.AddAsync(newest, TestContext.Current.CancellationToken); @@ -345,7 +345,7 @@ public async Task GetDocumentsPagedAsync_RespectsPageSize() await _repository.AddAsync( new DocumentBuilder().WithFileName($"{testPrefix}-{i}.pdf").Build(), TestContext.Current.CancellationToken); - await Task.Delay(5); // Ensure distinct GUIDv7s + await Task.Delay(5, TestContext.Current.CancellationToken); // Ensure distinct GUIDv7s } // Act @@ -369,7 +369,7 @@ public async Task GetDocumentsPagedAsync_WithCursor_ReturnsNextPage() Document doc = new DocumentBuilder().WithFileName($"{testPrefix}-{i}.pdf").Build(); Document added = await _repository.AddAsync(doc, TestContext.Current.CancellationToken); addedDocs.Add(added); - await Task.Delay(5); + await Task.Delay(5, TestContext.Current.CancellationToken); } // Act - Get first page @@ -400,7 +400,7 @@ public async Task GetDocumentsPagedAsync_LastPage_HasMoreIsFalse() await _repository.AddAsync( new DocumentBuilder().WithFileName($"{testPrefix}-{i}.pdf").Build(), TestContext.Current.CancellationToken); - await Task.Delay(5); + await Task.Delay(5, TestContext.Current.CancellationToken); } // Act - Request more than available diff --git a/PaperlessREST.Tests/PaperlessREST.Tests.csproj b/PaperlessREST.Tests/PaperlessREST.Tests.csproj index fe6afbc..4602ec5 100644 --- a/PaperlessREST.Tests/PaperlessREST.Tests.csproj +++ b/PaperlessREST.Tests/PaperlessREST.Tests.csproj @@ -1,30 +1,22 @@ - + - net10.0 - preview - enable - enable - Exe - false + true + + true PaperlessREST.Tests true - true - - true - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/PaperlessREST.Tests/Unit/DocumentServiceErrorMappingTests.cs b/PaperlessREST.Tests/Unit/DocumentServiceErrorMappingTests.cs index 9cf3226..9a9993c 100644 --- a/PaperlessREST.Tests/Unit/DocumentServiceErrorMappingTests.cs +++ b/PaperlessREST.Tests/Unit/DocumentServiceErrorMappingTests.cs @@ -37,7 +37,7 @@ public async Task UploadDocumentAsync_StorageTimeout_ReturnsStorageTimeoutError( DocumentService sut = CreateSut(); // Act - ErrorOr result = await sut.UploadDocumentAsync(request); + ErrorOr result = await sut.UploadDocumentAsync(request, TestContext.Current.CancellationToken); // Assert result.IsError.Should().BeTrue(); @@ -57,7 +57,7 @@ public async Task UploadDocumentAsync_Storage500_ReturnsStorageServerError() DocumentService sut = CreateSut(); // Act - ErrorOr result = await sut.UploadDocumentAsync(request); + ErrorOr result = await sut.UploadDocumentAsync(request, TestContext.Current.CancellationToken); // Assert result.IsError.Should().BeTrue(); @@ -80,7 +80,7 @@ public async Task UploadDocumentAsync_StorageConnectionRefused_ReturnsStorageCon DocumentService sut = CreateSut(); // Act - ErrorOr result = await sut.UploadDocumentAsync(request); + ErrorOr result = await sut.UploadDocumentAsync(request, TestContext.Current.CancellationToken); // Assert result.IsError.Should().BeTrue(); diff --git a/PaperlessREST/Features/BatchProcessing/Application/ReportProcessor.cs b/PaperlessREST/Features/BatchProcessing/Application/ReportProcessor.cs index 6ce11ff..455989f 100644 --- a/PaperlessREST/Features/BatchProcessing/Application/ReportProcessor.cs +++ b/PaperlessREST/Features/BatchProcessing/Application/ReportProcessor.cs @@ -6,7 +6,7 @@ public sealed class ReportProcessor( ILogger logger) : IReportProcessor { private const string SchemaFileName = "accessReport.xsd"; - private static readonly XmlSerializer Serializer = new(typeof(AccessReportDto)); + private static readonly XmlSerializer s_serializer = new(typeof(AccessReportDto)); private XmlSchemaSet Schemas => field ??= LoadSchemas(); @@ -89,7 +89,7 @@ private XmlSchemaSet LoadSchemas() }; using XmlReader reader = XmlReader.Create(stream, settings); - AccessReportDto dto = (AccessReportDto)Serializer.Deserialize(reader)!; + AccessReportDto dto = (AccessReportDto)s_serializer.Deserialize(reader)!; if (validationErrors.Count > 0) { diff --git a/PaperlessREST/Features/DocumentManagement/Application/Document.cs b/PaperlessREST/Features/DocumentManagement/Application/Document.cs index 0553cd7..d79e24b 100644 --- a/PaperlessREST/Features/DocumentManagement/Application/Document.cs +++ b/PaperlessREST/Features/DocumentManagement/Application/Document.cs @@ -77,6 +77,7 @@ public sealed class Document /// Creates a new instance from an uploaded file. /// /// The original filename of the uploaded PDF. + /// Provides the UTC timestamp recorded on ; inject for testability. /// A new in status. /// /// This factory method initializes a document with: diff --git a/PaperlessREST/Features/DocumentManagement/Application/DocumentService.cs b/PaperlessREST/Features/DocumentManagement/Application/DocumentService.cs index 3245c7a..ba50d6d 100644 --- a/PaperlessREST/Features/DocumentManagement/Application/DocumentService.cs +++ b/PaperlessREST/Features/DocumentManagement/Application/DocumentService.cs @@ -245,6 +245,6 @@ await Task.WhenAll( "Document.StorageConnectionFailed", $"Cannot connect to storage service for {storagePath}"), - _ => null! + _ => null }; } diff --git a/PaperlessREST/Host/Extensions/ServiceCollectionExtensions.cs b/PaperlessREST/Host/Extensions/ServiceCollectionExtensions.cs index a569f66..7f57ab0 100644 --- a/PaperlessREST/Host/Extensions/ServiceCollectionExtensions.cs +++ b/PaperlessREST/Host/Extensions/ServiceCollectionExtensions.cs @@ -220,7 +220,7 @@ private IServiceCollection AddInfrastructure(IConfiguration config) private IServiceCollection AddPostgres(IConfiguration config) { - NpgsqlDataSource dataSource = new NpgsqlDataSourceBuilder(config.GetConnectionString("PaperlessDb")!) + NpgsqlDataSource dataSource = new NpgsqlDataSourceBuilder(config.GetConnectionString("PaperlessDb")) .MapEnum("document_status") .Build(); diff --git a/PaperlessREST/Host/Extensions/TypedErrorOrAsyncExtensions.cs b/PaperlessREST/Host/Extensions/TypedErrorOrAsyncExtensions.cs index ea1bfd4..b3705ae 100644 --- a/PaperlessREST/Host/Extensions/TypedErrorOrAsyncExtensions.cs +++ b/PaperlessREST/Host/Extensions/TypedErrorOrAsyncExtensions.cs @@ -5,9 +5,6 @@ namespace PaperlessREST.Host.Extensions; /// public static class TypedErrorOrAsyncExtensions { - private static readonly NotFound NotFound = TypedResults.NotFound(); - private static readonly NoContent NoContent = TypedResults.NoContent(); - private static ValidationProblem CreateValidationProblem(IReadOnlyList errors) => TypedResults.ValidationProblem( errors.Where(e => e.Type == ErrorType.Validation) @@ -79,7 +76,7 @@ public async Task, NotFound>> ToOkOr404( } return result.FirstError.Type == ErrorType.NotFound - ? NotFound + ? TypedResults.NotFound() : throw ContractViolationException.ForNotFoundOnly(result.FirstError, result.Errors, callerName); } @@ -126,11 +123,11 @@ public async Task> ToNoContentOr404([CallerMemberNa if (!result.IsError) { - return NoContent; + return TypedResults.NoContent(); } return result.FirstError.Type == ErrorType.NotFound - ? NotFound + ? TypedResults.NotFound() : throw ContractViolationException.ForNotFoundOnly(result.FirstError, result.Errors, callerName); } } diff --git a/PaperlessREST/PaperlessREST.csproj b/PaperlessREST/PaperlessREST.csproj index 2c553e9..dcd9e21 100644 --- a/PaperlessREST/PaperlessREST.csproj +++ b/PaperlessREST/PaperlessREST.csproj @@ -1,17 +1,8 @@ - + - net10.0 - enable - enable - true - preview Linux - true - true - latest - true - $(NoWarn);1591 + false diff --git a/PaperlessServices.Tests/PaperlessServices.Tests.csproj b/PaperlessServices.Tests/PaperlessServices.Tests.csproj index 3062150..a395a45 100644 --- a/PaperlessServices.Tests/PaperlessServices.Tests.csproj +++ b/PaperlessServices.Tests/PaperlessServices.Tests.csproj @@ -1,23 +1,14 @@ - + - net10.0 - preview - enable - enable + + true Exe - false - true - - true - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/PaperlessServices/Features/OcrProcessing/Infrastructure/Search/SearchIndexService.cs b/PaperlessServices/Features/OcrProcessing/Infrastructure/Search/SearchIndexService.cs index 4d18e00..5f6fa04 100644 --- a/PaperlessServices/Features/OcrProcessing/Infrastructure/Search/SearchIndexService.cs +++ b/PaperlessServices/Features/OcrProcessing/Infrastructure/Search/SearchIndexService.cs @@ -17,8 +17,8 @@ public class SearchIndexService( ILogger logger) : ISearchIndexService { - private static readonly SemaphoreSlim SInitLock = new(1, 1); - private static readonly ConcurrentDictionary SInitializedIndices = new(); + private static readonly SemaphoreSlim s_initLock = new(1, 1); + private static readonly ConcurrentDictionary s_initializedIndices = new(); /// /// Indexes a document in Elasticsearch after OCR processing completes. @@ -77,16 +77,16 @@ private async Task InitializeAsync(CancellationToken cancellationToken = default string indexName = options.Value.DefaultIndex; // Fast path: index already initialized - if (SInitializedIndices.ContainsKey(indexName)) + if (s_initializedIndices.ContainsKey(indexName)) { return; } - await SInitLock.WaitAsync(cancellationToken); + await s_initLock.WaitAsync(cancellationToken); try { // Double-check after acquiring lock - if (SInitializedIndices.ContainsKey(indexName)) + if (s_initializedIndices.ContainsKey(indexName)) { return; } @@ -94,7 +94,7 @@ private async Task InitializeAsync(CancellationToken cancellationToken = default ExistsResponse existsResponse = await elastic.Indices.ExistsAsync(indexName, cancellationToken); if (existsResponse.Exists) { - SInitializedIndices.TryAdd(indexName, true); + s_initializedIndices.TryAdd(indexName, true); return; } @@ -113,11 +113,11 @@ private async Task InitializeAsync(CancellationToken cancellationToken = default logger.LogInformation("Created Elasticsearch index: {IndexName}", indexName); } - SInitializedIndices.TryAdd(indexName, true); + s_initializedIndices.TryAdd(indexName, true); } finally { - SInitLock.Release(); + s_initLock.Release(); } } } diff --git a/PaperlessServices/PaperlessServices.csproj b/PaperlessServices/PaperlessServices.csproj index 3a6ce16..145c700 100644 --- a/PaperlessServices/PaperlessServices.csproj +++ b/PaperlessServices/PaperlessServices.csproj @@ -1,17 +1,23 @@ - + - net10.0 - enable - enable + Exe paperless-services - true - preview + false + + + + + + + + diff --git a/PaperlessUI.Angular/PaperlessUI.Angular.esproj b/PaperlessUI.Angular/PaperlessUI.Angular.esproj index 83b6915..1c0e4a5 100644 --- a/PaperlessUI.Angular/PaperlessUI.Angular.esproj +++ b/PaperlessUI.Angular/PaperlessUI.Angular.esproj @@ -1,10 +1,12 @@ - + pnpm run start src\ Jasmine false + + false $(MSBuildProjectDirectory)\dist\paperless-ui-angular diff --git a/PaperlessUI.Blazor/PaperlessUI.Blazor.csproj b/PaperlessUI.Blazor/PaperlessUI.Blazor.csproj index b5f6af0..c349c29 100644 --- a/PaperlessUI.Blazor/PaperlessUI.Blazor.csproj +++ b/PaperlessUI.Blazor/PaperlessUI.Blazor.csproj @@ -1,10 +1,8 @@ - + - net10.0 - enable - enable true + false diff --git a/PaperlessUI.React/PaperlessUI.React.esproj b/PaperlessUI.React/PaperlessUI.React.esproj index 6e996bb..55cd96a 100644 --- a/PaperlessUI.React/PaperlessUI.React.esproj +++ b/PaperlessUI.React/PaperlessUI.React.esproj @@ -1,10 +1,12 @@ - + pnpm run dev src\ Vitest false + + false $(MSBuildProjectDirectory)\dist diff --git a/Pipeline/Build.csproj b/Pipeline/Build.csproj index 1662874..91e0794 100644 --- a/Pipeline/Build.csproj +++ b/Pipeline/Build.csproj @@ -27,6 +27,11 @@ + + + diff --git a/global.json b/global.json index 400edd5..8b810e1 100644 --- a/global.json +++ b/global.json @@ -3,6 +3,11 @@ "version": "10.0.203", "rollForward": "latestFeature" }, + "msbuild-sdks": { + "ANcpLua.NET.Sdk": "3.4.27", + "ANcpLua.NET.Sdk.Web": "3.4.27", + "ANcpLua.NET.Sdk.Test": "3.4.27" + }, "test": { "runner": "Microsoft.Testing.Platform" } From 98959afe8713e5e9f98ef29bc2c164e28feb89f8 Mon Sep 17 00:00:00 2001 From: ancplua Date: Tue, 12 May 2026 15:22:48 +0200 Subject: [PATCH 2/2] refactor(esproj): drop Microsoft.VisualStudio.JavaScript.Sdk shims MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace both PaperlessUI.{Angular,React}.esproj projects with the qyl hand-rolled MSBuild pattern (qyl/services/qyl.dashboard/qyl.dashboard.esproj), adapted for pnpm. No more ; custom Restore/Build/Test/Clean targets shell to pnpm only when RunFrontendOnBuild=true, defaulting to no-op so CI's dedicated frontend jobs remain the single source of truth. Removes the entire shim stack that existed only to neutralize the JS SDK: - - false - false - src\ (VS-Windows only) - Jasmine|Vitest (VS-Windows only) - $(MSBuildProjectDirectory)\dist\...> (backslashes leaked literal 'obj\Debug' folders on macOS/Linux every time dotnet build ran) - opt-in in Paperless.slnx (only needed because the JS SDK ignored projects that weren't explicitly selected per config) The bootstrap commit (02ce2b3, today 01:34 UTC+2) hand-typed SDK version 1.0.1641815, which is a Visual Studio Windows internal build number from the IDE's private NuGet feed and never published to nuget.org — that's why dotnet build outside VS-Windows failed to resolve it. Dropping the SDK entirely removes the version-pinning fragility for good. Both projects still surface their source trees to Rider's solution explorer via etc., and 'dotnet build Paperless.slnx' remains green (0 errors). Real frontend builds keep happening in the pnpm CI jobs. Co-Authored-By: Claude Opus 4.7 (1M context) --- Paperless.slnx | 8 +-- .../PaperlessUI.Angular.esproj | 56 ++++++++++++++---- PaperlessUI.React/PaperlessUI.React.esproj | 57 +++++++++++++++---- 3 files changed, 95 insertions(+), 26 deletions(-) diff --git a/Paperless.slnx b/Paperless.slnx index 88e2c15..22e5342 100644 --- a/Paperless.slnx +++ b/Paperless.slnx @@ -5,11 +5,7 @@ - - - - - - + + diff --git a/PaperlessUI.Angular/PaperlessUI.Angular.esproj b/PaperlessUI.Angular/PaperlessUI.Angular.esproj index 1c0e4a5..31323fc 100644 --- a/PaperlessUI.Angular/PaperlessUI.Angular.esproj +++ b/PaperlessUI.Angular/PaperlessUI.Angular.esproj @@ -1,13 +1,49 @@ - + + + + - pnpm run start - src\ - Jasmine - - false - - false - - $(MSBuildProjectDirectory)\dist\paperless-ui-angular + $(MSBuildProjectDirectory)/ + pnpm + $(FrontendRoot)dist/paperless-ui-angular + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PaperlessUI.React/PaperlessUI.React.esproj b/PaperlessUI.React/PaperlessUI.React.esproj index 55cd96a..2c91422 100644 --- a/PaperlessUI.React/PaperlessUI.React.esproj +++ b/PaperlessUI.React/PaperlessUI.React.esproj @@ -1,13 +1,50 @@ - + + + + - pnpm run dev - src\ - Vitest - - false - - false - - $(MSBuildProjectDirectory)\dist + $(MSBuildProjectDirectory)/ + pnpm + $(FrontendRoot)dist + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +