From 78c98b171259385f99d2bc9ffe9099c3836b341d Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Sat, 13 Jan 2024 14:17:18 +0100 Subject: [PATCH 01/63] Increment version to 5.5.2 (used for pre-release builds from ci) --- Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Build.props b/Directory.Build.props index 0c2b51e13b..534f9bb7af 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -27,6 +27,6 @@ false $(MSBuildThisFileDirectory)CodingGuidelines.ruleset $(MSBuildThisFileDirectory)tests.runsettings - 5.5.1 + 5.5.2 From 167197ae4b9e86b877353de159c05fc19fd59942 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Jan 2024 22:52:49 +0000 Subject: [PATCH 02/63] Bump actions/dependency-review-action from 3 to 4 (#1442) --- .github/workflows/deps-review.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deps-review.yml b/.github/workflows/deps-review.yml index b9945082d5..b9d6d20fff 100644 --- a/.github/workflows/deps-review.yml +++ b/.github/workflows/deps-review.yml @@ -11,4 +11,4 @@ jobs: - name: 'Checkout Repository' uses: actions/checkout@v4 - name: 'Dependency Review' - uses: actions/dependency-review-action@v3 + uses: actions/dependency-review-action@v4 From 459e27bd0cd3b153390ee89b8835494fcfca38ed Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 Jan 2024 00:19:23 +0000 Subject: [PATCH 03/63] Bump jetbrains.resharper.globaltools from 2023.3.2 to 2023.3.3 (#1443) --- .config/dotnet-tools.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 575923d62c..556e9c5598 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -3,7 +3,7 @@ "isRoot": true, "tools": { "jetbrains.resharper.globaltools": { - "version": "2023.3.2", + "version": "2023.3.3", "commands": [ "jb" ] From 8d37ce6488c552b5352f3774557945b869b96dfe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Feb 2024 23:52:10 +0000 Subject: [PATCH 04/63] Bump dotnet-reportgenerator-globaltool from 5.2.0 to 5.2.1 (#1453) --- .config/dotnet-tools.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 556e9c5598..9658fff117 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -15,7 +15,7 @@ ] }, "dotnet-reportgenerator-globaltool": { - "version": "5.2.0", + "version": "5.2.1", "commands": [ "reportgenerator" ] From 412af65b275a372c8de935f2db7cf37b0e0f448f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Feb 2024 00:26:58 +0000 Subject: [PATCH 05/63] Bump codecov/codecov-action from 3 to 4 (#1452) --- .github/workflows/build.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index eb3aab63b2..0e41da591a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -138,7 +138,9 @@ jobs: dotnet test --no-build --configuration Release --collect:"XPlat Code Coverage" --logger "GitHubActions;summary.includeSkippedTests=true" - name: Upload coverage to codecov.io if: matrix.os == 'ubuntu-latest' - uses: codecov/codecov-action@v3 + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + uses: codecov/codecov-action@v4 with: fail_ci_if_error: true verbose: true From d9d74f4bb2eda64a6196c3a6424185092e11ed0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire?= Date: Tue, 6 Feb 2024 21:42:12 -0500 Subject: [PATCH 06/63] doc: fix path of path example --- docs/usage/writing/updating.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/usage/writing/updating.md b/docs/usage/writing/updating.md index ea27e1a220..30e1b4fa7d 100644 --- a/docs/usage/writing/updating.md +++ b/docs/usage/writing/updating.md @@ -5,7 +5,7 @@ To modify the attributes of a single resource, send a PATCH request. The next example changes the article caption: ```http -PATCH /articles HTTP/1.1 +PATCH /articles/1 HTTP/1.1 { "data": { From 06195b84be389223508de5077a5127098cdef0c1 Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Wed, 7 Feb 2024 10:40:52 +0100 Subject: [PATCH 07/63] Update ROADMAP.md --- ROADMAP.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index 270ae294e6..3ffba718e7 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -2,12 +2,14 @@ This document provides an overview of the direction this project is heading and lists what we intend to work on in the near future. -> Disclaimer: This is an open source project. The available time of our contributors varies and therefore we do not plan release dates. This document expresses our current intent, which may change over time. +> Disclaimer: This is an open-source project. The available time of our contributors varies and therefore we do not plan release dates. This document expresses our current intent, which may change over time. -We have interest in the following topics. It's too soon yet to decide whether they'll make it into v5.x or in a later major version. +We have an interest in the following topics. It's too soon yet to decide whether they'll make it into v5.x or in a later major version. +- OpenAPI (Swagger): Generate documentation and typed clients [#1046](https://github.com/json-api-dotnet/JsonApiDotNetCore/issues/1046) +- Query strings on JSON-mapped columns [#1439](https://github.com/json-api-dotnet/JsonApiDotNetCore/issues/1439) +- Improved SQL Server support [#1118](https://github.com/json-api-dotnet/JsonApiDotNetCore/issues/1118) - Optimistic concurrency [#1119](https://github.com/json-api-dotnet/JsonApiDotNetCore/pull/1119) -- OpenAPI (Swagger) [#1046](https://github.com/json-api-dotnet/JsonApiDotNetCore/issues/1046) - Fluent API [#776](https://github.com/json-api-dotnet/JsonApiDotNetCore/issues/776) - Idempotency [#1132](https://github.com/json-api-dotnet/JsonApiDotNetCore/pull/1132) From 587d972e208f40650da7a5723b067e1c839cc40b Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Wed, 7 Feb 2024 10:43:41 +0100 Subject: [PATCH 08/63] Add sponsor link --- ROADMAP.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ROADMAP.md b/ROADMAP.md index 3ffba718e7..7ba6a2a5a8 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -21,3 +21,5 @@ Please give us feedback that will give us insight on the following points: * Existing features that are missing some capability or otherwise don't work well enough. * Missing features that should be added to the product. * Design choices for a feature that is currently in-progress. + +Please consider to [sponsor the project](https://github.com/sponsors/json-api-dotnet). From 3f62b77c5e7ebf757d80d01ce0a3d455b51ad9e3 Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Sun, 18 Feb 2024 02:45:56 +0100 Subject: [PATCH 09/63] Replaces CreateTupleAccessExpressionForConstant with CloseOver, which is simpler and requires less reflection. --- .../QueryableBuilding/SelectClauseBuilder.cs | 4 +-- .../SkipTakeClauseBuilder.cs | 2 +- .../QueryableBuilding/WhereClauseBuilder.cs | 3 +- .../Queries/SystemExpressionBuilder.cs | 34 +++++++++++++++++++ .../Queries/SystemExpressionExtensions.cs | 33 ------------------ .../Resources/ResourceFactory.cs | 2 +- 6 files changed, 39 insertions(+), 39 deletions(-) create mode 100644 src/JsonApiDotNetCore/Queries/SystemExpressionBuilder.cs delete mode 100644 src/JsonApiDotNetCore/Queries/SystemExpressionExtensions.cs diff --git a/src/JsonApiDotNetCore/Queries/QueryableBuilding/SelectClauseBuilder.cs b/src/JsonApiDotNetCore/Queries/QueryableBuilding/SelectClauseBuilder.cs index 858532d7c2..d1113946ad 100644 --- a/src/JsonApiDotNetCore/Queries/QueryableBuilding/SelectClauseBuilder.cs +++ b/src/JsonApiDotNetCore/Queries/QueryableBuilding/SelectClauseBuilder.cs @@ -93,9 +93,9 @@ private Expression CreateLambdaBodyInitializerForTypeHierarchy(FieldSelection se private static BinaryExpression CreateRuntimeTypeCheck(LambdaScope lambdaScope, Type concreteClrType) { // Emitting "resource.GetType() == typeof(Article)" instead of "resource is Article" so we don't need to check for most-derived - // types first. This way, we can fallback to "anything else" at the end without worrying about order. + // types first. This way, we can fall back to "anything else" at the end without worrying about order. - Expression concreteTypeConstant = concreteClrType.CreateTupleAccessExpressionForConstant(typeof(Type)); + Expression concreteTypeConstant = SystemExpressionBuilder.CloseOver(concreteClrType); MethodCallExpression getTypeCall = Expression.Call(lambdaScope.Accessor, TypeGetTypeMethod); return Expression.MakeBinary(ExpressionType.Equal, getTypeCall, concreteTypeConstant, false, TypeOpEqualityMethod); diff --git a/src/JsonApiDotNetCore/Queries/QueryableBuilding/SkipTakeClauseBuilder.cs b/src/JsonApiDotNetCore/Queries/QueryableBuilding/SkipTakeClauseBuilder.cs index b48fa696db..4c54586cb6 100644 --- a/src/JsonApiDotNetCore/Queries/QueryableBuilding/SkipTakeClauseBuilder.cs +++ b/src/JsonApiDotNetCore/Queries/QueryableBuilding/SkipTakeClauseBuilder.cs @@ -36,7 +36,7 @@ public override Expression VisitPagination(PaginationExpression expression, Quer private static Expression ExtensionMethodCall(Expression source, string operationName, int value, QueryClauseBuilderContext context) { - Expression constant = value.CreateTupleAccessExpressionForConstant(typeof(int)); + Expression constant = SystemExpressionBuilder.CloseOver(value); return Expression.Call(context.ExtensionType, operationName, [context.LambdaScope.Parameter.Type], source, constant); } diff --git a/src/JsonApiDotNetCore/Queries/QueryableBuilding/WhereClauseBuilder.cs b/src/JsonApiDotNetCore/Queries/QueryableBuilding/WhereClauseBuilder.cs index f14d795f7b..b5fafdd21b 100644 --- a/src/JsonApiDotNetCore/Queries/QueryableBuilding/WhereClauseBuilder.cs +++ b/src/JsonApiDotNetCore/Queries/QueryableBuilding/WhereClauseBuilder.cs @@ -245,7 +245,6 @@ public override Expression VisitNullConstant(NullConstantExpression expression, public override Expression VisitLiteralConstant(LiteralConstantExpression expression, QueryClauseBuilderContext context) { - Type type = expression.TypedValue.GetType(); - return expression.TypedValue.CreateTupleAccessExpressionForConstant(type); + return SystemExpressionBuilder.CloseOver(expression.TypedValue); } } diff --git a/src/JsonApiDotNetCore/Queries/SystemExpressionBuilder.cs b/src/JsonApiDotNetCore/Queries/SystemExpressionBuilder.cs new file mode 100644 index 0000000000..f625ee9b4f --- /dev/null +++ b/src/JsonApiDotNetCore/Queries/SystemExpressionBuilder.cs @@ -0,0 +1,34 @@ +using System.Linq.Expressions; +using System.Reflection; + +#pragma warning disable AV1008 + +namespace JsonApiDotNetCore.Queries; + +internal static class SystemExpressionBuilder +{ + private static readonly MethodInfo CloseOverOpenMethod = + typeof(SystemExpressionBuilder).GetMethods().Single(method => method is { Name: nameof(CloseOver), IsGenericMethod: true }); + + // To enable efficient query plan caching, inline constants (that vary per request) should be converted into query parameters. + // https://stackoverflow.com/questions/54075758/building-a-parameterized-entityframework-core-expression + // + // CloseOver can be used to change a query like: + // SELECT ... FROM ... WHERE x."Age" = 3 + // into: + // SELECT ... FROM ... WHERE x."Age" = @p0 + + public static Expression CloseOver(object value) + { + ArgumentGuard.NotNull(value); + + MethodInfo closeOverClosedMethod = CloseOverOpenMethod.MakeGenericMethod(value.GetType()); + return (Expression)closeOverClosedMethod.Invoke(null, [value])!; + } + + public static Expression CloseOver(T value) + { + // From https://github.com/dotnet/efcore/issues/28151#issuecomment-1374480257. + return ((Expression>)(() => value)).Body; + } +} diff --git a/src/JsonApiDotNetCore/Queries/SystemExpressionExtensions.cs b/src/JsonApiDotNetCore/Queries/SystemExpressionExtensions.cs deleted file mode 100644 index ef81aece33..0000000000 --- a/src/JsonApiDotNetCore/Queries/SystemExpressionExtensions.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Linq.Expressions; -using System.Reflection; - -namespace JsonApiDotNetCore.Queries; - -internal static class SystemExpressionExtensions -{ - public static Expression CreateTupleAccessExpressionForConstant(this object? value, Type type) - { - // To enable efficient query plan caching, inline constants (that vary per request) should be converted into query parameters. - // https://stackoverflow.com/questions/54075758/building-a-parameterized-entityframework-core-expression - - // This method can be used to change a query like: - // SELECT ... FROM ... WHERE x."Age" = 3 - // into: - // SELECT ... FROM ... WHERE x."Age" = @p0 - - // The code below builds the next expression for a type T that is unknown at compile time: - // Expression.Property(Expression.Constant(Tuple.Create(value)), "Item1") - // Which represents the next C# code: - // Tuple.Create(value).Item1; - - MethodInfo tupleCreateUnboundMethod = typeof(Tuple).GetMethods() - .Single(method => method is { Name: "Create", IsGenericMethod: true } && method.GetGenericArguments().Length == 1); - - MethodInfo tupleCreateClosedMethod = tupleCreateUnboundMethod.MakeGenericMethod(type); - - ConstantExpression constantExpression = Expression.Constant(value, type); - - MethodCallExpression tupleCreateCall = Expression.Call(tupleCreateClosedMethod, constantExpression); - return Expression.Property(tupleCreateCall, "Item1"); - } -} diff --git a/src/JsonApiDotNetCore/Resources/ResourceFactory.cs b/src/JsonApiDotNetCore/Resources/ResourceFactory.cs index 9d282b4938..f8af9dfa2f 100644 --- a/src/JsonApiDotNetCore/Resources/ResourceFactory.cs +++ b/src/JsonApiDotNetCore/Resources/ResourceFactory.cs @@ -102,7 +102,7 @@ public NewExpression CreateNewExpression(Type resourceClrType) { object constructorArgument = ActivatorUtilities.GetServiceOrCreateInstance(_serviceProvider, constructorParameter.ParameterType); - Expression argumentExpression = constructorArgument.CreateTupleAccessExpressionForConstant(constructorArgument.GetType()); + Expression argumentExpression = SystemExpressionBuilder.CloseOver(constructorArgument); constructorArguments.Add(argumentExpression); } #pragma warning disable AV1210 // Catch a specific exception instead of Exception, SystemException or ApplicationException From d1707ef55642f258249a4dd9e2054f23e5acf6c9 Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Wed, 21 Feb 2024 07:10:13 +0100 Subject: [PATCH 10/63] Resharper: "Local function can be made static" is at warning level in cibuild, but was turned off in IDE (#1473) --- JsonApiDotNetCore.sln.DotSettings | 1 + 1 file changed, 1 insertion(+) diff --git a/JsonApiDotNetCore.sln.DotSettings b/JsonApiDotNetCore.sln.DotSettings index 6e4e064588..4f68cc519a 100644 --- a/JsonApiDotNetCore.sln.DotSettings +++ b/JsonApiDotNetCore.sln.DotSettings @@ -59,6 +59,7 @@ JsonApiDotNetCore.ArgumentGuard.NotNull($EXPR$); SUGGESTION HINT WARNING + SUGGESTION DO_NOT_SHOW HINT SUGGESTION From 4362c5400d2d60161fc7cd476a5be11c634896c0 Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Thu, 22 Feb 2024 01:11:01 +0100 Subject: [PATCH 11/63] Fix spelling error in comment --- test/TestBuildingBlocks/FakerContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/TestBuildingBlocks/FakerContainer.cs b/test/TestBuildingBlocks/FakerContainer.cs index 72f9a05567..c29700c968 100644 --- a/test/TestBuildingBlocks/FakerContainer.cs +++ b/test/TestBuildingBlocks/FakerContainer.cs @@ -34,7 +34,7 @@ private static MethodBase GetTestMethod() if (testMethod == null) { // If called after the first await statement, the test method is no longer on the stack, - // but has been replaced with the compiler-generated async/wait state machine. + // but has been replaced with the compiler-generated async/await state machine. throw new InvalidOperationException("Fakers can only be used from within (the start of) a test method."); } From 330459c2d285cbfb2adbb5ba684ab9f583d8ea07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire?= Date: Sun, 25 Feb 2024 18:33:35 -0500 Subject: [PATCH 12/63] doc: fix POST status code (#1478) --- docs/usage/writing/creating.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/usage/writing/creating.md b/docs/usage/writing/creating.md index ba0a21d52b..7e8a3243af 100644 --- a/docs/usage/writing/creating.md +++ b/docs/usage/writing/creating.md @@ -17,7 +17,7 @@ POST /articles HTTP/1.1 ``` When using client-generated IDs and only attributes from the request have changed, the server returns `204 No Content`. -Otherwise, the server returns `200 OK`, along with the updated resource and its newly assigned ID. +Otherwise, the server returns `201 Created`, along with the updated resource and its newly assigned ID. In both cases, a `Location` header is returned that contains the URL to the new resource. From fe957673dd9a60c881674accdee6219cf775cc55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire?= Date: Mon, 26 Feb 2024 04:20:43 -0500 Subject: [PATCH 13/63] doc: clarify wording around 204 for POST (#1481) * doc: clarify wording around 204 for POST * Update creating.md --- docs/usage/writing/creating.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/usage/writing/creating.md b/docs/usage/writing/creating.md index 7e8a3243af..8cc0c03e49 100644 --- a/docs/usage/writing/creating.md +++ b/docs/usage/writing/creating.md @@ -16,8 +16,8 @@ POST /articles HTTP/1.1 } ``` -When using client-generated IDs and only attributes from the request have changed, the server returns `204 No Content`. -Otherwise, the server returns `201 Created`, along with the updated resource and its newly assigned ID. +When using client-generated IDs and all attributes of the created resource are the same as in the request, the server +returns `204 No Content`. Otherwise, the server returns `201 Created`, along with the stored attributes and its newly assigned ID. In both cases, a `Location` header is returned that contains the URL to the new resource. From 442718726beaa41297a1cead397d558dddada480 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Feb 2024 23:23:24 +0000 Subject: [PATCH 14/63] Bump dotnet-reportgenerator-globaltool from 5.2.1 to 5.2.2 (#1482) --- .config/dotnet-tools.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 9658fff117..240023b45a 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -15,7 +15,7 @@ ] }, "dotnet-reportgenerator-globaltool": { - "version": "5.2.1", + "version": "5.2.2", "commands": [ "reportgenerator" ] From 7a64b9d9a67689f3fa534cf7df3166f0a25b9277 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire?= Date: Tue, 27 Feb 2024 19:59:18 -0500 Subject: [PATCH 15/63] Don't crash on empty query string parameter name (#1484) --- .../QueryStrings/QueryStringReader.cs | 5 +++++ .../QueryStrings/QueryStringTests.cs | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/src/JsonApiDotNetCore/QueryStrings/QueryStringReader.cs b/src/JsonApiDotNetCore/QueryStrings/QueryStringReader.cs index c412d03c94..e3c944a045 100644 --- a/src/JsonApiDotNetCore/QueryStrings/QueryStringReader.cs +++ b/src/JsonApiDotNetCore/QueryStrings/QueryStringReader.cs @@ -38,6 +38,11 @@ public void ReadAll(DisableQueryStringAttribute? disableQueryStringAttribute) foreach ((string parameterName, StringValues parameterValue) in _queryStringAccessor.Query) { + if (parameterName.Length == 0) + { + continue; + } + IQueryStringParameterReader? reader = _parameterReaders.FirstOrDefault(nextReader => nextReader.CanRead(parameterName)); if (reader != null) diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/QueryStringTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/QueryStringTests.cs index 0aa955a219..4f6ee95ad2 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/QueryStringTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/QueryStringTests.cs @@ -63,6 +63,24 @@ public async Task Can_use_unknown_query_string_parameter() httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); } + [Theory] + [InlineData("")] + [InlineData("bar")] + public async Task Can_use_empty_query_string_parameter_name(string parameterValue) + { + // Arrange + var options = (JsonApiOptions)_testContext.Factory.Services.GetRequiredService(); + options.AllowUnknownQueryStringParameters = false; + + string route = $"calendars?={parameterValue}"; + + // Act + (HttpResponseMessage httpResponse, Document _) = await _testContext.ExecuteGetAsync(route); + + // Assert + httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); + } + [Theory] [InlineData("filter")] [InlineData("sort")] From 72bd6f81167efb2f2ebe9edc1f3c390b4f9824a9 Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Sat, 2 Mar 2024 03:59:04 +0100 Subject: [PATCH 16/63] Document PR workflow (#1487) --- .github/CONTRIBUTING.md | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 4205b1ceec..e7d3ce2494 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -39,7 +39,7 @@ When you are creating an enhancement suggestion, please include as many details - **Use a clear and descriptive title** for the issue to identify the suggestion. - **Provide a step-by-step description of the suggested enhancement** in as many details as possible. -- **Provide specific examples to demonstrate the usage.** Include copy/pasteable snippets which you use in those examples, as [Markdown code blocks](https://docs.github.com/en/github/writing-on-github/creating-and-highlighting-code-blocks). +- **Provide specific examples to demonstrate the usage.** Include copy/pasteable snippets which you use in those examples as [Markdown code blocks](https://docs.github.com/en/github/writing-on-github/creating-and-highlighting-code-blocks). - **Describe the current behavior and explain which behavior you expected to see instead** and why. - **Explain why this enhancement would be useful** to most users and isn't something that can or should be implemented in your API project directly. - **Verify that your enhancement does not conflict** with the [JSON:API specification](https://jsonapi.org/). @@ -56,7 +56,7 @@ Please follow these steps to have your contribution considered by the maintainer - Follow all instructions in the template. Don't forget to add tests and update documentation. - After you submit your pull request, verify that all status checks are passing. In release builds, all compiler warnings are treated as errors, so you should address them before push. -We use [CSharpGuidelines](https://csharpcodingguidelines.com/) as our coding standard (with a few minor exceptions). Coding style is validated during PR build, where we inject an extra settings layer that promotes various suggestions to warning level. This ensures a high-quality codebase without interfering too much when editing code. +We use [CSharpGuidelines](https://csharpcodingguidelines.com/) as our coding standard. Coding style is validated during PR build, where we inject an extra settings layer that promotes various IDE suggestions to warning level. This ensures a high-quality codebase without interfering too much while editing code. You can run the following [PowerShell scripts](https://github.com/PowerShell/PowerShell/releases) locally: - `pwsh ./inspectcode.ps1`: Scans the code for style violations and opens the result in your web browser. - `pwsh ./cleanupcode.ps1 [branch-name-or-commit-hash]`: Reformats the codebase to match with our configured style, optionally only changed files since the specified branch (usually master). @@ -86,13 +86,39 @@ public sealed class AppDbContext : DbContext } ``` +### Pull request workflow + +Please follow the steps and guidelines below for a smooth experience. + +Authors: +- When opening a new pull request, create it in **Draft** mode. +- After you've completed the work *and* all checks are green, click the **Ready for review** button. + - If you have permissions to do so, ask a team member for review. +- Once the review has started, don't force-push anymore. +- When you've addressed feedback from a conversation, mark it with a thumbs-up or add a some text. +- Don't close a conversation you didn't start. The creator closes it after verifying the concern has been addressed. +- Apply suggestions in a batch, instead of individual commits (to minimize email notifications). +- Re-request review when you're ready for another round. +- If you want to clean up your commits before merge, let the reviewer know in time. This is optional. + +Reviewers: +- If you're unable to review within a few days, let the author know what to expect. +- Use **Start a review** instead of **Add single comment** (to minimize email notifications). +- Consider to use suggestions (the ± button). +- Don't close a conversation you didn't start. Close the ones you opened after verifying the concern has been addressed. +- Once approved, use a merge commit only if all commits are clean. Otherwise, squash them into a single commit. + A commit is considered clean when: + - It is properly documented and covers all aspects of an isolated change (code, style, tests, docs). + - Checking out the commit results in a green build. + - Having this commit show up in the history is helpful (and can potentially be reverted). + ## Creating a release (for maintainers) - Verify documentation is up-to-date -- Bump the package version in Directory.Build.props +- Bump the package version in `Directory.Build.props` - Create a GitHub release -- Update https://github.com/json-api-dotnet/JsonApiDotNetCore.MongoDb to consume the new version and release -- Create a new branch in https://github.com/json-api-dotnet/MigrationGuide and update README.md in master +- Update [JsonApiDotNetCore.MongoDb](https://github.com/json-api-dotnet/JsonApiDotNetCore.MongoDb) to consume the new version and release +- Create a new branch in [MigrationGuide](https://github.com/json-api-dotnet/MigrationGuide) and update README.md in master, if major version change ## Backporting and hotfixes (for maintainers) @@ -101,7 +127,7 @@ public sealed class AppDbContext : DbContext git checkout tags/v2.5.1 -b release/2.5.2 ``` - Cherrypick the merge commit: `git cherry-pick {git commit SHA}` -- Bump the package version in Directory.Build.props +- Bump the package version in `Directory.Build.props` - Make any other compatibility, documentation, or tooling related changes - Push the branch to origin and verify the build - Once the build is verified, create a GitHub release, tagging the release branch From 8a7fcf1fe1e2c12ba56c59614f2cf019c451b4ab Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Sun, 3 Mar 2024 13:43:12 +0100 Subject: [PATCH 17/63] Add missing documentation for type parameters --- .../Queries/Expressions/QueryExpressionVisitor.cs | 6 ++++++ src/JsonApiDotNetCore/Repositories/DbContextResolver.cs | 3 +++ .../Repositories/EntityFrameworkCoreRepository.cs | 6 ++++++ src/JsonApiDotNetCore/Resources/IResourceChangeTracker.cs | 3 +++ .../Resources/QueryStringParameterHandlers.cs | 3 +++ .../Serialization/Objects/SingleOrManyData.cs | 3 +++ 6 files changed, 24 insertions(+) diff --git a/src/JsonApiDotNetCore/Queries/Expressions/QueryExpressionVisitor.cs b/src/JsonApiDotNetCore/Queries/Expressions/QueryExpressionVisitor.cs index 7dcf44b1f4..12242c29ff 100644 --- a/src/JsonApiDotNetCore/Queries/Expressions/QueryExpressionVisitor.cs +++ b/src/JsonApiDotNetCore/Queries/Expressions/QueryExpressionVisitor.cs @@ -5,6 +5,12 @@ namespace JsonApiDotNetCore.Queries.Expressions; /// /// Implements the visitor design pattern that enables traversing a tree. /// +/// +/// The type to use for passing custom state between visit methods. +/// +/// +/// The type that is returned from visit methods. +/// [PublicAPI] public abstract class QueryExpressionVisitor { diff --git a/src/JsonApiDotNetCore/Repositories/DbContextResolver.cs b/src/JsonApiDotNetCore/Repositories/DbContextResolver.cs index 794eecc6f2..bc275a96c1 100644 --- a/src/JsonApiDotNetCore/Repositories/DbContextResolver.cs +++ b/src/JsonApiDotNetCore/Repositories/DbContextResolver.cs @@ -4,6 +4,9 @@ namespace JsonApiDotNetCore.Repositories; /// +/// +/// The type of the to resolve. +/// [PublicAPI] public sealed class DbContextResolver : IDbContextResolver where TDbContext : DbContext diff --git a/src/JsonApiDotNetCore/Repositories/EntityFrameworkCoreRepository.cs b/src/JsonApiDotNetCore/Repositories/EntityFrameworkCoreRepository.cs index 4c3314ddab..a5f083932b 100644 --- a/src/JsonApiDotNetCore/Repositories/EntityFrameworkCoreRepository.cs +++ b/src/JsonApiDotNetCore/Repositories/EntityFrameworkCoreRepository.cs @@ -21,6 +21,12 @@ namespace JsonApiDotNetCore.Repositories; /// /// Implements the foundational Repository layer in the JsonApiDotNetCore architecture that uses Entity Framework Core. /// +/// +/// The resource type. +/// +/// +/// The resource identifier type. +/// [PublicAPI] public class EntityFrameworkCoreRepository : IResourceRepository, IRepositorySupportsTransaction where TResource : class, IIdentifiable diff --git a/src/JsonApiDotNetCore/Resources/IResourceChangeTracker.cs b/src/JsonApiDotNetCore/Resources/IResourceChangeTracker.cs index 1f69735f92..13404f2759 100644 --- a/src/JsonApiDotNetCore/Resources/IResourceChangeTracker.cs +++ b/src/JsonApiDotNetCore/Resources/IResourceChangeTracker.cs @@ -3,6 +3,9 @@ namespace JsonApiDotNetCore.Resources; /// /// Used to determine whether additional changes to a resource (side effects), not specified in a POST or PATCH request, have been applied. /// +/// +/// The resource type. +/// public interface IResourceChangeTracker where TResource : class, IIdentifiable { diff --git a/src/JsonApiDotNetCore/Resources/QueryStringParameterHandlers.cs b/src/JsonApiDotNetCore/Resources/QueryStringParameterHandlers.cs index b48c46e26e..7fe8970b53 100644 --- a/src/JsonApiDotNetCore/Resources/QueryStringParameterHandlers.cs +++ b/src/JsonApiDotNetCore/Resources/QueryStringParameterHandlers.cs @@ -6,4 +6,7 @@ namespace JsonApiDotNetCore.Resources; /// This is an alias type intended to simplify the implementation's method signature. See /// for usage details. /// +/// +/// The resource type. +/// public sealed class QueryStringParameterHandlers : Dictionary, StringValues, IQueryable>>; diff --git a/src/JsonApiDotNetCore/Serialization/Objects/SingleOrManyData.cs b/src/JsonApiDotNetCore/Serialization/Objects/SingleOrManyData.cs index 1126f84f26..99884d61e6 100644 --- a/src/JsonApiDotNetCore/Serialization/Objects/SingleOrManyData.cs +++ b/src/JsonApiDotNetCore/Serialization/Objects/SingleOrManyData.cs @@ -9,6 +9,9 @@ namespace JsonApiDotNetCore.Serialization.Objects; /// Represents the value of the "data" element, which is either null, a single object or an array of objects. Add /// to to properly roundtrip. /// +/// +/// The type of elements being wrapped, typically or . +/// [PublicAPI] public readonly struct SingleOrManyData // The "new()" constraint exists for parity with SingleOrManyDataConverterFactory, which creates empty instances From a3c92c71108d8a56f023bc415d08f65a44e718c4 Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Mon, 4 Mar 2024 00:25:53 +0100 Subject: [PATCH 18/63] Fixes in landing page --- docs/home/index.html | 56 ++++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/docs/home/index.html b/docs/home/index.html index 2c3e57849b..582eb7f619 100644 --- a/docs/home/index.html +++ b/docs/home/index.html @@ -9,7 +9,7 @@ - + @@ -22,7 +22,10 @@

JsonApiDotNetCore

-

A framework for building JSON:API compliant REST APIs using .NET Core and Entity Framework Core. Includes support for Atomic Operations.

+

+ A framework for building JSON:API compliant REST APIs using .NET Core and Entity Framework Core. + Includes support for Atomic Operations. +

Read more Getting started Contribute on GitHub @@ -43,12 +46,13 @@

A framework for building JSON

Objectives

- The goal of this library is to simplify the development of APIs that leverage the full range of features provided by the JSON:API specification. + The goal of this library is to simplify the development of APIs that leverage the full range of features + provided by the JSON:API specification. You just need to focus on defining the resources and implementing your custom business logic.

- +

Eliminate boilerplate

We strive to eliminate as much boilerplate as possible by offering out-of-the-box features such as sorting, filtering and pagination.

@@ -69,28 +73,28 @@

Features

The following features are supported, from HTTP all the way down to the database

-
+

Filtering

Perform compound filtering using the filter query string parameter

-
+
-
+

Sorting

Order resources on one or multiple attributes using the sort query string parameter

-