feat: estruturação inicial da solução

This commit is contained in:
Jean Gatto
2022-06-02 22:36:11 -03:00
parent 0340f11aa7
commit c132156b82
24 changed files with 538 additions and 0 deletions
+3
View File
@@ -3,6 +3,9 @@
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# coverage
coverage/
# User-specific files
*.rsuser
*.suo
+32
View File
@@ -0,0 +1,32 @@
{
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Launch (web)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceFolder}/src/Shop.PublicApi/bin/Debug/net6.0/Shop.PublicApi.dll",
"args": [],
"cwd": "${workspaceFolder}/src/Shop.PublicApi",
"stopAtEntry": false,
"logging": { "moduleLoad": false },
"serverReadyAction": {
"action": "openExternally",
"pattern": "\\bNow listening on:\\s+(https?://\\S+)",
"uriFormat": "%s/swagger"
},
"env": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"sourceFileMap": {
"/Views": "${workspaceFolder}/Views"
}
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach"
}
]
}
+41
View File
@@ -0,0 +1,41 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/src/Shop.PublicApi/Shop.PublicApi.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "publish",
"command": "dotnet",
"type": "process",
"args": [
"publish",
"${workspaceFolder}/src/Shop.PublicApi/Shop.PublicApi.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "watch",
"command": "dotnet",
"type": "process",
"args": [
"watch",
"run",
"--project",
"${workspaceFolder}/src/Shop.PublicApi/Shop.PublicApi.csproj"
],
"problemMatcher": "$msCompile"
}
]
}
+1
View File
@@ -10,6 +10,7 @@
<AnalysisLevel>latest</AnalysisLevel>
<EnableNETAnalyzers>true</EnableNETAnalyzers>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>
</Project>
+71
View File
@@ -0,0 +1,71 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30114.105
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{8011CDDD-0814-4C74-9B74-C3E3365D50CC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shop.Application", "src\Shop.Application\Shop.Application.csproj", "{72DC21B1-F2D0-4858-9657-44EF571E43D2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shop.Core", "src\Shop.Core\Shop.Core.csproj", "{3AF7991A-6443-4107-9C93-BEF0E97944EF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shop.Domain", "src\Shop.Domain\Shop.Domain.csproj", "{7FDA8D84-9E01-4424-872E-ABAABC3965A9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shop.Infrastructure", "src\Shop.Infrastructure\Shop.Infrastructure.csproj", "{11296DB2-D948-4ADF-A4CE-3F2BFF627478}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{DFB189FE-F11B-46EA-A5CD-3571CEC8193A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shop.UnitTests", "tests\Shop.UnitTests\Shop.UnitTests.csproj", "{D957E297-38EA-402F-B603-25F3EC156E18}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shop.IntegrationTests", "tests\Shop.IntegrationTests\Shop.IntegrationTests.csproj", "{8EF0E054-F77D-4C6D-9102-565887855766}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shop.PublicApi", "src\Shop.PublicApi\Shop.PublicApi.csproj", "{E94C4296-DC64-4C22-87A1-B5A054FAADAC}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{72DC21B1-F2D0-4858-9657-44EF571E43D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{72DC21B1-F2D0-4858-9657-44EF571E43D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{72DC21B1-F2D0-4858-9657-44EF571E43D2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{72DC21B1-F2D0-4858-9657-44EF571E43D2}.Release|Any CPU.Build.0 = Release|Any CPU
{3AF7991A-6443-4107-9C93-BEF0E97944EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3AF7991A-6443-4107-9C93-BEF0E97944EF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3AF7991A-6443-4107-9C93-BEF0E97944EF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3AF7991A-6443-4107-9C93-BEF0E97944EF}.Release|Any CPU.Build.0 = Release|Any CPU
{7FDA8D84-9E01-4424-872E-ABAABC3965A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7FDA8D84-9E01-4424-872E-ABAABC3965A9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7FDA8D84-9E01-4424-872E-ABAABC3965A9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7FDA8D84-9E01-4424-872E-ABAABC3965A9}.Release|Any CPU.Build.0 = Release|Any CPU
{11296DB2-D948-4ADF-A4CE-3F2BFF627478}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{11296DB2-D948-4ADF-A4CE-3F2BFF627478}.Debug|Any CPU.Build.0 = Debug|Any CPU
{11296DB2-D948-4ADF-A4CE-3F2BFF627478}.Release|Any CPU.ActiveCfg = Release|Any CPU
{11296DB2-D948-4ADF-A4CE-3F2BFF627478}.Release|Any CPU.Build.0 = Release|Any CPU
{D957E297-38EA-402F-B603-25F3EC156E18}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D957E297-38EA-402F-B603-25F3EC156E18}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D957E297-38EA-402F-B603-25F3EC156E18}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D957E297-38EA-402F-B603-25F3EC156E18}.Release|Any CPU.Build.0 = Release|Any CPU
{8EF0E054-F77D-4C6D-9102-565887855766}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8EF0E054-F77D-4C6D-9102-565887855766}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8EF0E054-F77D-4C6D-9102-565887855766}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8EF0E054-F77D-4C6D-9102-565887855766}.Release|Any CPU.Build.0 = Release|Any CPU
{E94C4296-DC64-4C22-87A1-B5A054FAADAC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E94C4296-DC64-4C22-87A1-B5A054FAADAC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E94C4296-DC64-4C22-87A1-B5A054FAADAC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E94C4296-DC64-4C22-87A1-B5A054FAADAC}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{72DC21B1-F2D0-4858-9657-44EF571E43D2} = {8011CDDD-0814-4C74-9B74-C3E3365D50CC}
{3AF7991A-6443-4107-9C93-BEF0E97944EF} = {8011CDDD-0814-4C74-9B74-C3E3365D50CC}
{7FDA8D84-9E01-4424-872E-ABAABC3965A9} = {8011CDDD-0814-4C74-9B74-C3E3365D50CC}
{11296DB2-D948-4ADF-A4CE-3F2BFF627478} = {8011CDDD-0814-4C74-9B74-C3E3365D50CC}
{D957E297-38EA-402F-B603-25F3EC156E18} = {DFB189FE-F11B-46EA-A5CD-3571CEC8193A}
{8EF0E054-F77D-4C6D-9102-565887855766} = {DFB189FE-F11B-46EA-A5CD-3571CEC8193A}
{E94C4296-DC64-4C22-87A1-B5A054FAADAC} = {8011CDDD-0814-4C74-9B74-C3E3365D50CC}
EndGlobalSection
EndGlobal
@@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Shop.Domain\Shop.Domain.csproj" />
<ProjectReference Include="..\Shop.Core\Shop.Core.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,45 @@
using JsonNet.ContractResolvers;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
namespace Shop.Core.Extensions;
/// <summary>
/// Extensões para a utilização do JSON.
/// </summary>
public static class JsonExtensions
{
private static readonly CamelCaseNamingStrategy NamingStrategy = new();
private static readonly StringEnumConverter StringEnumConverter = new(NamingStrategy);
private static readonly IContractResolver ContractResolver = new PrivateSetterContractResolver { NamingStrategy = NamingStrategy };
private static readonly JsonSerializerSettings JsonSettings = new JsonSerializerSettings().Configure();
/// <summary>
/// Desserializa o JSON para o tipo especificado.
/// </summary>
/// <typeparam name="T">O tipo de objeto para o qual desserializar.</typeparam>
/// <param name="value">O objeto a ser desserializado.</param>
/// <returns>O objeto desserializado da string JSON.</returns>
public static T FromJson<T>(this string value)
=> JsonConvert.DeserializeObject<T>(value, JsonSettings);
/// <summary>
/// Serializa o objeto especificado em uma string JSON.
/// </summary>
/// <param name="value">O objeto a ser serializado.</param>
/// <returns>Uma representação de string JSON do objeto.</returns>
public static string ToJson<T>(this T value)
=> JsonConvert.SerializeObject(value, JsonSettings);
public static JsonSerializerSettings Configure(this JsonSerializerSettings settings)
{
settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
settings.PreserveReferencesHandling = PreserveReferencesHandling.None;
settings.NullValueHandling = NullValueHandling.Ignore;
settings.Formatting = Formatting.None;
settings.ContractResolver = ContractResolver;
settings.Converters.Add(StringEnumConverter);
return settings;
}
}
@@ -0,0 +1,8 @@
namespace Shop.Core.Interfaces;
/// <summary>
/// Interface marcadora para representar uma raiz de agregação.
/// </summary>
public interface IAggregateRoot
{
}
+18
View File
@@ -0,0 +1,18 @@
using MediatR;
namespace Shop.Core.Interfaces;
/// <summary>
/// Interface marcadora para representar um comando com uma resposta vazia.
/// </summary>
public interface ICommand : IRequest
{
}
/// <summary>
/// Interface marcadora para representar um comando com uma resposta.
/// </summary>
/// <typeparam name="TResponse">O tipo de resposta.</typeparam>
public interface ICommand<out TResponse> : IRequest<TResponse>
{
}
@@ -0,0 +1,13 @@
using MediatR;
namespace Shop.Core.Interfaces;
public interface ICommandHandler<in TCommand> : IRequestHandler<TCommand>
where TCommand : ICommand
{
}
public interface ICommandHandler<in TCommand, TResponse> : IRequestHandler<TCommand, TResponse>
where TCommand : ICommand<TResponse>
{
}
+17
View File
@@ -0,0 +1,17 @@
namespace Shop.Core.Interfaces;
/// <summary>
/// Interface marcadora para representar uma entidade.
/// </summary>
public interface IEntity
{
}
/// <summary>
/// Interface marcadora para representar uma entidade.
/// </summary>
/// <typeparam name="TKey">O tipo da chave.</typeparam>
public interface IEntityKey<out TKey> : IEntity
{
TKey Id { get; }
}
+7
View File
@@ -0,0 +1,7 @@
using MediatR;
namespace Shop.Core.Interfaces;
public interface IQuery<out TResponse> : IRequest<TResponse>
{
}
@@ -0,0 +1,8 @@
using MediatR;
namespace Shop.Core.Interfaces;
public interface IQueryHandler<in TQuery, TResponse> : IRequestHandler<TQuery, TResponse>
where TQuery : IQuery<TResponse>
{
}
+15
View File
@@ -0,0 +1,15 @@
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Shop.Core.Interfaces;
public interface IUnitOfWork : IDisposable
{
/// <summary>
/// Salva todas as alterações feitas no contexto do banco de dados.
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns>O número de linhas afetadas no banco de dados.</returns>
Task<int> CommitAsync(CancellationToken cancellationToken = default);
}
+13
View File
@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="JsonNet.ContractResolvers" Version="2.0.0" />
<PackageReference Include="MediatR" Version="10.0.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup>
</Project>
+11
View File
@@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Shop.Core\Shop.Core.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Shop.Core\Shop.Core.csproj" />
<ProjectReference Include="..\Shop.Domain\Shop.Domain.csproj" />
</ItemGroup>
</Project>
+70
View File
@@ -0,0 +1,70 @@
using System;
using System.IO;
using System.IO.Compression;
using System.Reflection;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.ResponseCompression;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.OpenApi.Models;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddResponseCompression(options => options.Providers.Add<GzipCompressionProvider>());
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new OpenApiInfo
{
Version = "v1",
Title = "Shop (e-commerce)",
Description = "ASP.NET Core C# CQRS, REST API, DDD, Princípios SOLID e Clean Architecture",
Contact = new OpenApiContact
{
Name = "Jean Gatto",
Email = "jean_gatto@hotmail.com",
Url = new Uri("https://www.linkedin.com/in/jeangatto/")
},
License = new OpenApiLicense
{
Name = "MIT License",
Url = new Uri("https://github.com/jeangatto/asp-net-core-cqrs-ddd-solid-api/blob/main/LICENSE")
}
});
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
options.IncludeXmlComments(xmlPath, true);
});
builder.Services.AddSwaggerGenNewtonsoftSupport();
builder.Services.Configure<GzipCompressionProviderOptions>(options => options.Level = CompressionLevel.Optimal);
builder.Services.Configure<RouteOptions>(options => options.LowercaseUrls = true);
builder.Services.Configure<KestrelServerOptions>(options => options.AddServerHeader = false);
builder.Host.UseDefaultServiceProvider((context, options) =>
{
options.ValidateScopes = context.HostingEnvironment.IsDevelopment();
options.ValidateOnBuild = true;
});
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI(options => options.DisplayRequestDuration());
}
app.UseResponseCompression();
app.UseHttpLogging();
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
@@ -0,0 +1,33 @@
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:6452",
"sslPort": 44331
}
},
"profiles": {
"Shop.PublicApi": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"hotReloadEnabled": true,
"launchUrl": "swagger",
"applicationUrl": "https://localhost:7225;http://localhost:5072",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"hotReloadEnabled": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
+18
View File
@@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<IncludeOpenAPIAnalyzers>true</IncludeOpenAPIAnalyzers>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.3.1" />
<PackageReference Include="Swashbuckle.AspNetCore.Newtonsoft" Version="6.3.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Shop.Application\Shop.Application.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}
+9
View File
@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
@@ -0,0 +1,35 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="3.1.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="coverlet.msbuild" Version="3.1.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="FluentAssertions" Version="6.7.0"/>
<PackageReference Include="FluentAssertions.Analyzers" Version="0.17.2"/>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.2.0" />
<PackageReference Include="Moq" Version="4.18.1"/>
<PackageReference Include="Moq.Analyzers" Version="0.0.9"/>
<PackageReference Include="xunit" Version="2.4.1"/>
<PackageReference Include="xunit.analyzers" Version="0.10.0"/>
<PackageReference Include="xunit.categories" Version="2.0.6"/>
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Shop.PublicApi\Shop.PublicApi.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,38 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="3.1.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="coverlet.msbuild" Version="3.1.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="FluentAssertions" Version="6.7.0"/>
<PackageReference Include="FluentAssertions.Analyzers" Version="0.17.2"/>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.2.0" />
<PackageReference Include="Moq" Version="4.18.1"/>
<PackageReference Include="Moq.Analyzers" Version="0.0.9"/>
<PackageReference Include="xunit" Version="2.4.1"/>
<PackageReference Include="xunit.analyzers" Version="0.10.0"/>
<PackageReference Include="xunit.categories" Version="2.0.6"/>
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Shop.Infrastructure\Shop.Infrastructure.csproj" />
<ProjectReference Include="..\..\src\Shop.Domain\Shop.Domain.csproj" />
<ProjectReference Include="..\..\src\Shop.Core\Shop.Core.csproj" />
<ProjectReference Include="..\..\src\Shop.Application\Shop.Application.csproj" />
</ItemGroup>
</Project>