diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml
index 85a8338..49284a2 100644
--- a/.github/workflows/sonarcloud.yml
+++ b/.github/workflows/sonarcloud.yml
@@ -22,13 +22,18 @@ jobs:
with:
dotnet-version: '8.0.x'
- - name: Install SonarScanner
- run: dotnet tool install --global dotnet-sonarscanner
+ - name: Install global tools (SonarScanner + ReportGenerator)
+ run: |
+ dotnet tool install --global dotnet-sonarscanner
+ dotnet tool install --global dotnet-reportgenerator-globaltool
+
+ - name: Add tool path to environment
+ run: echo "$HOME/.dotnet/tools" >> $GITHUB_PATH
- name: Restore dependencies
run: dotnet restore src/Faura.sln
- - name: Begin SonarCloud Analysis
+ - name: Begin SonarCloud analysis
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: |
@@ -36,10 +41,35 @@ jobs:
/k:"JosepFe_faura" \
/o:"josepfe" \
/d:sonar.login="${SONAR_TOKEN}" \
- /d:sonar.host.url="https://sonarcloud.io"
+ /d:sonar.host.url="https://sonarcloud.io" \
+ /d:sonar.cs.opencover.reportsPaths="coverage/combined/coverage.opencover.xml"
- name: Build solution
- run: dotnet build src/Faura.sln --no-restore --no-incremental
+ run: dotnet build src/Faura.sln --no-restore --configuration Release
+
+ - name: Run Unit Tests with Coverage (WebAPI)
+ run: |
+ mkdir -p coverage/unit
+ dotnet test src/Templates/Faura.WebAPI.UnitTests/Faura.WebAPI.UnitTests.csproj \
+ --configuration Release \
+ /p:CollectCoverage=true \
+ /p:CoverletOutputFormat=opencover \
+ /p:CoverletOutput=coverage/unit/ \
+ --no-build
+
+ - name: Merge coverage reports
+ run: |
+ mkdir -p coverage/combined
+ reportgenerator \
+ -reports:"coverage/unit/coverage.opencover.xml" \
+ -targetdir:"coverage/combined" \
+ -reporttypes:Html
+
+ - name: Upload Coverage Report Artifact
+ uses: actions/upload-artifact@v4
+ with:
+ name: CoverageReport
+ path: coverage/combined
- name: End SonarCloud Analysis
env:
diff --git a/.gitignore b/.gitignore
index 4c071b2..8de49f6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -150,7 +150,6 @@ AppPackages/
sql/
*.Cache
ClientBin/
-[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
diff --git a/src/.editorconfig b/src/.editorconfig
new file mode 100644
index 0000000..ded567f
--- /dev/null
+++ b/src/.editorconfig
@@ -0,0 +1,157 @@
+root = true
+
+[*]
+charset = utf-8
+indent_size = 4
+indent_style = space
+insert_final_newline = true
+time_trailing_whitespace = true
+end_of_line = lf
+
+[*.cs]
+csharp_using_directive_placement = inside_namespace:warning
+dotnet_sort_system_directives_first = true
+csharp_style_expression_bodied_methods = true:warning
+csharp_style_expression_bodied_constructors = true:warning
+csharp_style_expression_bodied_properties = true:warning
+csharp_style_expression_bodied_indexers = true:warning
+csharp_style_expression_bodied_accessors = true:warning
+
+
+### IDE specific rules
+
+# IDE0090: Use 'new(...)'
+csharp_style_implicit_object_creation_when_type_is_apparent = true
+
+# IDE0017: Simplify object initialization
+dotnet_style_object_initializer = true
+
+### StyleCop.Analyzers custom configuration
+
+# SA0001: Xml comment analysis disabled
+dotnet_diagnostic.SA0001.severity = none
+
+# Methods should only be documented if shipped as a public API, the best documentation is the code implementation
+dotnet_diagnostic.SA1516.severity = none
+dotnet_diagnostic.SA1600.severity = none
+dotnet_diagnostic.SA1601.severity = none
+dotnet_diagnostic.SA1602.severity = none
+dotnet_diagnostic.SA1611.severity = none
+dotnet_diagnostic.SA1615.severity = none
+dotnet_diagnostic.SA1618.severity = none
+dotnet_diagnostic.SA1619.severity = none
+
+# SA1633: File should have header
+dotnet_diagnostic.SA1633.severity = none
+
+# SA1101: Prefix local calls with this
+dotnet_diagnostic.SA1101.severity = none
+
+# SX1101: Do not prefix local calls with 'this.'
+dotnet_diagnostic.SX1101.severity = warning
+
+# SA1309: Field names should not begin with underscore
+dotnet_diagnostic.SA1309.severity = none
+
+# SX1309: Field names should begin with underscore
+dotnet_diagnostic.SX1309.severity = warning
+
+# SA1130: Classes should not be empty
+dotnet_diagnostic.SA1130.severity = none
+
+# SA1400: Access modifier must be declared
+dotnet_diagnostic.SA1400.severity = warning
+
+# SA1413: Use trailing commas in multi-line initializers
+dotnet_diagnostic.SA1413.severity = warning
+
+# SA1503: Braces should not be omitted
+dotnet_diagnostic.SA1503.severity = none
+
+### SonarAnalyzer.CSharp custom configuration
+
+# S1128: Unused "using" should be removed
+dotnet_diagnostic.S1128.severity = warning
+
+# S2094: Classes should not be empty
+dotnet_diagnostic.S2094.severity = none
+
+# S4487: Unread "private" fields should be removed
+dotnet_diagnostic.S4487.severity = warning
+
+# S1172: Unused method parameters should be removed
+dotnet_diagnostic.S1172.severity = warning
+
+#Disable S1133 for obsolete
+dotnet_diagnostic.S1133.severity = suggestion
+
+#Disable CS0618 for obsolete
+dotnet_diagnostic.CS0618.severity = suggestion
+csharp_indent_labels = one_less_than_current
+csharp_prefer_simple_using_statement = true:suggestion
+csharp_prefer_braces = true:silent
+csharp_style_namespace_declarations = file_scoped:silent
+csharp_style_prefer_method_group_conversion = true:silent
+csharp_style_prefer_top_level_statements = true:silent
+csharp_style_prefer_primary_constructors = true:suggestion
+csharp_prefer_system_threading_lock = true:suggestion
+csharp_style_expression_bodied_operators = false:silent
+csharp_style_expression_bodied_lambdas = true:silent
+csharp_style_expression_bodied_local_functions = false:silent
+csharp_space_around_binary_operators = before_and_after
+dotnet_diagnostic.SA1010.severity = none
+dotnet_diagnostic.SA1000.severity = none
+
+[*.{cs,vb}]
+#### Naming styles ####
+
+# Naming rules
+
+dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
+dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
+dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
+
+dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
+dotnet_naming_rule.types_should_be_pascal_case.symbols = types
+dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
+
+dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
+dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
+dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
+
+# Symbol specifications
+
+dotnet_naming_symbols.interface.applicable_kinds = interface
+dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
+dotnet_naming_symbols.interface.required_modifiers =
+
+dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
+dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
+dotnet_naming_symbols.types.required_modifiers =
+
+dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
+dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
+dotnet_naming_symbols.non_field_members.required_modifiers =
+
+# Naming styles
+
+dotnet_naming_style.begins_with_i.required_prefix = I
+dotnet_naming_style.begins_with_i.required_suffix =
+dotnet_naming_style.begins_with_i.word_separator =
+dotnet_naming_style.begins_with_i.capitalization = pascal_case
+
+dotnet_naming_style.pascal_case.required_prefix =
+dotnet_naming_style.pascal_case.required_suffix =
+dotnet_naming_style.pascal_case.word_separator =
+dotnet_naming_style.pascal_case.capitalization = pascal_case
+
+dotnet_naming_style.pascal_case.required_prefix =
+dotnet_naming_style.pascal_case.required_suffix =
+dotnet_naming_style.pascal_case.word_separator =
+dotnet_naming_style.pascal_case.capitalization = pascal_case
+dotnet_style_operator_placement_when_wrapping = beginning_of_line
+tab_width = 4
+dotnet_style_coalesce_expression = true:suggestion
+dotnet_style_null_propagation = true:suggestion
+dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
+dotnet_style_prefer_auto_properties = true:silent
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
new file mode 100644
index 0000000..7d28e81
--- /dev/null
+++ b/src/Directory.Build.props
@@ -0,0 +1,43 @@
+
+
+ net8.0
+ enable
+ enable
+ latest
+ false
+ en
+ true
+ Faura
+ Faura
+ git
+ 1.0.0
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
diff --git a/src/Faura.sln b/src/Faura.sln
index 6adf77b..0b0ea62 100644
--- a/src/Faura.sln
+++ b/src/Faura.sln
@@ -27,7 +27,22 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Faura.Infrastructure.ApiBoo
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Faura.Infrastructure.IntegrationTesting", "Modules\Faura.Infrastructure.IntegrationTesting\Faura.Infrastructure.IntegrationTesting.csproj", "{09790598-6AD0-D698-A32D-D9A056BAF8D0}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Faura.IntegrationTest", "Templates\Faura.IntegrationTest\Faura.IntegrationTest.csproj", "{89320569-AAF8-4290-B912-699F792319F5}"
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionItems", "SolutionItems", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}"
+ ProjectSection(SolutionItems) = preProject
+ .editorconfig = .editorconfig
+ ..\.gitignore = ..\.gitignore
+ Directory.Build.props = Directory.Build.props
+ global.json = global.json
+ stylecop.json = stylecop.json
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WebAPI", "WebAPI", "{F1517752-590B-4773-A4D6-9E670C639523}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WebAPIGrpc", "WebAPIGrpc", "{F3ABDB5B-F5E0-43DE-898B-4170F6852893}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Faura.WebAPI.UnitTests", "Templates\Faura.WebAPI.UnitTests\Faura.WebAPI.UnitTests.csproj", "{38B3C54C-1AED-42E7-A510-0734DF5A7B8F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Faura.WebAPI.IntegrationTests", "Templates\Faura.WebAPI.IntegrationTests\Faura.WebAPI.IntegrationTests.csproj", "{71A15B05-FF1A-8D1F-0833-4F72927CEC48}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -75,10 +90,14 @@ Global
{09790598-6AD0-D698-A32D-D9A056BAF8D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{09790598-6AD0-D698-A32D-D9A056BAF8D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{09790598-6AD0-D698-A32D-D9A056BAF8D0}.Release|Any CPU.Build.0 = Release|Any CPU
- {89320569-AAF8-4290-B912-699F792319F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {89320569-AAF8-4290-B912-699F792319F5}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {89320569-AAF8-4290-B912-699F792319F5}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {89320569-AAF8-4290-B912-699F792319F5}.Release|Any CPU.Build.0 = Release|Any CPU
+ {38B3C54C-1AED-42E7-A510-0734DF5A7B8F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {38B3C54C-1AED-42E7-A510-0734DF5A7B8F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {38B3C54C-1AED-42E7-A510-0734DF5A7B8F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {38B3C54C-1AED-42E7-A510-0734DF5A7B8F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {71A15B05-FF1A-8D1F-0833-4F72927CEC48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {71A15B05-FF1A-8D1F-0833-4F72927CEC48}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {71A15B05-FF1A-8D1F-0833-4F72927CEC48}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {71A15B05-FF1A-8D1F-0833-4F72927CEC48}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -87,14 +106,17 @@ Global
{F0757E5C-ACCD-44DD-B755-64CAFE654A7A} = {420A3EFF-9247-407D-B58F-EC8144EB14F4}
{8146A031-8E30-4F0F-940E-F77795C208F8} = {420A3EFF-9247-407D-B58F-EC8144EB14F4}
{1F34C695-2396-428D-87EF-7D3FDD9BD8C2} = {420A3EFF-9247-407D-B58F-EC8144EB14F4}
- {2B690895-0614-4013-85D8-7FC47B956C26} = {0C2B5D2F-B5EE-48E0-ACEE-A064E0232A26}
+ {2B690895-0614-4013-85D8-7FC47B956C26} = {F1517752-590B-4773-A4D6-9E670C639523}
{F749C616-5B16-4A0B-9F88-D08BEAA5F27B} = {420A3EFF-9247-407D-B58F-EC8144EB14F4}
{CE7C267E-97CF-4C7F-A5D0-B8AFC30C6130} = {420A3EFF-9247-407D-B58F-EC8144EB14F4}
- {09790598-6AD0-D698-A32D-D9A056BAF8D0} = {420A3EFF-9247-407D-B58F-EC8144EB14F4}
- {89320569-AAF8-4290-B912-699F792319F5} = {0C2B5D2F-B5EE-48E0-ACEE-A064E0232A26}
{AFC92389-71C2-BB14-10A4-CA1B415F02E9} = {420A3EFF-9247-407D-B58F-EC8144EB14F4}
- {31D599B8-9C10-410E-9ACD-0F2201C2BD4E} = {0C2B5D2F-B5EE-48E0-ACEE-A064E0232A26}
+ {31D599B8-9C10-410E-9ACD-0F2201C2BD4E} = {F3ABDB5B-F5E0-43DE-898B-4170F6852893}
{93D57E51-3F79-19CF-B65F-08600B130F57} = {420A3EFF-9247-407D-B58F-EC8144EB14F4}
+ {09790598-6AD0-D698-A32D-D9A056BAF8D0} = {420A3EFF-9247-407D-B58F-EC8144EB14F4}
+ {F1517752-590B-4773-A4D6-9E670C639523} = {0C2B5D2F-B5EE-48E0-ACEE-A064E0232A26}
+ {F3ABDB5B-F5E0-43DE-898B-4170F6852893} = {0C2B5D2F-B5EE-48E0-ACEE-A064E0232A26}
+ {38B3C54C-1AED-42E7-A510-0734DF5A7B8F} = {F1517752-590B-4773-A4D6-9E670C639523}
+ {71A15B05-FF1A-8D1F-0833-4F72927CEC48} = {F1517752-590B-4773-A4D6-9E670C639523}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {7B487365-BA97-49F1-93FD-C12DB361C20B}
diff --git a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/ApiExtensions.cs b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/ApiExtensions.cs
index 8283470..88bc600 100644
--- a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/ApiExtensions.cs
+++ b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/ApiExtensions.cs
@@ -1,14 +1,13 @@
-using Microsoft.Extensions.DependencyInjection;
-
namespace Faura.Infrastructure.ApiBootstrapper.Extensions;
+using Microsoft.Extensions.DependencyInjection;
+
public static class ApiExtensions
{
///
/// Configures controllers.
///
/// services.
- ///
public static IMvcBuilder ConfigureControllers(this IServiceCollection services) =>
services.AddControllers();
}
diff --git a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/ConfigurationExtensions.cs b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/ConfigurationExtensions.cs
index 71c0402..73956eb 100644
--- a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/ConfigurationExtensions.cs
+++ b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/ConfigurationExtensions.cs
@@ -1,8 +1,8 @@
-using Faura.Configurations;
-using Microsoft.Extensions.Configuration;
-
namespace Faura.Infrastructure.ApiBootstrapper.Extensions;
+using Faura.Infrastructure.Common.Models;
+using Microsoft.Extensions.Configuration;
+
public static class ConfigurationExtensions
{
public static void ConfigureUserSecrets(this IConfigurationBuilder configBuilder)
diff --git a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/HeadersPropagationExtensions.cs b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/HeadersPropagationExtensions.cs
index 0538053..f639345 100644
--- a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/HeadersPropagationExtensions.cs
+++ b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/HeadersPropagationExtensions.cs
@@ -1,22 +1,21 @@
-using Microsoft.AspNetCore.Builder;
+namespace Faura.Infrastructure.ApiBootstrapper.Extensions;
+
+using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
-namespace Faura.Infrastructure.ApiBootstrapper.Extensions;
-
public static class HeadersPropagationExtensions
{
public const string CorrelationIdHeaderKey = "x-correlation-id";
public static void AddHeadersPropagation(
this WebApplicationBuilder builder,
- IConfiguration config
- ) => builder.Services.AddHeadersPropagation(config);
+ IConfiguration config)
+ => builder.Services.AddHeadersPropagation(config);
public static IServiceCollection AddHeadersPropagation(
this IServiceCollection services,
- IConfiguration config
- )
+ IConfiguration config)
{
services.AddHeaderPropagation(options =>
{
diff --git a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/SwaggerExtension.cs b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/SwaggerExtension.cs
index fd7cf3b..706dc27 100644
--- a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/SwaggerExtension.cs
+++ b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/SwaggerExtension.cs
@@ -1,15 +1,15 @@
-using Faura.Configurations;
+namespace Faura.Infrastructure.ApiBootstrapper.Extensions;
+
using Faura.Infrastructure.ApiBootstrapper.Swagger.Authentication.ApiKey;
using Faura.Infrastructure.ApiBootstrapper.Swagger.Authentication.BasicAuth;
using Faura.Infrastructure.ApiBootstrapper.Swagger.Authentication.Bearer;
using Faura.Infrastructure.ApiBootstrapper.Swagger.Authentication.OAuth2;
+using Faura.Infrastructure.Common.Models;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Swashbuckle.AspNetCore.SwaggerGen;
-namespace Faura.Infrastructure.ApiBootstrapper.Extensions;
-
public static class SwaggerExtensions
{
///
@@ -29,8 +29,7 @@ public static void ConfigureUseSwagger(this IApplicationBuilder app)
public static IServiceCollection SetUpSwagger(
this IServiceCollection services,
- IConfiguration configuration
- )
+ IConfiguration configuration)
{
if (FauraEnvironment.IsProduction)
{
@@ -49,13 +48,10 @@ IConfiguration configuration
private static SwaggerGenOptions AddSwaggerSecurityConfigurations(
this SwaggerGenOptions options,
- IConfiguration configuration
- )
- {
- return options
+ IConfiguration configuration)
+ => options
.AddOAuth2Authentication(configuration)
.AddBearerAuthentication(configuration)
.AddBasicAuthentication(configuration)
.AddApiKeyAuthentication(configuration);
- }
}
diff --git a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/WebApplicationBuilderExtensions.cs b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/WebApplicationBuilderExtensions.cs
index 1089e15..b3255ad 100644
--- a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/WebApplicationBuilderExtensions.cs
+++ b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/WebApplicationBuilderExtensions.cs
@@ -1,15 +1,14 @@
-using Microsoft.AspNetCore.Builder;
+namespace Faura.Infrastructure.ApiBootstrapper.Extensions;
+
+using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
-namespace Faura.Infrastructure.ApiBootstrapper.Extensions;
-
public static class WebApplicationBuilderExtensions
{
public static WebApplicationBuilder BootstrapCommonFauraServices(
- this WebApplicationBuilder builder
- )
+ this WebApplicationBuilder builder)
{
builder.Services.ConfigureControllers();
diff --git a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/WebApplicationExtensions.cs b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/WebApplicationExtensions.cs
index fd32aaa..2091220 100644
--- a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/WebApplicationExtensions.cs
+++ b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Extensions/WebApplicationExtensions.cs
@@ -1,8 +1,8 @@
-using Faura.Infrastructure.ApiBootstrapper.Middlewares;
-using Microsoft.AspNetCore.Builder;
-
namespace Faura.Infrastructure.ApiBootstrapper.Extensions;
+using Faura.Infrastructure.ApiBootstrapper.Middlewares;
+using Microsoft.AspNetCore.Builder;
+
public static class WebApplicationExtensions
{
public static WebApplication ConfigureCommonFauraWebApplication(this WebApplication app)
diff --git a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Faura.Infrastructure.ApiBootstrapper.csproj b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Faura.Infrastructure.ApiBootstrapper.csproj
index 33e005c..69022d8 100644
--- a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Faura.Infrastructure.ApiBootstrapper.csproj
+++ b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Faura.Infrastructure.ApiBootstrapper.csproj
@@ -1,5 +1,5 @@
-
+
net8.0
enable
@@ -17,13 +17,22 @@
-
-
-
+
+
+
+
+
+
+
+
+ **/**/*.cs
+
+
+
True
@@ -34,5 +43,5 @@
\
-
+
diff --git a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Middlewares/CorrelationId/CorrelationIdMiddleware.cs b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Middlewares/CorrelationId/CorrelationIdMiddleware.cs
index 4cd4371..5a641bd 100644
--- a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Middlewares/CorrelationId/CorrelationIdMiddleware.cs
+++ b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Middlewares/CorrelationId/CorrelationIdMiddleware.cs
@@ -1,9 +1,9 @@
-using Faura.Infrastructure.ApiBootstrapper.Extensions;
+namespace Faura.Infrastructure.ApiBootstrapper.Middlewares.CorrelationId;
+
+using Faura.Infrastructure.ApiBootstrapper.Extensions;
using Microsoft.AspNetCore.HeaderPropagation;
using Microsoft.AspNetCore.Http;
-namespace Faura.Infrastructure.ApiBootstrapper.Middlewares.CorrelationId;
-
public class CorrelationIdMiddleware
{
private readonly RequestDelegate _next;
@@ -11,14 +11,13 @@ public class CorrelationIdMiddleware
public CorrelationIdMiddleware(
RequestDelegate next,
- HeaderPropagationValues headerPropagationValues
- )
+ HeaderPropagationValues headerPropagationValues)
{
_next = next;
_headerPropagationValues = headerPropagationValues;
}
- public async Task InvokeAsync(HttpContext context)
+ public Task InvokeAsync(HttpContext context)
{
var correlationId = context
.Request.Headers[HeadersPropagationExtensions.CorrelationIdHeaderKey]
@@ -28,12 +27,10 @@ public async Task InvokeAsync(HttpContext context)
correlationId = Guid.NewGuid().ToString();
context.Request.Headers.TryAdd(
HeadersPropagationExtensions.CorrelationIdHeaderKey,
- correlationId
- );
+ correlationId);
_headerPropagationValues.Headers!.TryAdd(
HeadersPropagationExtensions.CorrelationIdHeaderKey,
- correlationId
- );
+ correlationId);
}
var responseHeader = context
@@ -43,10 +40,9 @@ public async Task InvokeAsync(HttpContext context)
{
context.Response.Headers.TryAdd(
HeadersPropagationExtensions.CorrelationIdHeaderKey,
- correlationId
- );
+ correlationId);
}
- await _next(context);
+ return _next(context);
}
}
diff --git a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Middlewares/MiddlewareConfiguration.cs b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Middlewares/MiddlewareConfiguration.cs
index 2765988..7f9504d 100644
--- a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Middlewares/MiddlewareConfiguration.cs
+++ b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Middlewares/MiddlewareConfiguration.cs
@@ -1,12 +1,10 @@
-using Faura.Infrastructure.ApiBootstrapper.Middlewares.CorrelationId;
-using Microsoft.AspNetCore.Builder;
-
namespace Faura.Infrastructure.ApiBootstrapper.Middlewares;
+using Faura.Infrastructure.ApiBootstrapper.Middlewares.CorrelationId;
+using Microsoft.AspNetCore.Builder;
+
public static class MiddlewareConfiguration
{
public static void ConfigureMiddlewares(this IApplicationBuilder app)
- {
- app.UseMiddleware();
- }
+ => app.UseMiddleware();
}
diff --git a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/ApiKey/ApiKeyExtensions.cs b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/ApiKey/ApiKeyExtensions.cs
index 988f01d..2c5aff5 100644
--- a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/ApiKey/ApiKeyExtensions.cs
+++ b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/ApiKey/ApiKeyExtensions.cs
@@ -1,16 +1,15 @@
-using Microsoft.Extensions.Configuration;
+namespace Faura.Infrastructure.ApiBootstrapper.Swagger.Authentication.ApiKey;
+
+using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
-namespace Faura.Infrastructure.ApiBootstrapper.Swagger.Authentication.ApiKey;
-
public static class ApiKeyExtensions
{
public static SwaggerGenOptions AddApiKeyAuthentication(
this SwaggerGenOptions options,
- IConfiguration configuration
- )
+ IConfiguration configuration)
{
var apiKeyOptions = configuration
.GetSection(ApiKeyOptions.SectionName)
@@ -27,8 +26,7 @@ IConfiguration configuration
Name = apiKeyOptions.Name,
In = apiKeyOptions.In,
Description = "API Key Authentication",
- }
- );
+ });
options.AddSecurityRequirement(
new OpenApiSecurityRequirement
@@ -44,8 +42,7 @@ IConfiguration configuration
},
new List()
},
- }
- );
+ });
return options;
}
diff --git a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/ApiKey/ApiKeyOptions.cs b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/ApiKey/ApiKeyOptions.cs
index a804272..0d6cc1b 100644
--- a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/ApiKey/ApiKeyOptions.cs
+++ b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/ApiKey/ApiKeyOptions.cs
@@ -1,7 +1,7 @@
-using Microsoft.OpenApi.Models;
-
namespace Faura.Infrastructure.ApiBootstrapper.Swagger.Authentication.ApiKey;
+using Microsoft.OpenApi.Models;
+
public class ApiKeyOptions
{
public const string SectionName = "Swagger:Authentication:ApiKey";
diff --git a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/BasicAuth/BasicAuthExtensions.cs b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/BasicAuth/BasicAuthExtensions.cs
index 675f674..943ce6b 100644
--- a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/BasicAuth/BasicAuthExtensions.cs
+++ b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/BasicAuth/BasicAuthExtensions.cs
@@ -1,16 +1,15 @@
-using Microsoft.Extensions.Configuration;
+namespace Faura.Infrastructure.ApiBootstrapper.Swagger.Authentication.BasicAuth;
+
+using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
-namespace Faura.Infrastructure.ApiBootstrapper.Swagger.Authentication.BasicAuth;
-
public static class BasicAuthExtensions
{
public static SwaggerGenOptions AddBasicAuthentication(
this SwaggerGenOptions options,
- IConfiguration configuration
- )
+ IConfiguration configuration)
{
var basicAuthOptions = configuration
.GetSection(BasicAuthOptions.SectionName)
@@ -21,14 +20,13 @@ IConfiguration configuration
// Security Definition
options.AddSecurityDefinition(
- basicAuthOptions.Name,
+ basicAuthOptions!.Name,
new OpenApiSecurityScheme
{
Type = SecuritySchemeType.Http,
Scheme = "basic",
Description = "Basic Authentication",
- }
- );
+ });
// Security Requirement
options.AddSecurityRequirement(
@@ -45,8 +43,7 @@ IConfiguration configuration
},
new List()
},
- }
- );
+ });
return options;
}
diff --git a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/BasicAuth/BasicAuthOptions.cs b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/BasicAuth/BasicAuthOptions.cs
index ec55c56..5ed0e2e 100644
--- a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/BasicAuth/BasicAuthOptions.cs
+++ b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/BasicAuth/BasicAuthOptions.cs
@@ -1,4 +1,4 @@
-namespace Faura.Infrastructure.ApiBootstrapper.Swagger.Authentication.BasicAuth;
+namespace Faura.Infrastructure.ApiBootstrapper.Swagger.Authentication.BasicAuth;
public class BasicAuthOptions
{
diff --git a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/Bearer/BearerExtensions.cs b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/Bearer/BearerExtensions.cs
index c88990a..5f5ff7b 100644
--- a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/Bearer/BearerExtensions.cs
+++ b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/Bearer/BearerExtensions.cs
@@ -1,16 +1,15 @@
-using Microsoft.Extensions.Configuration;
+namespace Faura.Infrastructure.ApiBootstrapper.Swagger.Authentication.Bearer;
+
+using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
-namespace Faura.Infrastructure.ApiBootstrapper.Swagger.Authentication.Bearer;
-
public static class BearerExtensions
{
public static SwaggerGenOptions AddBearerAuthentication(
this SwaggerGenOptions options,
- IConfiguration configuration
- )
+ IConfiguration configuration)
{
var bearerOptions = configuration
.GetSection(BearerOptions.SectionName)
@@ -30,8 +29,7 @@ IConfiguration configuration
BearerFormat = "JWT",
In = ParameterLocation.Header,
Description = "JWT Authorization header using the Bearer scheme.",
- }
- );
+ });
// Security Requirement
var requirement = new OpenApiSecurityRequirement
diff --git a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/OAuth2/OAuth2Extensions.cs b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/OAuth2/OAuth2Extensions.cs
index 706b125..a328beb 100644
--- a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/OAuth2/OAuth2Extensions.cs
+++ b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/OAuth2/OAuth2Extensions.cs
@@ -1,16 +1,15 @@
-using Microsoft.Extensions.Configuration;
+namespace Faura.Infrastructure.ApiBootstrapper.Swagger.Authentication.OAuth2;
+
+using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
-namespace Faura.Infrastructure.ApiBootstrapper.Swagger.Authentication.OAuth2;
-
public static class OAuth2Extensions
{
public static SwaggerGenOptions AddOAuth2Authentication(
this SwaggerGenOptions options,
- IConfiguration configuration
- )
+ IConfiguration configuration)
{
var oauth2Options = configuration
.GetSection(OAuth2Options.SectionName)
@@ -21,7 +20,7 @@ IConfiguration configuration
// Security Definition
options.AddSecurityDefinition(
- oauth2Options.Name,
+ oauth2Options!.Name,
new OpenApiSecurityScheme
{
Type = SecuritySchemeType.OAuth2,
@@ -29,12 +28,11 @@ IConfiguration configuration
{
Implicit = new OpenApiOAuthFlow
{
- AuthorizationUrl = new Uri(oauth2Options.AuthenticationURL),
+ AuthorizationUrl = new Uri(oauth2Options.AuthenticationURL!),
Scopes = oauth2Options.Scopes,
},
},
- }
- );
+ });
// Security Requirement
var requirement = new OpenApiSecurityRequirement
diff --git a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/OAuth2/OAuth2Options.cs b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/OAuth2/OAuth2Options.cs
index 64ce93a..58bb9ff 100644
--- a/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/OAuth2/OAuth2Options.cs
+++ b/src/Modules/Faura.Infrastructure.ApiBootstrapper/Swagger/Authentication/OAuth2/OAuth2Options.cs
@@ -1,12 +1,12 @@
-namespace Faura.Infrastructure.ApiBootstrapper.Swagger.Authentication.OAuth2;
+namespace Faura.Infrastructure.ApiBootstrapper.Swagger.Authentication.OAuth2;
public class OAuth2Options
{
public const string SectionName = "Swagger:Authentication:OAuth2";
public bool Enable { get; set; } = false;
- public string Name { get; set; }
- public string AuthenticationURL { get; set; }
+ public string? Name { get; set; }
+ public string? AuthenticationURL { get; set; }
public Dictionary Scopes { get; set; } =
- new() { { "openid", "openid" }, { "profile", "profile" } };
+ new () { { "openid", "openid" }, { "profile", "profile" } };
}
diff --git a/src/Modules/Faura.Infrastructure.Common/Faura.Infrastructure.Common.csproj b/src/Modules/Faura.Infrastructure.Common/Faura.Infrastructure.Common.csproj
index afd0134..969efbf 100644
--- a/src/Modules/Faura.Infrastructure.Common/Faura.Infrastructure.Common.csproj
+++ b/src/Modules/Faura.Infrastructure.Common/Faura.Infrastructure.Common.csproj
@@ -1,5 +1,5 @@
-
+
net8.0
enable
@@ -22,6 +22,12 @@
+
+
+ **/**/*.cs
+
+
+
True
@@ -32,4 +38,5 @@
\
+
diff --git a/src/Modules/Faura.Infrastructure.Common/Models/FauraEnvironment.cs b/src/Modules/Faura.Infrastructure.Common/Models/FauraEnvironment.cs
index 9424115..eb82fa1 100644
--- a/src/Modules/Faura.Infrastructure.Common/Models/FauraEnvironment.cs
+++ b/src/Modules/Faura.Infrastructure.Common/Models/FauraEnvironment.cs
@@ -1,5 +1,4 @@
-namespace Faura.Configurations;
-
+namespace Faura.Infrastructure.Common.Models;
public enum FauraDeploymentMode
{
Local,
@@ -12,8 +11,8 @@ public enum FauraDeploymentMode
public static class FauraEnvironment
{
- private static FauraDeploymentMode? _currentMode;
private const string FauraEnvVariableName = "FAURA_ENVIRONMENT";
+ private static FauraDeploymentMode? _currentMode;
public static FauraDeploymentMode CurrentMode => _currentMode ??= DetectMode();
diff --git a/src/Modules/Faura.Infrastructure.Common/Utils/FileUtils.cs b/src/Modules/Faura.Infrastructure.Common/Utils/FileUtils.cs
index d7aa150..657d159 100644
--- a/src/Modules/Faura.Infrastructure.Common/Utils/FileUtils.cs
+++ b/src/Modules/Faura.Infrastructure.Common/Utils/FileUtils.cs
@@ -1,10 +1,10 @@
-using System.Reflection;
-
namespace Faura.Infrastructure.Common.Utils;
+using System.Reflection;
+
public static class FileUtils
{
- private static string? AapplicationDirectory;
+ private static string? applicationDirectory;
public static List SearchFiles(string pattern, string baseDirectory = "")
{
@@ -27,16 +27,11 @@ public static List SearchFiles(string pattern, string baseDirectory = ""
}
public static string? GetApplicationDirectory()
- {
- return AapplicationDirectory ??= Path.GetDirectoryName(
- Assembly.GetEntryAssembly()?.Location
- );
- }
+ => applicationDirectory ??= Path.GetDirectoryName(
+ Assembly.GetEntryAssembly()?.Location);
private static string ResolveDirectory(string baseDirectory)
- {
- return !string.IsNullOrWhiteSpace(baseDirectory) && Directory.Exists(baseDirectory)
+ => !string.IsNullOrWhiteSpace(baseDirectory) && Directory.Exists(baseDirectory)
? baseDirectory
: Directory.GetCurrentDirectory();
- }
}
diff --git a/src/Modules/Faura.Infrastructure.Common/Utils/OptionUtils.cs b/src/Modules/Faura.Infrastructure.Common/Utils/OptionUtils.cs
index 2633acd..0b53a54 100644
--- a/src/Modules/Faura.Infrastructure.Common/Utils/OptionUtils.cs
+++ b/src/Modules/Faura.Infrastructure.Common/Utils/OptionUtils.cs
@@ -1,16 +1,15 @@
-using Microsoft.Extensions.Configuration;
+namespace Faura.Infrastructure.Common.Utils;
+
+using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
-namespace Faura.Infrastructure.Common.Utils;
-
public static class OptionUtils
{
public static T? GetTypedOptions(
this IServiceCollection services,
IConfiguration configuration,
- string sectionName
- )
+ string sectionName)
where T : class, new()
{
if (configuration == null || string.IsNullOrWhiteSpace(sectionName))
diff --git a/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Extensions/ConfigurationExtensions.cs b/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Extensions/ConfigurationExtensions.cs
index e83571d..5ad0189 100644
--- a/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Extensions/ConfigurationExtensions.cs
+++ b/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Extensions/ConfigurationExtensions.cs
@@ -1,8 +1,8 @@
-using Faura.Configurations;
-using Microsoft.Extensions.Configuration;
-
namespace Faura.Infrastructure.GrpcBootstrapper.Extensions;
+using Faura.Infrastructure.Common.Models;
+using Microsoft.Extensions.Configuration;
+
public static class ConfigurationExtensions
{
public static void ConfigureUserSecrets(this IConfigurationBuilder configBuilder)
diff --git a/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Extensions/HeadersPropagationExtensions.cs b/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Extensions/HeadersPropagationExtensions.cs
index 3d4cf74..11c45e7 100644
--- a/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Extensions/HeadersPropagationExtensions.cs
+++ b/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Extensions/HeadersPropagationExtensions.cs
@@ -1,27 +1,19 @@
-using Microsoft.AspNetCore.Builder;
-using Microsoft.Extensions.Configuration;
-using Microsoft.Extensions.DependencyInjection;
-
namespace Faura.Infrastructure.GrpcBootstrapper.Extensions;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.Extensions.DependencyInjection;
+
public static class HeadersPropagationExtensions
{
public const string CorrelationIdHeaderKey = "x-correlation-id";
public static void AddHeadersPropagation(
- this WebApplicationBuilder builder,
- IConfiguration config
- ) => builder.Services.AddHeadersPropagation(config);
+ this WebApplicationBuilder builder) => builder.Services.AddHeadersPropagation();
public static IServiceCollection AddHeadersPropagation(
- this IServiceCollection services,
- IConfiguration config
- )
+ this IServiceCollection services)
{
- services.AddHeaderPropagation(options =>
- {
- options.Headers.Add(CorrelationIdHeaderKey);
- });
+ services.AddHeaderPropagation(options => options.Headers.Add(CorrelationIdHeaderKey));
return services;
}
}
diff --git a/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Extensions/WebApplicationBuilderExtensions.cs b/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Extensions/WebApplicationBuilderExtensions.cs
index 38a7f03..6c2f453 100644
--- a/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Extensions/WebApplicationBuilderExtensions.cs
+++ b/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Extensions/WebApplicationBuilderExtensions.cs
@@ -1,23 +1,19 @@
-using Faura.Infrastructure.GrpcBootstrapper.Interceptors;
+namespace Faura.Infrastructure.GrpcBootstrapper.Extensions;
+
+using Faura.Infrastructure.GrpcBootstrapper.Interceptors;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
-namespace Faura.Infrastructure.GrpcBootstrapper.Extensions;
-
public static class WebApplicationBuilderExtensions
{
public static WebApplicationBuilder BootstrapCommonFauraServices(
- this WebApplicationBuilder builder
- )
+ this WebApplicationBuilder builder)
{
- builder.Services.AddGrpc(options =>
- {
- options.Interceptors.Add();
- });
+ builder.Services.AddGrpc(options => options.Interceptors.Add());
- builder.Services.AddHeadersPropagation(builder.Configuration);
+ builder.Services.AddHeadersPropagation();
return builder;
}
diff --git a/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Extensions/WebApplicationExtensions.cs b/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Extensions/WebApplicationExtensions.cs
index 0cb7e3d..f6a8ff7 100644
--- a/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Extensions/WebApplicationExtensions.cs
+++ b/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Extensions/WebApplicationExtensions.cs
@@ -1,23 +1,19 @@
-using Microsoft.AspNetCore.Builder;
-using Microsoft.AspNetCore.Routing;
-
namespace Faura.Infrastructure.GrpcBootstrapper.Extensions;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Routing;
+
public static class WebApplicationExtensions
{
public static IApplicationBuilder ConfigureCommonFauraWebApplication(
this IApplicationBuilder app,
- Action mapGrpcServices
- )
+ Action mapGrpcServices)
{
app.UseRouting();
app.UseHeaderPropagation();
- app.UseEndpoints(endpoints =>
- {
- mapGrpcServices(endpoints);
- });
+ app.UseEndpoints(endpoints => mapGrpcServices(endpoints));
return app;
}
diff --git a/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Faura.Infrastructure.GrpcBootstrapper.csproj b/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Faura.Infrastructure.GrpcBootstrapper.csproj
index 5fe256f..246f0c9 100644
--- a/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Faura.Infrastructure.GrpcBootstrapper.csproj
+++ b/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Faura.Infrastructure.GrpcBootstrapper.csproj
@@ -1,5 +1,5 @@
-
+
net8.0
enable
@@ -18,10 +18,19 @@
-
-
+
+
+
+
+
+
+
+ **/**/*.cs
+
+
+
True
@@ -32,5 +41,5 @@
\
-
+
diff --git a/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Interceptors/CorrelationIdInterceptor.cs b/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Interceptors/CorrelationIdInterceptor.cs
index c1339d9..7f0485f 100644
--- a/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Interceptors/CorrelationIdInterceptor.cs
+++ b/src/Modules/Faura.Infrastructure.GrpcBootstrapper/Interceptors/CorrelationIdInterceptor.cs
@@ -1,24 +1,21 @@
-using Grpc.Core;
+namespace Faura.Infrastructure.GrpcBootstrapper.Interceptors;
+
+using Grpc.Core;
using Grpc.Core.Interceptors;
using Microsoft.AspNetCore.HeaderPropagation;
-namespace Faura.Infrastructure.GrpcBootstrapper.Interceptors;
-
public class CorrelationIdInterceptor : Interceptor
{
- private readonly HeaderPropagationValues _headerPropagationValues;
private const string HeaderKey = "x-correlation-id";
+ private readonly HeaderPropagationValues _headerPropagationValues;
public CorrelationIdInterceptor(HeaderPropagationValues headerPropagationValues)
- {
- _headerPropagationValues = headerPropagationValues;
- }
+ => _headerPropagationValues = headerPropagationValues;
- public override async Task UnaryServerHandler(
+ public override Task UnaryServerHandler(
TRequest request,
ServerCallContext context,
- UnaryServerMethod continuation
- )
+ UnaryServerMethod continuation)
{
var correlationId = context.RequestHeaders.GetValue(HeaderKey) ?? Guid.NewGuid().ToString();
@@ -26,6 +23,6 @@ UnaryServerMethod continuation
context.ResponseTrailers.Add(HeaderKey, correlationId);
- return await continuation(request, context);
+ return continuation(request, context);
}
}
diff --git a/src/Modules/Faura.Infrastructure.JWT/Extensions/ServiceCollectionExtensions.cs b/src/Modules/Faura.Infrastructure.JWT/Extensions/ServiceCollectionExtensions.cs
index 06e0656..b0b6690 100644
--- a/src/Modules/Faura.Infrastructure.JWT/Extensions/ServiceCollectionExtensions.cs
+++ b/src/Modules/Faura.Infrastructure.JWT/Extensions/ServiceCollectionExtensions.cs
@@ -1,23 +1,21 @@
-using Faura.Infrastructure.Common.Utils;
+namespace Faura.Infrastructure.JWT.Extensions;
+
+using Faura.Infrastructure.Common.Utils;
using Faura.Infrastructure.JWT.Options;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
-namespace Faura.Infrastructure.JWT.Extensions;
-
public static class ServiceCollectionExtensions
{
public static IServiceCollection SetUpJwt(
this IServiceCollection services,
- IConfiguration configuration
- )
+ IConfiguration configuration)
{
var jwtOptions = services.GetTypedOptions(
configuration,
- JwtOptions.SectionName
- );
+ JwtOptions.SectionName);
services.AddAuthorization();
services
diff --git a/src/Modules/Faura.Infrastructure.JWT/Faura.Infrastructure.JWT.csproj b/src/Modules/Faura.Infrastructure.JWT/Faura.Infrastructure.JWT.csproj
index 169a8d1..1003781 100644
--- a/src/Modules/Faura.Infrastructure.JWT/Faura.Infrastructure.JWT.csproj
+++ b/src/Modules/Faura.Infrastructure.JWT/Faura.Infrastructure.JWT.csproj
@@ -1,5 +1,5 @@
-
+
net8.0
enable
@@ -16,9 +16,18 @@
-
+
+
+
+
+
+
+
+ **/**/*.cs
+
+
@@ -30,5 +39,5 @@
\
-
+
diff --git a/src/Modules/Faura.Infrastructure.Logger/Enrichers/ConfigureLogEnrichers.cs b/src/Modules/Faura.Infrastructure.Logger/Enrichers/ConfigureLogEnrichers.cs
index 9ea5424..9b5827e 100644
--- a/src/Modules/Faura.Infrastructure.Logger/Enrichers/ConfigureLogEnrichers.cs
+++ b/src/Modules/Faura.Infrastructure.Logger/Enrichers/ConfigureLogEnrichers.cs
@@ -1,4 +1,4 @@
-namespace Faura.Infrastructure.Logger.Enrichers;
+namespace Faura.Infrastructure.Logger.Enrichers;
using Microsoft.Extensions.Configuration;
using Serilog;
@@ -11,7 +11,7 @@ public static LoggerConfiguration ConfigureLogEnrichers(this LoggerConfiguration
var loggingOptions = configuration.GetSection(LoggingOptions.SectionName).Get();
return loggerConfiguration
- .Enrich.WithProperty("ApplicationName", loggingOptions.ApplicationName)
+ .Enrich.WithProperty("ApplicationName", loggingOptions!.ApplicationName)
.Enrich.With(new CorrelationIdEnricher());
}
}
diff --git a/src/Modules/Faura.Infrastructure.Logger/Enrichers/CorrelationIdEnricher.cs b/src/Modules/Faura.Infrastructure.Logger/Enrichers/CorrelationIdEnricher.cs
index 9671625..de88be3 100644
--- a/src/Modules/Faura.Infrastructure.Logger/Enrichers/CorrelationIdEnricher.cs
+++ b/src/Modules/Faura.Infrastructure.Logger/Enrichers/CorrelationIdEnricher.cs
@@ -1,4 +1,4 @@
-namespace Faura.Infrastructure.Logger.Enrichers;
+namespace Faura.Infrastructure.Logger.Enrichers;
using Microsoft.AspNetCore.HeaderPropagation;
using Serilog.Core;
@@ -10,7 +10,10 @@ public class CorrelationIdEnricher : ILogEventEnricher
private const string HeaderKey = "x-correlation-id";
private readonly HeaderPropagationValues _headerPropagationValues;
- public CorrelationIdEnricher() : this(new HeaderPropagationValues()) { }
+ public CorrelationIdEnricher()
+ : this(new HeaderPropagationValues())
+ {
+ }
public CorrelationIdEnricher(HeaderPropagationValues headerPropagationValues) => _headerPropagationValues = headerPropagationValues;
diff --git a/src/Modules/Faura.Infrastructure.Logger/Faura.Infrastructure.Logger.csproj b/src/Modules/Faura.Infrastructure.Logger/Faura.Infrastructure.Logger.csproj
index 1f6de5f..fe26329 100644
--- a/src/Modules/Faura.Infrastructure.Logger/Faura.Infrastructure.Logger.csproj
+++ b/src/Modules/Faura.Infrastructure.Logger/Faura.Infrastructure.Logger.csproj
@@ -16,16 +16,25 @@
-
-
+
-
+
+
+
+
+
+
+
+ **/**/*.cs
+
+
+
True
diff --git a/src/Modules/Faura.Infrastructure.Logger/LoggingConfiguration.cs b/src/Modules/Faura.Infrastructure.Logger/LoggingConfiguration.cs
index b694a58..b81471c 100644
--- a/src/Modules/Faura.Infrastructure.Logger/LoggingConfiguration.cs
+++ b/src/Modules/Faura.Infrastructure.Logger/LoggingConfiguration.cs
@@ -13,6 +13,7 @@ namespace Faura.Infrastructure.Logger;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Faura.Infrastructure.Logger.Options;
+using Faura.Infrastructure.Logger.Outputs.Seq;
public static class LoggingConfiguration
{
@@ -56,4 +57,4 @@ public static LoggerConfiguration ConfigureFauraLogging(
return loggerConfiguration;
}
-}
\ No newline at end of file
+}
diff --git a/src/Modules/Faura.Infrastructure.Logger/Options/LoggingOptions.cs b/src/Modules/Faura.Infrastructure.Logger/Options/LoggingOptions.cs
index 86457d8..e8e418f 100644
--- a/src/Modules/Faura.Infrastructure.Logger/Options/LoggingOptions.cs
+++ b/src/Modules/Faura.Infrastructure.Logger/Options/LoggingOptions.cs
@@ -1,8 +1,8 @@
-namespace Faura.Infrastructure.Logger.Options
+namespace Faura.Infrastructure.Logger.Options
{
public class LoggingOptions
{
public const string SectionName = "Logging";
- public string ApplicationName { get; set; }
+ public string? ApplicationName { get; set; }
}
}
diff --git a/src/Modules/Faura.Infrastructure.Logger/Outputs/Console/LogConsoleExtensions.cs b/src/Modules/Faura.Infrastructure.Logger/Outputs/Console/LogConsoleExtensions.cs
index daa5dc9..4474dda 100644
--- a/src/Modules/Faura.Infrastructure.Logger/Outputs/Console/LogConsoleExtensions.cs
+++ b/src/Modules/Faura.Infrastructure.Logger/Outputs/Console/LogConsoleExtensions.cs
@@ -1,4 +1,4 @@
-namespace Faura.Infrastructure.Logger.Outputs.Console;
+namespace Faura.Infrastructure.Logger.Outputs.Console;
using Microsoft.Extensions.Configuration;
using Serilog.Core;
@@ -8,7 +8,7 @@ public static class LogConsoleExtensions
{
public const string BaseLogTemplate = "[{Timestamp:yyyy-MM-dd HH:mm:ss} {Level:u3}] {SourceContext}: {Message:lj}{NewLine}{Exception}";
- public static LoggerConfiguration ConfigureLogConsole(this LoggerConfiguration loggerConfiguration, IConfiguration configuration, List logEnrichers = null)
+ public static LoggerConfiguration ConfigureLogConsole(this LoggerConfiguration loggerConfiguration, IConfiguration configuration, List? logEnrichers = null)
{
var consoleOptions = configuration.GetSection(LogConsoleOptions.SectionName).Get() ?? new LogConsoleOptions();
diff --git a/src/Modules/Faura.Infrastructure.Logger/Outputs/Console/LogConsoleOptions.cs b/src/Modules/Faura.Infrastructure.Logger/Outputs/Console/LogConsoleOptions.cs
index 33e1ef5..a773ae9 100644
--- a/src/Modules/Faura.Infrastructure.Logger/Outputs/Console/LogConsoleOptions.cs
+++ b/src/Modules/Faura.Infrastructure.Logger/Outputs/Console/LogConsoleOptions.cs
@@ -1,9 +1,9 @@
-namespace Faura.Infrastructure.Logger.Outputs.Console;
+namespace Faura.Infrastructure.Logger.Outputs.Console;
public class LogConsoleOptions
{
public const string SectionName = "Logging:Outputs:Console";
public bool Enable { get; set; } = false;
- public string LogTemplate { get; set; }
+ public string? LogTemplate { get; set; }
}
diff --git a/src/Modules/Faura.Infrastructure.Logger/Outputs/GrayLog/LogGraylogExtensions.cs b/src/Modules/Faura.Infrastructure.Logger/Outputs/GrayLog/LogGraylogExtensions.cs
index cdbd7f1..1d6759d 100644
--- a/src/Modules/Faura.Infrastructure.Logger/Outputs/GrayLog/LogGraylogExtensions.cs
+++ b/src/Modules/Faura.Infrastructure.Logger/Outputs/GrayLog/LogGraylogExtensions.cs
@@ -1,4 +1,4 @@
-namespace Faura.Infrastructure.Logger.Outputs.GrayLog;
+namespace Faura.Infrastructure.Logger.Outputs.GrayLog;
using Serilog.Sinks.Graylog;
using Serilog;
@@ -8,7 +8,7 @@
public static class LogGrayLogExtensions
{
- public static LoggerConfiguration ConfigureLogGraylog(this LoggerConfiguration loggerConfiguration, IConfiguration configuration, List logEnrichers = null)
+ public static LoggerConfiguration ConfigureLogGraylog(this LoggerConfiguration loggerConfiguration, IConfiguration configuration, List? logEnrichers = null)
{
var graylogOptions = configuration.GetSection(LogGraylogOptions.SectionName).Get();
@@ -17,11 +17,11 @@ public static LoggerConfiguration ConfigureLogGraylog(this LoggerConfiguration l
var graylogSinkConfig = new GraylogSinkOptions
{
HostnameOrAddress = graylogOptions.GrayLogHost,
- TransportType = GetGraylogTransportTypeFromString(graylogOptions.GrayLogProtocol),
- HostnameOverride = graylogOptions.GrayLogHost,
+ TransportType = GetGraylogTransportTypeFromString(graylogOptions.GrayLogProtocol!),
+ HostnameOverride = graylogOptions.GrayLogHost!,
Port = graylogOptions.GrayLogPort,
MaxMessageSizeInUdp = graylogOptions.MaxUdpMessageSize,
- Facility = "FauraApp"
+ Facility = "FauraApp",
};
return loggerConfiguration
diff --git a/src/Modules/Faura.Infrastructure.Logger/Outputs/GrayLog/LogGraylogOptions.cs b/src/Modules/Faura.Infrastructure.Logger/Outputs/GrayLog/LogGraylogOptions.cs
index 6f190ad..2a40857 100644
--- a/src/Modules/Faura.Infrastructure.Logger/Outputs/GrayLog/LogGraylogOptions.cs
+++ b/src/Modules/Faura.Infrastructure.Logger/Outputs/GrayLog/LogGraylogOptions.cs
@@ -1,12 +1,12 @@
-namespace Faura.Infrastructure.Logger.Outputs.GrayLog;
+namespace Faura.Infrastructure.Logger.Outputs.GrayLog;
public class LogGraylogOptions
{
public const string SectionName = "Logging:Outputs:Graylog";
public bool Enable { get; set; } = false;
- public string GrayLogHost { get; set; }
+ public string? GrayLogHost { get; set; }
public int GrayLogPort { get; set; }
- public string GrayLogProtocol { get; set; }
+ public string? GrayLogProtocol { get; set; }
public int MaxUdpMessageSize { get; set; }
}
diff --git a/src/Modules/Faura.Infrastructure.Logger/Outputs/Seq/LogSeqExtensions.cs b/src/Modules/Faura.Infrastructure.Logger/Outputs/Seq/LogSeqExtensions.cs
index 40ac89b..8eed022 100644
--- a/src/Modules/Faura.Infrastructure.Logger/Outputs/Seq/LogSeqExtensions.cs
+++ b/src/Modules/Faura.Infrastructure.Logger/Outputs/Seq/LogSeqExtensions.cs
@@ -1,4 +1,4 @@
-namespace Faura.Infrastructure.Logger.Outputs.GrayLog;
+namespace Faura.Infrastructure.Logger.Outputs.Seq;
using Serilog;
using Microsoft.Extensions.Configuration;
@@ -6,12 +6,12 @@
public static class LogSeqExtensions
{
- public static LoggerConfiguration ConfigureLogSeq(this LoggerConfiguration loggerConfiguration, IConfiguration configuration, List logEnrichers = null)
+ public static LoggerConfiguration ConfigureLogSeq(this LoggerConfiguration loggerConfiguration, IConfiguration configuration, List? logEnrichers = null)
{
var seqOptions = configuration.GetSection(LogSeqOptions.SectionName).Get() ?? new LogSeqOptions();
if (!seqOptions.Enable) return loggerConfiguration;
return loggerConfiguration
- .WriteTo.Seq(serverUrl: seqOptions.ServerUrl, apiKey: seqOptions.ApiKey);
+ .WriteTo.Seq(serverUrl: seqOptions.ServerUrl!, apiKey: seqOptions.ApiKey);
}
}
diff --git a/src/Modules/Faura.Infrastructure.Logger/Outputs/Seq/LogSeqOptions.cs b/src/Modules/Faura.Infrastructure.Logger/Outputs/Seq/LogSeqOptions.cs
index fb908d2..95cc0d2 100644
--- a/src/Modules/Faura.Infrastructure.Logger/Outputs/Seq/LogSeqOptions.cs
+++ b/src/Modules/Faura.Infrastructure.Logger/Outputs/Seq/LogSeqOptions.cs
@@ -1,12 +1,11 @@
-namespace Faura.Infrastructure.Logger.Outputs.GrayLog;
+namespace Faura.Infrastructure.Logger.Outputs.Seq;
public class LogSeqOptions
{
public const string SectionName = "Logging:Outputs:Seq";
public bool Enable { get; set; } = false;
- public string ServerUrl { get; set; }
- public string ApplicationName { get; set; }
- public string ApiKey { get; set; }
-
+ public string? ServerUrl { get; set; }
+ public string? ApplicationName { get; set; }
+ public string? ApiKey { get; set; }
}
diff --git a/src/Modules/Faura.Infrastructure.Logger/Outputs/SqLiteDb/LogSqLiteDbExtensions.cs b/src/Modules/Faura.Infrastructure.Logger/Outputs/SqLiteDb/LogSqLiteDbExtensions.cs
index 72d494c..98cd289 100644
--- a/src/Modules/Faura.Infrastructure.Logger/Outputs/SqLiteDb/LogSqLiteDbExtensions.cs
+++ b/src/Modules/Faura.Infrastructure.Logger/Outputs/SqLiteDb/LogSqLiteDbExtensions.cs
@@ -1,4 +1,4 @@
-namespace Faura.Infrastructure.Logger.Outputs.SqLiteDb;
+namespace Faura.Infrastructure.Logger.Outputs.SqLiteDb;
using Faura.Infrastructure.Common.Utils;
using Microsoft.Extensions.Configuration;
@@ -15,7 +15,7 @@ public static LoggerConfiguration ConfigureLogSqLiteDb(this LoggerConfiguration
if (!sqLiteDbOptions.Enable) return loggerConfiguration;
return loggerConfiguration
- .WriteTo.SQLite(GetSqliteDbLogFilePath(sqLiteDbOptions.LogSqLiteFile, DefaultLogSqLiteFileName));
+ .WriteTo.SQLite(GetSqliteDbLogFilePath(sqLiteDbOptions.LogSqLiteFile!, DefaultLogSqLiteFileName));
}
internal static string GetSqliteDbLogFilePath(string file, string defaultFileName)
diff --git a/src/Modules/Faura.Infrastructure.Logger/Outputs/SqLiteDb/LogSqLiteDbOptions.cs b/src/Modules/Faura.Infrastructure.Logger/Outputs/SqLiteDb/LogSqLiteDbOptions.cs
index 2faf4fc..fc09a02 100644
--- a/src/Modules/Faura.Infrastructure.Logger/Outputs/SqLiteDb/LogSqLiteDbOptions.cs
+++ b/src/Modules/Faura.Infrastructure.Logger/Outputs/SqLiteDb/LogSqLiteDbOptions.cs
@@ -1,9 +1,9 @@
-namespace Faura.Infrastructure.Logger.Outputs.SqLiteDb;
+namespace Faura.Infrastructure.Logger.Outputs.SqLiteDb;
public class LogSqLiteDbOptions
{
public const string SectionName = "Logging:Outputs:SqLiteDb";
public bool Enable { get; set; } = false;
- public string LogSqLiteFile { get; set; }
+ public string? LogSqLiteFile { get; set; }
}
diff --git a/src/Modules/Faura.Infrastructure.Result/Faura.Infrastructure.Result.csproj b/src/Modules/Faura.Infrastructure.Result/Faura.Infrastructure.Result.csproj
index b6d782e..7b2785e 100644
--- a/src/Modules/Faura.Infrastructure.Result/Faura.Infrastructure.Result.csproj
+++ b/src/Modules/Faura.Infrastructure.Result/Faura.Infrastructure.Result.csproj
@@ -16,10 +16,15 @@
-
+
+
+ **/**/*.cs
+
+
+
True
diff --git a/src/Modules/Faura.Infrastructure.Result/FauraError.cs b/src/Modules/Faura.Infrastructure.Result/FauraError.cs
index bc58773..9e06525 100644
--- a/src/Modules/Faura.Infrastructure.Result/FauraError.cs
+++ b/src/Modules/Faura.Infrastructure.Result/FauraError.cs
@@ -1,20 +1,12 @@
-namespace Faura.Infrastructure.Result;
+namespace Faura.Infrastructure.Result;
using System.Net;
-public class FauraError
+public class FauraError(string code, string message, HttpStatusCode? httpStatus = null)
{
- public string Code { get; init; }
+ public string Code { get; init; } = code;
- public string Message { get; init; }
+ public string Message { get; init; } = message;
- public HttpStatusCode HttpStatus { get; private set; }
-
- public FauraError(string code, string message, HttpStatusCode? httpStatus = null)
- {
- Code = code;
- Message = message;
- HttpStatus = httpStatus ?? HttpStatusCode.InternalServerError;
- }
-
-}
\ No newline at end of file
+ public HttpStatusCode HttpStatus { get; private set; } = httpStatus ?? HttpStatusCode.InternalServerError;
+}
diff --git a/src/Modules/Faura.Infrastructure.Result/FauraResult.cs b/src/Modules/Faura.Infrastructure.Result/FauraResult.cs
index 591825b..7f9ad6d 100644
--- a/src/Modules/Faura.Infrastructure.Result/FauraResult.cs
+++ b/src/Modules/Faura.Infrastructure.Result/FauraResult.cs
@@ -1,25 +1,24 @@
-namespace Faura.Infrastructure.Result;
+namespace Faura.Infrastructure.Result;
-using Faura.Infrastructure.Result.Helpers;
-using Microsoft.AspNetCore.Mvc;
using System.Net;
using System.Text.Json.Serialization;
+using Microsoft.AspNetCore.Mvc;
+using Faura.Infrastructure.Result.Helpers;
+using System.Collections.Generic;
+using System;
+using System.Linq;
public class FauraResult : IFauraResult
{
- protected FauraResult() { }
+ public FauraResult(T value) => Data = value;
- public FauraResult(T value)
+ protected FauraResult()
{
- Data = value;
}
- public static implicit operator T(FauraResult result) => result.Data;
- public static implicit operator FauraResult(T value) => new FauraResult(value);
-
[JsonInclude]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
- public T Data { get; init; }
+ public T? Data { get; init; }
[JsonIgnore]
public Type ValueType => typeof(T);
@@ -31,78 +30,52 @@ public FauraResult(T value)
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public IEnumerable Errors { get; protected set; } = [];
- public object GetData()
- {
- return Data;
- }
+ public static implicit operator T(FauraResult result) => result.Data!;
- public static FauraResult Success(T value)
- {
- return new FauraResult(value);
- }
+ public static implicit operator FauraResult(T value) => new(value);
- public static FauraResult Error(FauraError fauraError)
- {
- return new FauraResult() { Errors = [fauraError] };
- }
+ public static FauraResult Success(T value) => new (value);
- public static FauraResult Error(IEnumerable fauraErrors = null)
+ public static FauraResult Error(FauraError fauraError) => new()
{
- return new FauraResult()
- {
- Errors = fauraErrors
- };
- }
+ Errors = [fauraError],
+ };
- public void AddError(FauraError error)
+ public static FauraResult Error(IEnumerable? fauraErrors = null) => new()
{
- IEnumerable errors;
- if (Errors != null)
- {
- errors = Errors.Append(error);
- }
- else
- {
- errors = [];
- }
+ Errors = fauraErrors ?? [],
+ };
- Errors = errors;
- }
+ public object? GetData() => Data;
+
+ public void AddError(FauraError error)
+ => Errors = Errors.Append(error);
public IEnumerable GetErrors()
- {
- return Errors;
- }
+ => Errors;
public bool ReturnedError(FauraError errorCode)
- {
- return Errors?.Any((myError) => myError.Code == $"{errorCode}") ?? false;
- }
+ => Errors?.Any(e => e.Code == errorCode.Code) ?? false;
public bool ReturnedError(IEnumerable errorCodes)
- {
- return errorCodes.Any((errorCode) => Errors?.Any((myError) => myError.Code == $"{errorCode}") ?? false);
- }
+ => errorCodes.Any(code => Errors?.Any(e => e.Code == code.Code) ?? false);
public IActionResult BuildResult(HttpStatusCode httpStatusCode = HttpStatusCode.OK)
{
if (IsSuccess)
{
- T dataAsT = Data;
- if (dataAsT == null)
- {
+ if (EqualityComparer.Default.Equals(Data!, default!))
return new NoContentResult();
- }
- return new OkObjectResult(dataAsT)
+ return new OkObjectResult(Data)
{
StatusCode = (int)httpStatusCode,
};
-
}
+
return new ObjectResult(Errors)
{
StatusCode = Errors.ToHigherHttpStatusCode(),
};
}
-}
\ No newline at end of file
+}
diff --git a/src/Modules/Faura.Infrastructure.Result/Helpers/FauraErrorHelper.cs b/src/Modules/Faura.Infrastructure.Result/Helpers/FauraErrorHelper.cs
index 4bb2ede..998d99c 100644
--- a/src/Modules/Faura.Infrastructure.Result/Helpers/FauraErrorHelper.cs
+++ b/src/Modules/Faura.Infrastructure.Result/Helpers/FauraErrorHelper.cs
@@ -1,6 +1,4 @@
-namespace Faura.Infrastructure.Result.Helpers;
-
-using Faura.Infrastructure.Result;
+namespace Faura.Infrastructure.Result.Helpers;
public static class FauraErrorHelper
{
diff --git a/src/Modules/Faura.Infrastructure.Result/IFauraResult.cs b/src/Modules/Faura.Infrastructure.Result/IFauraResult.cs
index ccaad13..b57bad8 100644
--- a/src/Modules/Faura.Infrastructure.Result/IFauraResult.cs
+++ b/src/Modules/Faura.Infrastructure.Result/IFauraResult.cs
@@ -1,7 +1,7 @@
-namespace Faura.Infrastructure.Result;
+namespace Faura.Infrastructure.Result;
public interface IFauraResult
{
IEnumerable Errors { get; }
Type ValueType { get; }
- object GetData();
+ object? GetData();
}
diff --git a/src/Modules/Faura.Infrastructure.UnitOfWork/Common/DatabaseConfiguration.cs b/src/Modules/Faura.Infrastructure.UnitOfWork/Common/DatabaseConfiguration.cs
index 4f9575c..98c7637 100644
--- a/src/Modules/Faura.Infrastructure.UnitOfWork/Common/DatabaseConfiguration.cs
+++ b/src/Modules/Faura.Infrastructure.UnitOfWork/Common/DatabaseConfiguration.cs
@@ -1,4 +1,4 @@
-namespace Faura.Infrastructure.UnitOfWork.Common;
+namespace Faura.Infrastructure.UnitOfWork.Common;
using Faura.Infrastructure.UnitOfWork.Enums;
using Microsoft.EntityFrameworkCore;
@@ -17,7 +17,8 @@ public static void ConfigureDatabase(
this IServiceCollection services,
string connectionString,
DatabaseType databaseType,
- ServiceLifetime serviceLifetime = ServiceLifetime.Scoped) where TContext : DbContext
+ ServiceLifetime serviceLifetime = ServiceLifetime.Scoped)
+ where TContext : DbContext
{
if (string.IsNullOrWhiteSpace(connectionString))
throw new ArgumentException("Connection string cannot be null or empty.", nameof(connectionString));
@@ -31,7 +32,8 @@ public static async Task ConfigureDatabase(
string connectionStringName,
DatabaseType databaseType,
ServiceLifetime serviceLifetime = ServiceLifetime.Scoped,
- bool runMigrations = false) where TContext : DbContext
+ bool runMigrations = false)
+ where TContext : DbContext
{
var connectionString = configuration.GetConnectionString(connectionStringName)
?? throw new ArgumentException($"Connection string '{connectionStringName}' not found or is empty.");
@@ -58,7 +60,8 @@ private static void ConfigureDatabaseOptions(
break;
case DatabaseType.MySql:
- options.UseMySql(ServerVersion.AutoDetect(connectionString),
+ options.UseMySql(
+ ServerVersion.AutoDetect(connectionString),
mysqlOptions => mysqlOptions.EnableRetryOnFailure(MaxRetryCount, TimeSpan.FromSeconds(MaxRetryDelay), null));
break;
@@ -75,7 +78,8 @@ private static void ConfigureDatabaseOptions(
}
}
- private static async Task ApplyMigrations(IServiceCollection services) where TContext : DbContext
+ private static async Task ApplyMigrations(IServiceCollection services)
+ where TContext : DbContext
{
using var serviceProvider = services.BuildServiceProvider();
var logger = serviceProvider.GetService();
@@ -83,7 +87,7 @@ private static async Task ApplyMigrations(IServiceCollection services)
if (context == null)
{
- logger?.LogError($"Unable to resolve {typeof(TContext).FullName}. Database migration will not be performed.");
+ logger?.LogError("Unable to resolve {ContextType}. Database migration will not be performed.", typeof(TContext).FullName);
return;
}
@@ -93,8 +97,8 @@ private static async Task ApplyMigrations(IServiceCollection services)
}
catch (Exception ex)
{
- logger?.LogError(ex, "An error occurred while migrating the database.");
- throw;
+ string contextName = typeof(TContext).FullName ?? "UnknownContext";
+ logger?.LogError(ex, "An error occurred while migrating the database for context {ContextName}. See inner exception for details.", contextName);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/Modules/Faura.Infrastructure.UnitOfWork/Enums/SortDirection.cs b/src/Modules/Faura.Infrastructure.UnitOfWork/Enums/SortDirection.cs
index c0ee16d..6c4c552 100644
--- a/src/Modules/Faura.Infrastructure.UnitOfWork/Enums/SortDirection.cs
+++ b/src/Modules/Faura.Infrastructure.UnitOfWork/Enums/SortDirection.cs
@@ -1,7 +1,7 @@
-namespace Faura.Infrastructure.UnitOfWork.Enums;
+namespace Faura.Infrastructure.UnitOfWork.Enums;
///
-/// Direction for sorting operations
+/// Direction for sorting operations.
///
public enum SortDirection
{
@@ -13,5 +13,5 @@ public enum SortDirection
///
/// Sort in descending order
///
- Descending
-}
\ No newline at end of file
+ Descending,
+}
diff --git a/src/Modules/Faura.Infrastructure.UnitOfWork/Exceptions/NullContextException.cs b/src/Modules/Faura.Infrastructure.UnitOfWork/Exceptions/NullContextException.cs
index e3ca4fe..76293dd 100644
--- a/src/Modules/Faura.Infrastructure.UnitOfWork/Exceptions/NullContextException.cs
+++ b/src/Modules/Faura.Infrastructure.UnitOfWork/Exceptions/NullContextException.cs
@@ -1,24 +1,18 @@
-namespace Faura.Infrastructure.UnitOfWork.Exceptions;
+namespace Faura.Infrastructure.UnitOfWork.Exceptions;
-using System.Runtime.Serialization;
-
-[Serializable]
public class NullContextException : Exception
{
- public NullContextException() : base()
- {
- }
-
- public NullContextException(string message) : base(message)
+ public NullContextException()
{
}
- public NullContextException(string message, Exception innerException) : base(message, innerException)
+ public NullContextException(string message)
+ : base(message)
{
}
- protected NullContextException(SerializationInfo serializationInfo, StreamingContext streamingContext)
- : base(serializationInfo, streamingContext)
+ public NullContextException(string message, Exception innerException)
+ : base(message, innerException)
{
}
-}
\ No newline at end of file
+}
diff --git a/src/Modules/Faura.Infrastructure.UnitOfWork/Exceptions/RepositoryExceptions.cs b/src/Modules/Faura.Infrastructure.UnitOfWork/Exceptions/RepositoryExceptions.cs
index 96adabb..26386ac 100644
--- a/src/Modules/Faura.Infrastructure.UnitOfWork/Exceptions/RepositoryExceptions.cs
+++ b/src/Modules/Faura.Infrastructure.UnitOfWork/Exceptions/RepositoryExceptions.cs
@@ -1,15 +1,21 @@
-namespace Faura.Infrastructure.UnitOfWork.Exceptions;
+namespace Faura.Infrastructure.UnitOfWork.Exceptions;
///
-/// Base exception for repository-related errors
+/// Base exception for repository-related errors.
///
public abstract class RepositoryException : Exception
{
- protected RepositoryException(string message) : base(message)
+ protected RepositoryException()
{
}
- protected RepositoryException(string message, Exception innerException) : base(message, innerException)
+ protected RepositoryException(string message)
+ : base(message)
{
}
-}
\ No newline at end of file
+
+ protected RepositoryException(string message, Exception innerException)
+ : base(message, innerException)
+ {
+ }
+}
diff --git a/src/Modules/Faura.Infrastructure.UnitOfWork/Exceptions/RepositoryOperationException.cs b/src/Modules/Faura.Infrastructure.UnitOfWork/Exceptions/RepositoryOperationException.cs
index 816f198..0f9313c 100644
--- a/src/Modules/Faura.Infrastructure.UnitOfWork/Exceptions/RepositoryOperationException.cs
+++ b/src/Modules/Faura.Infrastructure.UnitOfWork/Exceptions/RepositoryOperationException.cs
@@ -1,15 +1,21 @@
-namespace Faura.Infrastructure.UnitOfWork.Exceptions;
+namespace Faura.Infrastructure.UnitOfWork.Exceptions;
///
/// Exception for errors during repository operations (create, update, delete)
///
public class RepositoryOperationException : RepositoryException
{
- public RepositoryOperationException(string message) : base(message)
+ public RepositoryOperationException()
{
}
- public RepositoryOperationException(string message, Exception innerException) : base(message, innerException)
+ public RepositoryOperationException(string message)
+ : base(message)
+ {
+ }
+
+ public RepositoryOperationException(string message, Exception innerException)
+ : base(message, innerException)
{
}
}
diff --git a/src/Modules/Faura.Infrastructure.UnitOfWork/Exceptions/RepositoryQueryException.cs b/src/Modules/Faura.Infrastructure.UnitOfWork/Exceptions/RepositoryQueryException.cs
index 81dabe5..51269ba 100644
--- a/src/Modules/Faura.Infrastructure.UnitOfWork/Exceptions/RepositoryQueryException.cs
+++ b/src/Modules/Faura.Infrastructure.UnitOfWork/Exceptions/RepositoryQueryException.cs
@@ -1,15 +1,21 @@
-namespace Faura.Infrastructure.UnitOfWork.Exceptions;
+namespace Faura.Infrastructure.UnitOfWork.Exceptions;
///
-/// Exception for errors during repository queries
+/// Exception for errors during repository queries.
///
public class RepositoryQueryException : RepositoryException
{
- public RepositoryQueryException(string message) : base(message)
+ public RepositoryQueryException()
{
}
- public RepositoryQueryException(string message, Exception innerException) : base(message, innerException)
+ public RepositoryQueryException(string message)
+ : base(message)
+ {
+ }
+
+ public RepositoryQueryException(string message, Exception innerException)
+ : base(message, innerException)
{
}
}
diff --git a/src/Modules/Faura.Infrastructure.UnitOfWork/Exceptions/TransactionNullException.cs b/src/Modules/Faura.Infrastructure.UnitOfWork/Exceptions/TransactionNullException.cs
index d7e2009..6885a3b 100644
--- a/src/Modules/Faura.Infrastructure.UnitOfWork/Exceptions/TransactionNullException.cs
+++ b/src/Modules/Faura.Infrastructure.UnitOfWork/Exceptions/TransactionNullException.cs
@@ -1,24 +1,18 @@
-namespace Faura.Infrastructure.UnitOfWork.Exceptions;
+namespace Faura.Infrastructure.UnitOfWork.Exceptions;
-using System.Runtime.Serialization;
-
-[Serializable]
public class NullTransactionException : Exception
{
- public NullTransactionException() : base()
- {
- }
-
- public NullTransactionException(string message) : base(message)
+ public NullTransactionException()
{
}
- public NullTransactionException(string message, Exception innerException) : base(message, innerException)
+ public NullTransactionException(string message)
+ : base(message)
{
}
- protected NullTransactionException(SerializationInfo serializationInfo, StreamingContext streamingContext)
- : base(serializationInfo, streamingContext)
+ public NullTransactionException(string message, Exception innerException)
+ : base(message, innerException)
{
}
-}
\ No newline at end of file
+}
diff --git a/src/Modules/Faura.Infrastructure.UnitOfWork/Faura.Infrastructure.UnitOfWork.csproj b/src/Modules/Faura.Infrastructure.UnitOfWork/Faura.Infrastructure.UnitOfWork.csproj
index 80c765b..367c237 100644
--- a/src/Modules/Faura.Infrastructure.UnitOfWork/Faura.Infrastructure.UnitOfWork.csproj
+++ b/src/Modules/Faura.Infrastructure.UnitOfWork/Faura.Infrastructure.UnitOfWork.csproj
@@ -16,14 +16,21 @@
-
-
-
+
+
+
+
+
+
+ **/**/*.cs
+
+
+
True
diff --git a/src/Modules/Faura.Infrastructure.UnitOfWork/Models/PagedResult.cs b/src/Modules/Faura.Infrastructure.UnitOfWork/Models/PagedResult.cs
index 8ca1473..9a76443 100644
--- a/src/Modules/Faura.Infrastructure.UnitOfWork/Models/PagedResult.cs
+++ b/src/Modules/Faura.Infrastructure.UnitOfWork/Models/PagedResult.cs
@@ -1,42 +1,43 @@
-namespace Faura.Infrastructure.UnitOfWork.Models;
+namespace Faura.Infrastructure.UnitOfWork.Models;
///
-/// Represents a paginated result set
+/// Represents a paginated result set.
///
-public class PagedResult where T : class
+public class PagedResult
+ where T : class
{
///
- /// Items in the current page
+ /// Gets or sets items in the current page.
///
public IList Items { get; set; } = new List();
///
- /// Current page number
+ /// Gets or sets current page number.
///
public int CurrentPage { get; set; }
///
- /// Number of items per page
+ /// Gets or sets number of items per page.
///
public int PageSize { get; set; }
///
- /// Total number of items across all pages
+ /// Gets or sets total number of items across all pages.
///
public long TotalCount { get; set; }
///
- /// Total number of pages
+ /// Gets or sets total number of pages.
///
public int TotalPages { get; set; }
///
- /// Whether a previous page exists
+ /// Gets or sets a value indicating whether whether a previous page exists.
///
public bool HasPreviousPage { get; set; }
///
- /// Whether a next page exists
+ /// Gets or sets a value indicating whether whether a next page exists.
///
public bool HasNextPage { get; set; }
-}
\ No newline at end of file
+}
diff --git a/src/Modules/Faura.Infrastructure.UnitOfWork/Projectors/IProjector.cs b/src/Modules/Faura.Infrastructure.UnitOfWork/Projectors/IProjector.cs
index 6a32df6..13d51ce 100644
--- a/src/Modules/Faura.Infrastructure.UnitOfWork/Projectors/IProjector.cs
+++ b/src/Modules/Faura.Infrastructure.UnitOfWork/Projectors/IProjector.cs
@@ -1,17 +1,18 @@
namespace Faura.Infrastructure.UnitOfWork.Projectors;
-public interface IProjector where TEntity : class
+public interface IProjector
+ where TEntity : class
{
///
- /// Gets a projection from the entity
+ /// Gets a projection from the entity.
///
- /// The result type of the projection
- /// The projection function
- /// Optional page number for pagination
- /// Optional page size for pagination
- /// A task that represents the asynchronous operation, containing the projected results
+ /// The result type of the projection.
+ /// The projection function.
+ /// Optional page number for pagination.
+ /// Optional page size for pagination.
+ /// A task that represents the asynchronous operation, containing the projected results.
Task> GetProjectionAsync(
Func, IQueryable> projection,
int? page = null,
int? pageSize = null);
-}
\ No newline at end of file
+}
diff --git a/src/Modules/Faura.Infrastructure.UnitOfWork/Projectors/Projector.cs b/src/Modules/Faura.Infrastructure.UnitOfWork/Projectors/Projector.cs
index 23ccead..e09f4d8 100644
--- a/src/Modules/Faura.Infrastructure.UnitOfWork/Projectors/Projector.cs
+++ b/src/Modules/Faura.Infrastructure.UnitOfWork/Projectors/Projector.cs
@@ -1,16 +1,14 @@
namespace Faura.Infrastructure.UnitOfWork.Projectors;
-using System.Linq.Expressions;
using Microsoft.EntityFrameworkCore;
-public class Projector : IProjector where TEntity : class
+public class Projector : IProjector
+ where TEntity : class
{
private readonly DbContext _context;
public Projector(DbContext context)
- {
- _context = context ?? throw new ArgumentNullException(nameof(context));
- }
+ => _context = context ?? throw new ArgumentNullException(nameof(context));
public async Task> GetProjectionAsync(
Func, IQueryable> projection,
@@ -28,4 +26,4 @@ public async Task> GetProjectionAsync(
var projectionQuery = projection(query);
return await projectionQuery.ToListAsync();
}
-}
\ No newline at end of file
+}
diff --git a/src/Modules/Faura.Infrastructure.UnitOfWork/Repositories/EntityRepository.cs b/src/Modules/Faura.Infrastructure.UnitOfWork/Repositories/EntityRepository.cs
index df2593c..bef44fe 100644
--- a/src/Modules/Faura.Infrastructure.UnitOfWork/Repositories/EntityRepository.cs
+++ b/src/Modules/Faura.Infrastructure.UnitOfWork/Repositories/EntityRepository.cs
@@ -1,29 +1,29 @@
-namespace Faura.Infrastructure.UnitOfWork.Repositories;
+namespace Faura.Infrastructure.UnitOfWork.Repositories;
using Faura.Infrastructure.UnitOfWork.Enums;
using Faura.Infrastructure.UnitOfWork.Exceptions;
using Faura.Infrastructure.UnitOfWork.Models;
-using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using System.Linq.Expressions;
///
-/// Generic repository implementation for data access operations
+/// Generic repository implementation for data access operations.
///
-/// The entity type this repository works with
-public class EntityRepository : IEntityRepository where TEntity : class
+/// The entity type this repository works with.
+public class EntityRepository : IEntityRepository
+ where TEntity : class
{
private readonly DbContext _dbContext;
private readonly ILogger> _logger;
private readonly bool _enableTracking;
///
- /// Creates a new instance of the repository
+ /// Initializes a new instance of the class.
///
- /// Database context to use for operations
- /// Logger for capturing operation information
- /// Whether to enable entity tracking
+ /// Database context to use for operations.
+ /// Logger for capturing operation information.
+ /// Whether to enable entity tracking.
public EntityRepository(
DbContext dbContext,
ILogger> logger,
@@ -37,7 +37,7 @@ public EntityRepository(
}
///
- /// Base queryable for this entity type
+ /// Gets base queryable for this entity type.
///
private IQueryable BaseQuery => GetBaseQuery();
@@ -212,35 +212,15 @@ public async Task> DeleteRangeAsync(IEnumerable en
}
///
- public Task GetFirstOrDefaultAsync(Expression> predicate = null)
- {
- try
- {
- return ApplyPredicate(predicate).FirstOrDefaultAsync();
- }
- catch (Exception ex)
- {
- _logger.LogError(ex, "Error retrieving first entity of type {EntityType}", typeof(TEntity).Name);
- throw new RepositoryQueryException($"Failed to retrieve first entity: {ex.Message}", ex);
- }
- }
+ public Task GetFirstOrDefaultAsync(Expression>? predicate = null)
+ => ApplyPredicate(predicate).FirstOrDefaultAsync();
///
- public Task GetLastOrDefaultAsync(Expression> predicate = null)
- {
- try
- {
- return ApplyPredicate(predicate).LastOrDefaultAsync();
- }
- catch (Exception ex)
- {
- _logger.LogError(ex, "Error retrieving last entity of type {EntityType}", typeof(TEntity).Name);
- throw new RepositoryQueryException($"Failed to retrieve last entity: {ex.Message}", ex);
- }
- }
+ public Task GetLastOrDefaultAsync(Expression>? predicate = null)
+ => ApplyPredicate(predicate).LastOrDefaultAsync();
///
- public async Task> GetAsync(Expression> predicate = null)
+ public async Task> GetAsync(Expression>? predicate = null)
{
try
{
@@ -274,7 +254,7 @@ public async Task> GetSortedAsync(
///
public async Task> GetWithIncludesAsync(
IEnumerable includes,
- Expression> predicate = null)
+ Expression>? predicate = null)
{
try
{
@@ -292,7 +272,7 @@ public async Task> GetWithIncludesAsync(
public async Task> GetPagedAsync(
int page,
int pageSize,
- Expression> predicate = null)
+ Expression>? predicate = null)
{
try
{
@@ -310,7 +290,7 @@ public async Task> GetPagedWithIncludesAsync(
int page,
int pageSize,
IEnumerable includes,
- Expression> predicate = null)
+ Expression>? predicate = null)
{
try
{
@@ -345,7 +325,7 @@ public async Task> GetPagedSortedAsync(
}
///
- public Task CountAsync(Expression> predicate = null)
+ public Task CountAsync(Expression>? predicate = null)
{
try
{
@@ -360,12 +340,23 @@ public Task CountAsync(Expression> predicate = null)
}
}
+ private static IQueryable ApplySorting(
+ IQueryable query,
+ Expression> orderBy,
+ SortDirection sortDirection)
+ => sortDirection == SortDirection.Ascending
+ ? query.OrderBy(orderBy)
+ : query.OrderByDescending(orderBy);
+
+ private static IQueryable ApplyIncludes(
+ IQueryable query,
+ IEnumerable includes)
+ => includes.Aggregate(query, (current, includePath) => current.Include(includePath));
+
private IQueryable GetBaseQuery()
- {
- return _enableTracking
+ => _enableTracking
? _dbContext.Set()
: _dbContext.Set().AsNoTracking();
- }
private void ConfigureContextBehavior()
{
@@ -376,27 +367,8 @@ private void ConfigureContextBehavior()
: QueryTrackingBehavior.NoTracking;
}
- private IQueryable ApplyPredicate(Expression> predicate)
- {
- return predicate != null ? BaseQuery.Where(predicate) : BaseQuery;
- }
-
- private IQueryable ApplySorting(
- IQueryable query,
- Expression> orderBy,
- SortDirection sortDirection)
- {
- return sortDirection == SortDirection.Ascending
- ? query.OrderBy(orderBy)
- : query.OrderByDescending(orderBy);
- }
-
- private IQueryable ApplyIncludes(
- IQueryable query,
- IEnumerable includes)
- {
- return includes.Aggregate(query, (current, includePath) => current.Include(includePath));
- }
+ private IQueryable ApplyPredicate(Expression>? predicate)
+ => predicate != null ? BaseQuery.Where(predicate) : BaseQuery;
private async Task> CreatePagedResultAsync(
int page,
@@ -411,7 +383,7 @@ private async Task> CreatePagedResultAsync(
{
CurrentPage = page,
PageSize = pageSize,
- TotalCount = await query.CountAsync()
+ TotalCount = await query.CountAsync(),
};
var skip = (page - 1) * pageSize;
@@ -422,15 +394,4 @@ private async Task> CreatePagedResultAsync(
return result;
}
-
- private (string Query, object[] ParameterValues) BuildStoredProcedureCommand(
- string procedureName,
- SqlParameter[] parameters)
- {
- var paramList = parameters.ToList();
- var paramPlaceholders = string.Join(", ", paramList.Select((p, i) => $"@p{i}"));
- var paramValues = paramList.Select(p => p.Value).ToArray();
-
- return ($"EXEC {procedureName} {paramPlaceholders}", paramValues);
- }
-}
\ No newline at end of file
+}
diff --git a/src/Modules/Faura.Infrastructure.UnitOfWork/Repositories/IEntityRepository.cs b/src/Modules/Faura.Infrastructure.UnitOfWork/Repositories/IEntityRepository.cs
index afb518d..0012480 100644
--- a/src/Modules/Faura.Infrastructure.UnitOfWork/Repositories/IEntityRepository.cs
+++ b/src/Modules/Faura.Infrastructure.UnitOfWork/Repositories/IEntityRepository.cs
@@ -1,151 +1,145 @@
-namespace Faura.Infrastructure.UnitOfWork.Repositories;
+namespace Faura.Infrastructure.UnitOfWork.Repositories;
using Faura.Infrastructure.UnitOfWork.Enums;
using Faura.Infrastructure.UnitOfWork.Models;
using System.Linq.Expressions;
///
-/// Repository interface for entity operations
+/// Repository interface for entity operations.
///
-/// Entity type
-public interface IEntityRepository where TEntity : class
+/// Entity type.
+public interface IEntityRepository
+ where TEntity : class
{
///
- /// Creates a new entity
+ /// Creates a new entity.
///
- /// Entity to create
- /// Save options
- /// Created entity
+ /// Entity to create.
+ /// Created entity.
Task CreateAsync(TEntity entity, bool detach = true, bool autoSaveChanges = true);
///
- /// Creates multiple entities
+ /// Creates multiple entities.
///
- /// Entities to create
- /// Save options
- /// Created entities
+ /// Entities to create.
+ /// Created entities.
Task> CreateRangeAsync(IEnumerable entities, bool autoSaveChanges = true);
///
- /// Updates an existing entity
+ /// Updates an existing entity.
///
- /// Entity to update
- /// Save options
- /// Updated entity
+ /// Entity to update.
+ /// Updated entity.
Task UpdateAsync(TEntity entity, bool detach = true, bool autoSaveChanges = true);
///
- /// Updates multiple entities
+ /// Updates multiple entities.
///
- /// Entities to update
- /// Save options
- /// Updated entities
+ /// Entities to update.
+ /// Updated entities.
Task> UpdateRangeAsync(IEnumerable entities, bool autoSaveChanges = true);
///
- /// Deletes an entity
+ /// Deletes an entity.
///
- /// Entity to delete
- /// Save options
- /// Deleted entity
+ /// Entity to delete.
+ /// Deleted entity.
Task DeleteAsync(TEntity entity, bool detach = true, bool autoSaveChanges = true);
///
- /// Deletes entities matching a predicate
+ /// Deletes entities matching a predicate.
///
- /// Filter predicate
- /// Save options
- /// True if entities were deleted
+ /// Filter predicate.
+ /// True if entities were deleted.
Task DeleteByPredicateAsync(Expression> predicate, bool autoSaveChanges = true);
///
- /// Deletes multiple entities
+ /// Deletes multiple entities.
///
- /// Entities to delete
- /// Save options
- /// Deleted entities
+ /// Entities to delete.
+ /// Deleted entities.
Task> DeleteRangeAsync(IEnumerable entities, bool autoSaveChanges = true);
///
- /// Gets the first entity matching the predicate or default if none
+ /// Gets the first entity matching the predicate or default if none.
///
- /// Filter predicate
- /// First matching entity or default
- Task GetFirstOrDefaultAsync(Expression> predicate = null);
+ /// Filter predicate.
+ /// First matching entity or default.
+ Task GetFirstOrDefaultAsync(Expression>? predicate = null);
///
- /// Gets the last entity matching the predicate or default if none
+ /// Gets the last entity matching the predicate or default if none.
///
- /// Filter predicate
- /// Last matching entity or default
- Task GetLastOrDefaultAsync(Expression> predicate = null);
+ /// Filter predicate.
+ /// Last matching entity or default.
+ Task GetLastOrDefaultAsync(Expression>? predicate = null);
///
- /// Gets all entities matching the predicate
+ /// Gets all entities matching the predicate.
///
- /// Filter predicate
- /// List of matching entities
- Task> GetAsync(Expression> predicate = null);
+ /// Filter predicate.
+ /// List of matching entities.
+ Task> GetAsync(Expression>? predicate = null);
///
- /// Gets sorted entities matching the predicate
+ /// Gets sorted entities matching the predicate.
///
- /// Type of the sort key
- /// Filter predicate
- /// Property to sort by
- /// Sort direction
- /// Sorted list of matching entities
+ /// Type of the sort key.
+ /// Filter predicat.
+ /// Property to sort by.
+ /// Sort direction.
+ /// Sorted list of matching entities.
Task> GetSortedAsync(
Expression> predicate,
Expression> orderBy,
SortDirection sortDirection = SortDirection.Ascending);
///
- /// Gets entities with included related entities
+ /// Gets entities with included related entities.
///
- /// Properties to include
- /// Filter predicate
- /// List of entities with included properties
+ /// Properties to include.
+ /// Filter predicate.
+ /// List of entities with included properties.
Task> GetWithIncludesAsync(
IEnumerable includes,
- Expression> predicate = null);
+ Expression>? predicate = null);
///
- /// Gets a page of entities matching the predicate
+ /// Gets a page of entities matching the predicate.
///
- /// Page number (1-based)
- /// Page size
- /// Filter predicate
- /// Paged result
+ /// Page number (1-based).
+ /// Page size.
+ /// Filter predicate.
+ /// Paged result.
Task> GetPagedAsync(
int page,
int pageSize,
- Expression> predicate = null);
+ Expression>? predicate = null);
///
- /// Gets a page of entities with included related entities
+ /// Gets a page of entities with included related entities.
///
- /// Page number (1-based)
- /// Page size
- /// Properties to include
- /// Filter predicate
- /// Paged result with included properties
+ /// Page number (1-based).
+ /// Page size.
+ /// Properties to include.
+ /// Filter predicate.
+ /// Paged result with included properties.
Task> GetPagedWithIncludesAsync(
int page,
int pageSize,
IEnumerable includes,
- Expression> predicate = null);
+ Expression>? predicate = null);
///
- /// Gets a sorted page of entities matching the predicate
+ /// Gets a sorted page of entities matching the predicate.
///
- /// Type of the sort key
- /// Page number (1-based)
- /// Page size
- /// Filter predicate
- /// Property to sort by
- /// Sort direction
- /// Sorted paged result
+ /// Type of the sort key.
+ /// Page number (1-based).
+ /// Page size.
+ /// Filter predicate.
+ /// Property to sort by.
+ /// Sort direction.
+ /// Sorted paged result.
Task> GetPagedSortedAsync(
int page,
int pageSize,
@@ -154,9 +148,9 @@ Task> GetPagedSortedAsync(
SortDirection sortDirection = SortDirection.Ascending);
///
- /// Counts entities matching the predicate
+ /// Counts entities matching the predicate.
///
- /// Filter predicate
- /// Number of matching entities
- Task CountAsync(Expression> predicate = null);
-}
\ No newline at end of file
+ /// Filter predicate.
+ /// Number of matching entities.
+ Task CountAsync(Expression>? predicate = null);
+}
diff --git a/src/Modules/Faura.Infrastructure.UnitOfWork/Repositories/IRawSqlRepository.cs b/src/Modules/Faura.Infrastructure.UnitOfWork/Repositories/IRawSqlRepository.cs
index c6e370e..57eac99 100644
--- a/src/Modules/Faura.Infrastructure.UnitOfWork/Repositories/IRawSqlRepository.cs
+++ b/src/Modules/Faura.Infrastructure.UnitOfWork/Repositories/IRawSqlRepository.cs
@@ -1,16 +1,13 @@
-namespace Faura.Infrastructure.UnitOfWork.Repositories;
+namespace Faura.Infrastructure.UnitOfWork.Repositories;
using System.Data;
-public interface IRawSqlRepository where TModel : class
+public interface IRawSqlRepository
+ where TModel : class
{
///
/// This method executes a SQL query against the database using the Dapper library.
///
- ///
- ///
- ///
- ///
///
/// It returns an IEnumerable of the provided object containing the results of the query.
///
@@ -19,10 +16,6 @@ public interface IRawSqlRepository where TModel : class
///
/// This method executes a SQL query against the database using the Dapper library.
///
- ///
- ///
- ///
- ///
///
/// Returns the first result, or null if the query returns no results.
///
@@ -31,12 +24,8 @@ public interface IRawSqlRepository where TModel : class
///
/// This method executes a SQL query against the database using the Dapper library.
///
- ///
- ///
- ///
- ///
///
/// It returns the number of affected rows.
///
Task ExecuteAsync(string sql, object? parameters = null, IDbTransaction? transaction = null);
-}
\ No newline at end of file
+}
diff --git a/src/Modules/Faura.Infrastructure.UnitOfWork/Repositories/RawSqlRepository.cs b/src/Modules/Faura.Infrastructure.UnitOfWork/Repositories/RawSqlRepository.cs
index ef7983d..2708613 100644
--- a/src/Modules/Faura.Infrastructure.UnitOfWork/Repositories/RawSqlRepository.cs
+++ b/src/Modules/Faura.Infrastructure.UnitOfWork/Repositories/RawSqlRepository.cs
@@ -1,33 +1,32 @@
-namespace Faura.Infrastructure.UnitOfWork.Repositories;
+namespace Faura.Infrastructure.UnitOfWork.Repositories;
using System.Data;
using Dapper;
using Microsoft.EntityFrameworkCore;
-public class RawSqlRepository : IRawSqlRepository where TModel : class
+public class RawSqlRepository : IRawSqlRepository
+ where TModel : class
{
private readonly DbContext _context;
public RawSqlRepository(DbContext context)
- {
- _context = context ?? throw new ArgumentNullException(nameof(context));
- }
+ => _context = context ?? throw new ArgumentNullException(nameof(context));
- public async Task> QueryAsync(string sql, object? parameters = null, IDbTransaction? transaction = null)
+ public Task> QueryAsync(string sql, object? parameters = null, IDbTransaction? transaction = null)
{
var connection = _context.Database.GetDbConnection();
- return await connection.QueryAsync(sql, parameters, transaction);
+ return connection.QueryAsync(sql, parameters, transaction);
}
- public async Task QueryFirstOrDefaultAsync(string sql, object? parameters = null, IDbTransaction? transaction = null)
+ public Task QueryFirstOrDefaultAsync(string sql, object? parameters = null, IDbTransaction? transaction = null)
{
var connection = _context.Database.GetDbConnection();
- return await connection.QueryFirstOrDefaultAsync(sql, parameters, transaction);
+ return connection.QueryFirstOrDefaultAsync(sql, parameters, transaction);
}
- public async Task ExecuteAsync(string sql, object? parameters = null, IDbTransaction? transaction = null)
+ public Task ExecuteAsync(string sql, object? parameters = null, IDbTransaction? transaction = null)
{
var connection = _context.Database.GetDbConnection();
- return await connection.ExecuteAsync(sql, parameters, transaction);
+ return connection.ExecuteAsync(sql, parameters, transaction);
}
-}
\ No newline at end of file
+}
diff --git a/src/Modules/Faura.Infrastructure.UnitOfWork/UnitOfWork/IUnitOfWork.cs b/src/Modules/Faura.Infrastructure.UnitOfWork/UnitOfWork/IUnitOfWork.cs
index 6dd42b5..4231a2d 100644
--- a/src/Modules/Faura.Infrastructure.UnitOfWork/UnitOfWork/IUnitOfWork.cs
+++ b/src/Modules/Faura.Infrastructure.UnitOfWork/UnitOfWork/IUnitOfWork.cs
@@ -1,4 +1,4 @@
-namespace Faura.Infrastructure.UnitOfWork.UnitOfWork;
+namespace Faura.Infrastructure.UnitOfWork.UnitOfWork;
using System.Data;
using Microsoft.EntityFrameworkCore.Storage;
@@ -6,7 +6,7 @@
public interface IUnitOfWork
{
///
- /// Begins the transaction
+ /// Begins the transaction.
///
Task GetDbTransaction(int secondsTimeout = 30);
@@ -18,4 +18,4 @@ public interface IUnitOfWork
/// Commit the transaction if is correct, else rollback. Both cases dispose.
///
Task CommitTransaction(IDbTransaction transaction);
-}
\ No newline at end of file
+}
diff --git a/src/Modules/Faura.Infrastructure.UnitOfWork/UnitOfWork/UnitOfWork.cs b/src/Modules/Faura.Infrastructure.UnitOfWork/UnitOfWork/UnitOfWork.cs
index abe0110..7ed260f 100644
--- a/src/Modules/Faura.Infrastructure.UnitOfWork/UnitOfWork/UnitOfWork.cs
+++ b/src/Modules/Faura.Infrastructure.UnitOfWork/UnitOfWork/UnitOfWork.cs
@@ -1,18 +1,17 @@
-namespace Faura.Infrastructure.UnitOfWork.UnitOfWork;
+namespace Faura.Infrastructure.UnitOfWork.UnitOfWork;
using System.Data;
using Faura.Infrastructure.UnitOfWork.Exceptions;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage;
-public class UnitOfWork : IUnitOfWork where TContext : DbContext
+public class UnitOfWork : IUnitOfWork
+ where TContext : DbContext
{
private const int DefaultSecondsTimeout = 30;
protected UnitOfWork(TContext context)
- {
- Context = context ?? throw new NullContextException(nameof(context));
- }
+ => Context = context ?? throw new NullContextException(nameof(context));
private TContext Context { get; }
@@ -24,16 +23,11 @@ public async Task GetDbTransaction(int secondsTimeout = DefaultS
return dbContextTransaction.GetDbTransaction();
}
- public Task SaveChanges()
- {
- //Auditable entities
- return Context.SaveChangesAsync();
- }
+ public Task SaveChanges() =>
+ Context.SaveChangesAsync();
public IExecutionStrategy CreateExecutionStrategy()
- {
- return Context.Database.CreateExecutionStrategy();
- }
+ => Context.Database.CreateExecutionStrategy();
public async Task CommitTransaction(IDbTransaction transaction)
{
@@ -46,7 +40,7 @@ public async Task CommitTransaction(IDbTransaction transaction)
transaction.Commit();
}
- catch (Exception ex)
+ catch (Exception)
{
transaction.Rollback();
throw;
@@ -57,4 +51,4 @@ public async Task CommitTransaction(IDbTransaction transaction)
transaction.Dispose();
}
}
-}
\ No newline at end of file
+}
diff --git a/src/Modules/Faura.Infrastructure.UnitOfWork/UnitOfWorkConfiguration.cs b/src/Modules/Faura.Infrastructure.UnitOfWork/UnitOfWorkConfiguration.cs
index 1cf2186..20b10f5 100644
--- a/src/Modules/Faura.Infrastructure.UnitOfWork/UnitOfWorkConfiguration.cs
+++ b/src/Modules/Faura.Infrastructure.UnitOfWork/UnitOfWorkConfiguration.cs
@@ -1,4 +1,4 @@
-namespace Faura.Infrastructure.UnitOfWork;
+namespace Faura.Infrastructure.UnitOfWork;
using Faura.Infrastructure.UnitOfWork.Projectors;
using Faura.Infrastructure.UnitOfWork.Repositories;
@@ -12,4 +12,4 @@ public static void SetupUnitOfWork(this IServiceCollection services)
services.AddScoped(typeof(IRawSqlRepository<>), typeof(RawSqlRepository<>));
services.AddScoped(typeof(IProjector<>), typeof(Projector<>));
}
-}
\ No newline at end of file
+}
diff --git a/src/Templates/Faura.Grpc/Bootstrappers/ApplicationBootstrapper.cs b/src/Templates/Faura.Grpc/Bootstrappers/ApplicationBootstrapper.cs
index 097f3e2..23997bd 100644
--- a/src/Templates/Faura.Grpc/Bootstrappers/ApplicationBootstrapper.cs
+++ b/src/Templates/Faura.Grpc/Bootstrappers/ApplicationBootstrapper.cs
@@ -1,11 +1,7 @@
-namespace Faura.Grpc.Bootstrappers;
+namespace Faura.Grpc.Bootstrappers;
public static class ApplicationBootstrapper
{
public static WebApplicationBuilder RegisterApplicationDependencies(
- this WebApplicationBuilder builder
- )
- {
- return builder;
- }
+ this WebApplicationBuilder builder) => builder;
}
diff --git a/src/Templates/Faura.Grpc/Bootstrappers/GrpcBootstrapper.cs b/src/Templates/Faura.Grpc/Bootstrappers/GrpcBootstrapper.cs
index 80baf53..a5441ba 100644
--- a/src/Templates/Faura.Grpc/Bootstrappers/GrpcBootstrapper.cs
+++ b/src/Templates/Faura.Grpc/Bootstrappers/GrpcBootstrapper.cs
@@ -1,9 +1,9 @@
-using Faura.Grpc.Services;
+namespace Faura.Grpc.Bootstrappers;
+
+using Faura.Grpc.Services;
using Faura.Infrastructure.GrpcBootstrapper.Extensions;
using Faura.Infrastructure.Logger;
-namespace Faura.Grpc.Bootstrappers;
-
public static class GrpcBootstrapper
{
public static WebApplicationBuilder RegisterDependencies(this WebApplicationBuilder builder)
@@ -16,10 +16,5 @@ public static WebApplicationBuilder RegisterDependencies(this WebApplicationBuil
}
public static Action RegisterGrpcServices()
- {
- return endpoints =>
- {
- endpoints.MapGrpcService();
- };
- }
+ => endpoints => endpoints.MapGrpcService();
}
diff --git a/src/Templates/Faura.Grpc/Bootstrappers/OptionsBootstrapper.cs b/src/Templates/Faura.Grpc/Bootstrappers/OptionsBootstrapper.cs
index 104c5b8..e2d28f3 100644
--- a/src/Templates/Faura.Grpc/Bootstrappers/OptionsBootstrapper.cs
+++ b/src/Templates/Faura.Grpc/Bootstrappers/OptionsBootstrapper.cs
@@ -1,11 +1,10 @@
-namespace Faura.Grpc.Bootstrappers;
+namespace Faura.Grpc.Bootstrappers;
public static class OptionsBootstrapper
{
public static void RegisterOptions(
this IServiceCollection services,
- IConfiguration configuration
- )
+ IConfiguration configuration)
{
// Add Options here
}
diff --git a/src/Templates/Faura.Grpc/Faura.Grpc.csproj b/src/Templates/Faura.Grpc/Faura.Grpc.csproj
index e56d51f..6651ab9 100644
--- a/src/Templates/Faura.Grpc/Faura.Grpc.csproj
+++ b/src/Templates/Faura.Grpc/Faura.Grpc.csproj
@@ -11,7 +11,7 @@
-
+
diff --git a/src/Templates/Faura.Grpc/Program.cs b/src/Templates/Faura.Grpc/Program.cs
index fa44dcd..83e9bbb 100644
--- a/src/Templates/Faura.Grpc/Program.cs
+++ b/src/Templates/Faura.Grpc/Program.cs
@@ -10,4 +10,11 @@
app.ConfigureCommonFauraWebApplication(GrpcBootstrapper.RegisterGrpcServices());
-app.Run();
+await app.RunAsync();
+
+public partial class Program
+{
+ protected Program()
+ {
+ }
+}
diff --git a/src/Templates/Faura.Grpc/Services/GreeterService.cs b/src/Templates/Faura.Grpc/Services/GreeterService.cs
index a0a3bf2..87b6075 100644
--- a/src/Templates/Faura.Grpc/Services/GreeterService.cs
+++ b/src/Templates/Faura.Grpc/Services/GreeterService.cs
@@ -1,16 +1,13 @@
-using Faura.Infrastructure.Logger.Extensions;
-using Grpc.Core;
-
namespace Faura.Grpc.Services;
+using Faura.Infrastructure.Logger.Extensions;
+using global::Grpc.Core;
+
public class GreeterService : Greeter.GreeterBase
{
private readonly ILogger _logger;
- public GreeterService(ILogger logger)
- {
- _logger = logger;
- }
+ public GreeterService(ILogger logger) => _logger = logger;
public override Task SayHello(HelloRequest request, ServerCallContext context)
{
diff --git a/src/Templates/Faura.IntegrationTest/Configuration/CustomWebApplicationFactory.cs b/src/Templates/Faura.WebAPI.IntegrationTests/Configuration/CustomWebApplicationFactory.cs
similarity index 100%
rename from src/Templates/Faura.IntegrationTest/Configuration/CustomWebApplicationFactory.cs
rename to src/Templates/Faura.WebAPI.IntegrationTests/Configuration/CustomWebApplicationFactory.cs
diff --git a/src/Templates/Faura.IntegrationTest/Configuration/IntegrationTestBase.cs b/src/Templates/Faura.WebAPI.IntegrationTests/Configuration/IntegrationTestBase.cs
similarity index 100%
rename from src/Templates/Faura.IntegrationTest/Configuration/IntegrationTestBase.cs
rename to src/Templates/Faura.WebAPI.IntegrationTests/Configuration/IntegrationTestBase.cs
diff --git a/src/Templates/Faura.IntegrationTest/Faura.IntegrationTest.csproj b/src/Templates/Faura.WebAPI.IntegrationTests/Faura.WebAPI.IntegrationTests.csproj
similarity index 100%
rename from src/Templates/Faura.IntegrationTest/Faura.IntegrationTest.csproj
rename to src/Templates/Faura.WebAPI.IntegrationTests/Faura.WebAPI.IntegrationTests.csproj
diff --git a/src/Templates/Faura.IntegrationTest/Seeders/EmployeeTestDataSeeder.cs b/src/Templates/Faura.WebAPI.IntegrationTests/Seeders/EmployeeTestDataSeeder.cs
similarity index 100%
rename from src/Templates/Faura.IntegrationTest/Seeders/EmployeeTestDataSeeder.cs
rename to src/Templates/Faura.WebAPI.IntegrationTests/Seeders/EmployeeTestDataSeeder.cs
diff --git a/src/Templates/Faura.WebAPI.IntegrationTests/UseCases/EmployeeTests.cs b/src/Templates/Faura.WebAPI.IntegrationTests/UseCases/EmployeeTests.cs
new file mode 100644
index 0000000..57e4215
--- /dev/null
+++ b/src/Templates/Faura.WebAPI.IntegrationTests/UseCases/EmployeeTests.cs
@@ -0,0 +1,92 @@
+namespace Faura.IntegrationTest.UseCases;
+
+using System.Net;
+using System.Net.Http.Json;
+using Faura.IntegrationTest.Configuration;
+using Faura.WebAPI.Domain.Entities;
+using Xunit;
+
+public class EmployeeTests : IClassFixture>
+{
+ private readonly HttpClient _client;
+
+ public EmployeeTests(CustomWebApplicationFactory factory)
+ => _client = factory.CreateClient();
+
+ [Fact]
+ public async Task Should_Get_Employees()
+ {
+ // Act
+ var response = await _client.GetAsync("/Employee");
+
+ // Assert
+ response.EnsureSuccessStatusCode();
+ var employees = await response.Content.ReadFromJsonAsync>();
+
+ Assert.NotNull(employees);
+ }
+
+ [Fact]
+ public async Task Should_Create_Employee()
+ {
+ // Arrange
+ var newEmployee = new Employee("Test", "User", "test.user@example.com");
+
+ // Act
+ var response = await _client.PostAsJsonAsync("/Employee", newEmployee);
+
+ // Assert
+ response.EnsureSuccessStatusCode();
+ var created = await response.Content.ReadFromJsonAsync();
+
+ Assert.NotNull(created);
+ Assert.Equal(newEmployee.Email, created?.Email);
+ }
+
+ [Fact]
+ public async Task Should_Get_Employee_By_Id()
+ {
+ // Arrange
+ var employee = new Employee("Get", "ById", "get.byid@example.com");
+ var post = await _client.PostAsJsonAsync("/Employee", employee);
+ var created = await post.Content.ReadFromJsonAsync();
+
+ // Act
+ var response = await _client.GetAsync($"/Employee/{created!.Id}");
+
+ // Assert
+ response.EnsureSuccessStatusCode();
+ var result = await response.Content.ReadFromJsonAsync();
+ Assert.Equal(created.Id, result?.Id);
+ }
+
+ [Fact]
+ public async Task Should_Delete_Employee()
+ {
+ // Arrange
+ var employee = new Employee("To", "Delete", "to.delete@example.com");
+ var post = await _client.PostAsJsonAsync("/Employee", employee);
+ var created = await post.Content.ReadFromJsonAsync();
+
+ // Act
+ var delete = await _client.DeleteAsync($"/Employee/{created!.Id}");
+
+ // Assert
+ Assert.Equal(HttpStatusCode.NoContent, delete.StatusCode);
+
+ var get = await _client.GetAsync($"/Employee/{created.Id}");
+ Assert.Equal(HttpStatusCode.NotFound, get.StatusCode);
+ }
+
+ [Fact]
+ public async Task Should_Create_Two_Employees_In_Transaction()
+ {
+ // Act
+ var response = await _client.PostAsync("/Employee/batch", null);
+
+ // Assert
+ response.EnsureSuccessStatusCode();
+ var result = await response.Content.ReadAsStringAsync();
+ Assert.Equal("Two employees created in transaction.", result.Trim());
+ }
+}
diff --git a/src/Templates/Faura.IntegrationTest/appsettings.Test.json b/src/Templates/Faura.WebAPI.IntegrationTests/appsettings.Test.json
similarity index 100%
rename from src/Templates/Faura.IntegrationTest/appsettings.Test.json
rename to src/Templates/Faura.WebAPI.IntegrationTests/appsettings.Test.json
diff --git a/src/Templates/Faura.WebAPI.UnitTests/EmployeeControllerTests.cs b/src/Templates/Faura.WebAPI.UnitTests/EmployeeControllerTests.cs
new file mode 100644
index 0000000..4c50a81
--- /dev/null
+++ b/src/Templates/Faura.WebAPI.UnitTests/EmployeeControllerTests.cs
@@ -0,0 +1,127 @@
+namespace Faura.WebAPI.Tests.Controllers;
+
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Threading.Tasks;
+using Faura.WebAPI.Controllers;
+using Faura.WebAPI.Domain.Entities;
+using Faura.WebAPI.Domain.Repositories;
+using Faura.WebAPI.Infrastructure.Persistence;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Logging;
+using NSubstitute;
+using Xunit;
+
+public class EmployeeControllerTests
+{
+ private readonly ILogger _logger = Substitute.For>();
+ private readonly IEmployeeRepository _repository = Substitute.For();
+ private readonly IEmployeeUoW _uow = Substitute.For();
+ private readonly EmployeeController _controller;
+
+ public EmployeeControllerTests()
+ => _controller = new EmployeeController(_logger, _repository, _uow);
+
+ [Fact]
+ public async Task Get_ReturnsEmployees()
+ {
+ // Arrange
+ var employees = new List { new("Josep", "Ferrandis", "test@example.com") };
+ _repository.GetAsync().Returns(employees);
+
+ // Act
+ var result = await _controller.Get();
+
+ // Assert
+ var okResult = Assert.IsType(result);
+ Assert.Equal(employees, okResult.Value);
+ }
+
+ [Fact]
+ public async Task Create_ReturnsCreatedAtAction()
+ {
+ // Arrange
+ var employee = new Employee("Test", "User", "test@domain.com");
+ await _repository.CreateAsync(employee);
+
+ // Act
+ var result = await _controller.Create(employee);
+
+ // Assert
+ var created = Assert.IsType(result);
+ Assert.Equal(nameof(_controller.GetById), created.ActionName);
+ Assert.Equal(employee, created.Value);
+ }
+
+ [Fact]
+ public async Task CreateBatch_CreatesTwoEmployeesAndCommitsTransaction()
+ {
+ // Arrange
+ var fakeTransaction = Substitute.For();
+ _uow.GetDbTransaction(Arg.Any()).Returns(fakeTransaction);
+
+ // Act
+ var result = await _controller.CreateBatch();
+
+ // Assert
+ await _repository.Received(2).CreateAsync(Arg.Is(e =>
+ e.FirstName == "Josep" && e.LastName == "Ferrandis" && e.Email.StartsWith("josep")));
+
+ await _uow.Received(1).CommitTransaction(fakeTransaction);
+
+ var okResult = Assert.IsType(result);
+ Assert.Equal("Two employees created in transaction.", okResult.Value);
+ }
+
+ [Fact]
+ public async Task GetById_EmployeeExists_ReturnsOk()
+ {
+ // Arrange
+ var id = 1;
+ var employee = new Employee("A", "B", "a@b.com") { Id = id };
+ _repository.GetByIdAsync(id).Returns(employee);
+
+ // Act
+ var result = await _controller.GetById(id);
+
+ // Assert
+ var ok = Assert.IsType(result);
+ Assert.Equal(employee, ok.Value);
+ }
+
+ [Fact]
+ public async Task GetById_EmployeeNotFound_ReturnsNotFound()
+ {
+ var id = 1;
+ _repository.GetByIdAsync(id).Returns((Employee?)null);
+
+ var result = await _controller.GetById(id);
+
+ Assert.IsType(result);
+ }
+
+ [Fact]
+ public async Task Delete_EmployeeExists_DeletesAndReturnsNoContent()
+ {
+ var id = 1;
+ var employee = new Employee("Del", "Ete", "del@ete.com") { Id = id };
+ _repository.GetByIdAsync(id).Returns(employee);
+
+ var result = await _controller.Delete(id);
+
+ await _repository.Received(1).DeleteAsync(employee);
+ Assert.IsType(result);
+ }
+
+ [Fact]
+ public async Task Delete_EmployeeNotFound_ReturnsNotFound()
+ {
+ var id = 1;
+ _repository.GetByIdAsync(id).Returns((Employee?)null);
+
+ var result = await _controller.Delete(id);
+
+ Assert.IsType(result);
+ }
+}
diff --git a/src/Templates/Faura.WebAPI.UnitTests/Faura.WebAPI.UnitTests.csproj b/src/Templates/Faura.WebAPI.UnitTests/Faura.WebAPI.UnitTests.csproj
new file mode 100644
index 0000000..85bea97
--- /dev/null
+++ b/src/Templates/Faura.WebAPI.UnitTests/Faura.WebAPI.UnitTests.csproj
@@ -0,0 +1,20 @@
+
+
+
+ net8.0
+ enable
+ enable
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Templates/Faura.WebAPI/Bootstrappers/ApiBootstrapper.cs b/src/Templates/Faura.WebAPI/Bootstrappers/ApiBootstrapper.cs
index 894655b..423aeb5 100644
--- a/src/Templates/Faura.WebAPI/Bootstrappers/ApiBootstrapper.cs
+++ b/src/Templates/Faura.WebAPI/Bootstrappers/ApiBootstrapper.cs
@@ -1,8 +1,8 @@
-using Faura.Infrastructure.ApiBootstrapper.Extensions;
+namespace Faura.WebAPI.Bootstrappers;
+
using Faura.Infrastructure.JWT.Extensions;
using Faura.Infrastructure.Logger;
-
-namespace Faura.WebAPI.Bootstrappers;
+using Faura.Infrastructure.ApiBootstrapper.Extensions;
public static class ApiBootstrapper
{
diff --git a/src/Templates/Faura.WebAPI/Bootstrappers/OptionsBootstrapper.cs b/src/Templates/Faura.WebAPI/Bootstrappers/OptionsBootstrapper.cs
index ef95385..2ae9097 100644
--- a/src/Templates/Faura.WebAPI/Bootstrappers/OptionsBootstrapper.cs
+++ b/src/Templates/Faura.WebAPI/Bootstrappers/OptionsBootstrapper.cs
@@ -1,11 +1,10 @@
-namespace Faura.WebAPI.Bootstrappers;
+namespace Faura.WebAPI.Bootstrappers;
public static class OptionsBootstrapper
{
public static void RegisterOptions(
this IServiceCollection services,
- IConfiguration configuration
- )
+ IConfiguration configuration)
{
// Add Options here
}
diff --git a/src/Templates/Faura.WebAPI/Domain/Entities/Employee.cs b/src/Templates/Faura.WebAPI/Domain/Entities/Employee.cs
index 36ac673..f861528 100644
--- a/src/Templates/Faura.WebAPI/Domain/Entities/Employee.cs
+++ b/src/Templates/Faura.WebAPI/Domain/Entities/Employee.cs
@@ -1,7 +1,7 @@
-using System.ComponentModel.DataAnnotations.Schema;
-
namespace Faura.WebAPI.Domain.Entities;
+using System.ComponentModel.DataAnnotations.Schema;
+
[Table("employee")]
public class Employee
{
diff --git a/src/Templates/Faura.WebAPI/Domain/IEmployeeRepository.cs b/src/Templates/Faura.WebAPI/Domain/IEmployeeRepository.cs
deleted file mode 100644
index e6f2c49..0000000
--- a/src/Templates/Faura.WebAPI/Domain/IEmployeeRepository.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-using Faura.Infrastructure.UnitOfWork.Repositories;
-using Faura.WebAPI.Domain.Entities;
-
-namespace Faura.WebAPI.Domain;
-
-public interface IEmployeeRepository : IEntityRepository { }
diff --git a/src/Templates/Faura.WebAPI/Domain/Repositories/IEmployeeRepository.cs b/src/Templates/Faura.WebAPI/Domain/Repositories/IEmployeeRepository.cs
new file mode 100644
index 0000000..24618aa
--- /dev/null
+++ b/src/Templates/Faura.WebAPI/Domain/Repositories/IEmployeeRepository.cs
@@ -0,0 +1,9 @@
+namespace Faura.WebAPI.Domain.Repositories;
+
+using Faura.Infrastructure.UnitOfWork.Repositories;
+using Faura.WebAPI.Domain.Entities;
+
+public interface IEmployeeRepository : IEntityRepository
+{
+ Task GetByIdAsync(long id);
+}
diff --git a/src/Templates/Faura.WebAPI/Infrastructure/Persistence/IEmployeeUoW.cs b/src/Templates/Faura.WebAPI/Infrastructure/Persistence/IEmployeeUoW.cs
index 3343fc0..cdc3374 100644
--- a/src/Templates/Faura.WebAPI/Infrastructure/Persistence/IEmployeeUoW.cs
+++ b/src/Templates/Faura.WebAPI/Infrastructure/Persistence/IEmployeeUoW.cs
@@ -1,5 +1,7 @@
-using Faura.Infrastructure.UnitOfWork.UnitOfWork;
-
namespace Faura.WebAPI.Infrastructure.Persistence;
-public interface IEmployeeUoW : IUnitOfWork { }
+using Faura.Infrastructure.UnitOfWork.UnitOfWork;
+
+public interface IEmployeeUoW : IUnitOfWork
+{
+}
diff --git a/src/Templates/Faura.WebAPI/Infrastructure/Repositories/EmployeeRepository.cs b/src/Templates/Faura.WebAPI/Infrastructure/Repositories/EmployeeRepository.cs
new file mode 100644
index 0000000..b33aa70
--- /dev/null
+++ b/src/Templates/Faura.WebAPI/Infrastructure/Repositories/EmployeeRepository.cs
@@ -0,0 +1,21 @@
+namespace Faura.WebAPI.Infrastructure.Repositories;
+
+using System.Threading.Tasks;
+using Faura.Infrastructure.UnitOfWork.Repositories;
+using Faura.WebAPI.Domain.Entities;
+using Faura.WebAPI.Domain.Repositories;
+using Faura.WebAPI.Infrastructure.Persistence;
+
+public class EmployeeRepository : EntityRepository, IEmployeeRepository
+{
+ public EmployeeRepository(
+ EmployeeDbContext dbContext,
+ ILogger logger,
+ bool enableTracking = false)
+ : base(dbContext, logger, enableTracking)
+ {
+ }
+
+ public Task GetByIdAsync(long id)
+ => GetFirstOrDefaultAsync(e => e.Id == id);
+}
diff --git a/src/global.json b/src/global.json
new file mode 100644
index 0000000..dc998b1
--- /dev/null
+++ b/src/global.json
@@ -0,0 +1,6 @@
+{
+ "sdk": {
+ "rollForward": "latestFeature",
+ "version": "8.0.300"
+ }
+}
diff --git a/src/stylecop.json b/src/stylecop.json
new file mode 100644
index 0000000..2289c6a
--- /dev/null
+++ b/src/stylecop.json
@@ -0,0 +1,11 @@
+{
+ "@schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json",
+ "settings": {
+ "layoutRules": {
+ "newlineAtEndOfFile": "require"
+ },
+ "orderingRules": {
+ "blankLinesBetweenUsingGroups": "omit"
+ }
+ }
+}