initial commit
This commit is contained in:
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
bin/
|
||||||
|
obj/
|
||||||
|
/packages/
|
||||||
|
riderModule.iml
|
||||||
|
/_ReSharper.Caches/
|
||||||
15
.idea/.idea.GraphQLTEST/.idea/.gitignore
generated
vendored
Normal file
15
.idea/.idea.GraphQLTEST/.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Rider ignored files
|
||||||
|
/contentModel.xml
|
||||||
|
/.idea.GraphQLTEST.iml
|
||||||
|
/projectSettingsUpdater.xml
|
||||||
|
/modules.xml
|
||||||
|
# Ignored default folder with query files
|
||||||
|
/queries/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
6
.idea/.idea.GraphQLTEST/.idea/copilot.data.migration.agent.xml
generated
Normal file
6
.idea/.idea.GraphQLTEST/.idea/copilot.data.migration.agent.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="AgentMigrationStateService">
|
||||||
|
<option name="migrationStatus" value="COMPLETED" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
4
.idea/.idea.GraphQLTEST/.idea/encodings.xml
generated
Normal file
4
.idea/.idea.GraphQLTEST/.idea/encodings.xml
generated
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
|
||||||
|
</project>
|
||||||
8
.idea/.idea.GraphQLTEST/.idea/indexLayout.xml
generated
Normal file
8
.idea/.idea.GraphQLTEST/.idea/indexLayout.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="UserContentModel">
|
||||||
|
<attachedFolders />
|
||||||
|
<explicitIncludes />
|
||||||
|
<explicitExcludes />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
6
.idea/.idea.GraphQLTEST/.idea/vcs.xml
generated
Normal file
6
.idea/.idea.GraphQLTEST/.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
18
Application/Application.csproj
Normal file
18
Application/Application.csproj
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<LangVersion>latest</LangVersion>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Domain\Domain.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
12
Application/DependencyInjection.cs
Normal file
12
Application/DependencyInjection.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
using Application.Interfaces.Services;
|
||||||
|
using Application.Services;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
namespace Application;
|
||||||
|
|
||||||
|
public static class DependencyInjection
|
||||||
|
{
|
||||||
|
public static IServiceCollection AddApplication(this IServiceCollection services) =>
|
||||||
|
services.AddScoped<IUserService, UserService>()
|
||||||
|
.AddScoped<IKillService, KillService>();
|
||||||
|
}
|
||||||
8
Application/Exceptions/BaseException.cs
Normal file
8
Application/Exceptions/BaseException.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using Domain.Enums;
|
||||||
|
|
||||||
|
namespace Application.Exceptions;
|
||||||
|
|
||||||
|
public class BaseException(EErrorCategory category, string message) : Exception(message)
|
||||||
|
{
|
||||||
|
public readonly EErrorCategory Category = category;
|
||||||
|
}
|
||||||
8
Application/Exceptions/DuplicateEmailException.cs
Normal file
8
Application/Exceptions/DuplicateEmailException.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using Domain.Enums;
|
||||||
|
|
||||||
|
namespace Application.Exceptions;
|
||||||
|
|
||||||
|
public class DuplicateEmailException(string email) : BaseException(EErrorCategory.UserValidationError, $"Email {email} already registered")
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
8
Application/Exceptions/DuplicateUsernameException.cs
Normal file
8
Application/Exceptions/DuplicateUsernameException.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using Domain.Enums;
|
||||||
|
|
||||||
|
namespace Application.Exceptions;
|
||||||
|
|
||||||
|
public class DuplicateUsernameException(string? username) : BaseException(EErrorCategory.UserValidationError, $"Username {username} is taken")
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
using Domain.Enums;
|
||||||
|
|
||||||
|
namespace Application.Exceptions;
|
||||||
|
|
||||||
|
public class InsufficientParametersException(List<string> missingParameters) : BaseException(EErrorCategory.RequestError, "Insufficient Parameters: " + string.Join(", ", missingParameters))
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
8
Application/Exceptions/UserNotFoundException.cs
Normal file
8
Application/Exceptions/UserNotFoundException.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using Domain.Enums;
|
||||||
|
|
||||||
|
namespace Application.Exceptions;
|
||||||
|
|
||||||
|
public class UserNotFoundException(int id) : BaseException(EErrorCategory.DataNotFoundError,$"User with ID {id} not found.")
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
12
Application/Interfaces/Repositories/IKillRepository.cs
Normal file
12
Application/Interfaces/Repositories/IKillRepository.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
using Domain.Entities;
|
||||||
|
|
||||||
|
namespace Application.Interfaces.Repositories;
|
||||||
|
|
||||||
|
public interface IKillRepository
|
||||||
|
{
|
||||||
|
public IEnumerable<Kill> GetAllKills();
|
||||||
|
|
||||||
|
public bool TryGetKillById(int id, out Kill? kill);
|
||||||
|
public void AddKill(Kill kill);
|
||||||
|
public bool RemoveKill(Kill kill);
|
||||||
|
}
|
||||||
11
Application/Interfaces/Repositories/IUserRepository.cs
Normal file
11
Application/Interfaces/Repositories/IUserRepository.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
using Domain.Entities;
|
||||||
|
|
||||||
|
namespace Application.Interfaces.Repositories;
|
||||||
|
|
||||||
|
public interface IUserRepository
|
||||||
|
{
|
||||||
|
public IEnumerable<User> GetAllUsers();
|
||||||
|
public bool TryGetUserById(int id, out User? user);
|
||||||
|
public bool AddUser(User user);
|
||||||
|
public bool UpdateUser(User user);
|
||||||
|
}
|
||||||
14
Application/Interfaces/Services/IKillService.cs
Normal file
14
Application/Interfaces/Services/IKillService.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
using Application.Interfaces.Repositories;
|
||||||
|
using Domain.Entities;
|
||||||
|
|
||||||
|
namespace Application.Interfaces.Services;
|
||||||
|
|
||||||
|
public interface IKillService
|
||||||
|
{
|
||||||
|
public IEnumerable<Kill> GetAllKills();
|
||||||
|
public Kill GetKillById(int id);
|
||||||
|
public IEnumerable<Kill> GetKillsByUserId(int userId);
|
||||||
|
public IEnumerable<Kill> GetKillsByUserId(IEnumerable<int> userIds);
|
||||||
|
public bool AddKill(Kill kill);
|
||||||
|
public bool RemoveKill(Kill kill);
|
||||||
|
}
|
||||||
12
Application/Interfaces/Services/IUserService.cs
Normal file
12
Application/Interfaces/Services/IUserService.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
using Application.Interfaces.Repositories;
|
||||||
|
using Domain.Entities;
|
||||||
|
|
||||||
|
namespace Application.Interfaces.Services;
|
||||||
|
|
||||||
|
public interface IUserService
|
||||||
|
{
|
||||||
|
public IEnumerable<User> GetAllUsers();
|
||||||
|
public User GetUserById(int id);
|
||||||
|
public bool CreateUser(string username, string password, string email);
|
||||||
|
public bool UpdateUser(int id, string username, string password, string email);
|
||||||
|
}
|
||||||
48
Application/Services/KillService.cs
Normal file
48
Application/Services/KillService.cs
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
using Application.Interfaces.Repositories;
|
||||||
|
using Application.Interfaces.Services;
|
||||||
|
using Domain.Entities;
|
||||||
|
|
||||||
|
namespace Application.Services;
|
||||||
|
|
||||||
|
public class KillService(IKillRepository repository, IUserService userService) : IKillService
|
||||||
|
{
|
||||||
|
private IKillRepository Repository { get; } = repository;
|
||||||
|
|
||||||
|
public IEnumerable<Kill> GetAllKills()
|
||||||
|
{
|
||||||
|
return Repository.GetAllKills();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Kill GetKillById(int id)
|
||||||
|
{
|
||||||
|
if (!Repository.TryGetKillById(id, out var kill))
|
||||||
|
{
|
||||||
|
throw new KeyNotFoundException($"Failed to find kill with id: {id}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return kill;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<Kill> GetKillsByUserId(int userId)
|
||||||
|
{
|
||||||
|
return Repository.GetAllKills().Where(x => x.UserId == userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<Kill> GetKillsByUserId(IEnumerable<int> userIds)
|
||||||
|
{
|
||||||
|
return Repository.GetAllKills().Where(x => userIds.Contains(x.UserId));
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddKill(Kill kill)
|
||||||
|
{
|
||||||
|
Repository.AddKill(kill);
|
||||||
|
var user = userService.GetUserById(kill.UserId);
|
||||||
|
user.Kills.Append(kill);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool RemoveKill(Kill kill)
|
||||||
|
{
|
||||||
|
return Repository.RemoveKill(kill);
|
||||||
|
}
|
||||||
|
}
|
||||||
71
Application/Services/UserService.cs
Normal file
71
Application/Services/UserService.cs
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
using Application.Exceptions;
|
||||||
|
using Application.Interfaces.Repositories;
|
||||||
|
using Application.Interfaces.Services;
|
||||||
|
using Domain.Entities;
|
||||||
|
|
||||||
|
namespace Application.Services;
|
||||||
|
|
||||||
|
public class UserService(IUserRepository repository) : IUserService
|
||||||
|
{
|
||||||
|
private IUserRepository Repository { get; } = repository;
|
||||||
|
|
||||||
|
public IEnumerable<User> GetAllUsers()
|
||||||
|
{
|
||||||
|
return Repository.GetAllUsers();
|
||||||
|
}
|
||||||
|
|
||||||
|
public User GetUserById(int id)
|
||||||
|
{
|
||||||
|
if (!Repository.TryGetUserById(id, out var user))
|
||||||
|
{
|
||||||
|
throw new ArgumentException($"User with id {id} not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CreateUser(string username, string password, string email)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password) || string.IsNullOrEmpty(email))
|
||||||
|
{
|
||||||
|
throw new InsufficientParametersException(["username", "password", "email"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Repository.GetAllUsers().Any(x => x.Username == username))
|
||||||
|
{
|
||||||
|
throw new DuplicateUsernameException(username);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Repository.GetAllUsers().Any(x => x.Email == email))
|
||||||
|
{
|
||||||
|
throw new DuplicateEmailException(email);
|
||||||
|
}
|
||||||
|
|
||||||
|
var user = new User
|
||||||
|
{
|
||||||
|
Id = Repository.GetAllUsers().Count() + 1,
|
||||||
|
Username = username,
|
||||||
|
Password = password,
|
||||||
|
Email = email
|
||||||
|
};
|
||||||
|
return Repository.AddUser(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool UpdateUser(int id, string username, string password, string email)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password) || string.IsNullOrEmpty(email))
|
||||||
|
{
|
||||||
|
throw new InsufficientParametersException(["username", "password", "email"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Repository.TryGetUserById(id, out var user))
|
||||||
|
{
|
||||||
|
throw new UserNotFoundException(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
user.Email = email;
|
||||||
|
user.Password = password;
|
||||||
|
user.Username = username;
|
||||||
|
return Repository.UpdateUser(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
10
Domain/Domain.csproj
Normal file
10
Domain/Domain.csproj
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<LangVersion>latest</LangVersion>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
10
Domain/Entities/Kill.cs
Normal file
10
Domain/Entities/Kill.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
namespace Domain.Entities;
|
||||||
|
|
||||||
|
public class Kill
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int UserId { get; set; }
|
||||||
|
public User User { get; set; }
|
||||||
|
public string Victim { get; set; }
|
||||||
|
public double Damage { get; set; }
|
||||||
|
}
|
||||||
11
Domain/Entities/User.cs
Normal file
11
Domain/Entities/User.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
namespace Domain.Entities;
|
||||||
|
|
||||||
|
public class User
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string Username { get; set; }
|
||||||
|
public string Password { get; set; }
|
||||||
|
public string Email { get; set; }
|
||||||
|
|
||||||
|
public IEnumerable<Kill> Kills { get; set; } = new List<Kill>();
|
||||||
|
}
|
||||||
8
Domain/Enums/EErrorCategory.cs
Normal file
8
Domain/Enums/EErrorCategory.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
namespace Domain.Enums;
|
||||||
|
|
||||||
|
public enum EErrorCategory
|
||||||
|
{
|
||||||
|
UserValidationError,
|
||||||
|
DataNotFoundError,
|
||||||
|
RequestError,
|
||||||
|
}
|
||||||
7
Domain/Enums/ErrorCategories/EUserValidationError.cs
Normal file
7
Domain/Enums/ErrorCategories/EUserValidationError.cs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
namespace Domain.Enums.ErrorCategories;
|
||||||
|
|
||||||
|
public enum EUserValidationError
|
||||||
|
{
|
||||||
|
DuplicateUserName,
|
||||||
|
DuplicateEmail,
|
||||||
|
}
|
||||||
34
GraphQLTEST.sln
Normal file
34
GraphQLTEST.sln
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Presentation", "Presentation\Presentation.csproj", "{19ACF9DE-92C8-4F93-AD6D-30C68DB5C002}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Domain", "Domain\Domain.csproj", "{F9677CF6-6EBB-49D5-B9CA-822B1F5C681F}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Application", "Application\Application.csproj", "{D4834024-39F8-44A5-8FBE-99A2D4D64992}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Infrastructure", "Infrastructure\Infrastructure.csproj", "{8E0F3BFD-CC6E-4FE0-B6F8-65427C3B8602}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{19ACF9DE-92C8-4F93-AD6D-30C68DB5C002}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{19ACF9DE-92C8-4F93-AD6D-30C68DB5C002}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{19ACF9DE-92C8-4F93-AD6D-30C68DB5C002}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{19ACF9DE-92C8-4F93-AD6D-30C68DB5C002}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{F9677CF6-6EBB-49D5-B9CA-822B1F5C681F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{F9677CF6-6EBB-49D5-B9CA-822B1F5C681F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{F9677CF6-6EBB-49D5-B9CA-822B1F5C681F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{F9677CF6-6EBB-49D5-B9CA-822B1F5C681F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{D4834024-39F8-44A5-8FBE-99A2D4D64992}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{D4834024-39F8-44A5-8FBE-99A2D4D64992}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{D4834024-39F8-44A5-8FBE-99A2D4D64992}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{D4834024-39F8-44A5-8FBE-99A2D4D64992}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{8E0F3BFD-CC6E-4FE0-B6F8-65427C3B8602}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{8E0F3BFD-CC6E-4FE0-B6F8-65427C3B8602}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{8E0F3BFD-CC6E-4FE0-B6F8-65427C3B8602}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{8E0F3BFD-CC6E-4FE0-B6F8-65427C3B8602}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
5
GraphQLTEST.sln.DotSettings.user
Normal file
5
GraphQLTEST.sln.DotSettings.user
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AIDataLoader_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FSourcesCache_003Ff56ba8265fda8fe0b0b9ffde6310d25a34d11dd11e8013cfa9c84f7e824627_003FIDataLoader_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AIReadOnlyCollection_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FSourcesCache_003Fe1d3a46aba86a5ba1b6523b72cd6d2c3aea5d8aa082cb4e1ecc37cacb87_003FIReadOnlyCollection_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AIReadOnlyList_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FSourcesCache_003Fe28dab75134294818f77c8f45362c677acb91189b639a96db250f6ec69abdb_003FIReadOnlyList_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AThrowHelper_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fbf56714b34b64c2e9e85a0382d02720aaa910_003Fa6_003F5c042f18_003FThrowHelper_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary>
|
||||||
12
Infrastructure/Database/AppDbContext.cs
Normal file
12
Infrastructure/Database/AppDbContext.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
using Domain.Entities;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace Infrastructure.Database;
|
||||||
|
|
||||||
|
public class AppDbContext : DbContext
|
||||||
|
{
|
||||||
|
public DbSet<User> Users { get; set; }
|
||||||
|
public DbSet<Kill> Kills { get; set; }
|
||||||
|
|
||||||
|
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options){}
|
||||||
|
}
|
||||||
42
Infrastructure/Database/DbSeeder.cs
Normal file
42
Infrastructure/Database/DbSeeder.cs
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
using Bogus;
|
||||||
|
using Domain.Entities;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace Infrastructure.Database;
|
||||||
|
|
||||||
|
public class DbSeeder
|
||||||
|
{
|
||||||
|
public static async Task SeedAsync(DbContext dbContext, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var exampleUser = await dbContext.Set<User>().FirstOrDefaultAsync(u => u.Email.EndsWith("@example.com"), cancellationToken);
|
||||||
|
if (exampleUser == null)
|
||||||
|
{
|
||||||
|
dbContext.Set<User>().AddRange([
|
||||||
|
new User(){Id = 1, Email = "sunpy@example.com", Password = "iAmJaneEldenRing21", Username = "sunpy"},
|
||||||
|
new User(){Id = 2, Email = "yui@example.com", Password = "ILoveHalfLife98", Username = "yui"},
|
||||||
|
new User(){Id = 3, Email = "johnny@example.com", Password = "iAmCyberPunk77", Username = "johnny"},
|
||||||
|
new User(){Id = 4, Email = "skibidi@example.com", Password = "iHateToilets67", Username = "skibidi_hater"},
|
||||||
|
]);
|
||||||
|
await dbContext.SaveChangesAsync(cancellationToken);
|
||||||
|
}
|
||||||
|
var exampleKill = dbContext.Set<Kill>().FirstOrDefault(k => k.UserId == 1);
|
||||||
|
if (exampleKill == null)
|
||||||
|
{
|
||||||
|
var killSet = dbContext.Set<Kill>();
|
||||||
|
var fake = new Faker<Kill>()
|
||||||
|
.RuleFor(k => k.Id, f => ++f.IndexVariable)
|
||||||
|
.RuleFor(k => k.User, f => f.PickRandom(dbContext.Set<User>().ToList()))
|
||||||
|
.RuleFor(k => k.UserId, (_, k) => k.User.Id)
|
||||||
|
.RuleFor(k => k.Damage, f => f.Random.Double(1, 100))
|
||||||
|
.RuleFor(k => k.Victim, f => f.Name.FirstName());
|
||||||
|
var fakeKills = fake.Generate(500).ToList();
|
||||||
|
await killSet.AddRangeAsync(fakeKills, cancellationToken);
|
||||||
|
await dbContext.SaveChangesAsync(cancellationToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Seed(DbContext dbContext)
|
||||||
|
{
|
||||||
|
Task.Run(() => SeedAsync(dbContext, CancellationToken.None)).Wait();
|
||||||
|
}
|
||||||
|
}
|
||||||
23
Infrastructure/DependencyInjection.cs
Normal file
23
Infrastructure/DependencyInjection.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
using Application.Interfaces.Repositories;
|
||||||
|
using Infrastructure.Database;
|
||||||
|
using Infrastructure.Repositories;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
namespace Infrastructure;
|
||||||
|
|
||||||
|
public static class DependencyInjection
|
||||||
|
{
|
||||||
|
public static IServiceCollection AddInfrastructure(this IServiceCollection services)
|
||||||
|
{
|
||||||
|
return services.AddDbContextFactory<AppDbContext>(options =>
|
||||||
|
options
|
||||||
|
.UseInMemoryDatabase("Skibibase")
|
||||||
|
.UseSeeding((c, _) => DbSeeder.Seed(c))
|
||||||
|
.UseAsyncSeeding((async (context, _, token) => await DbSeeder.SeedAsync(context, token)))
|
||||||
|
.EnableSensitiveDataLogging()
|
||||||
|
)
|
||||||
|
.AddScoped<IUserRepository, UserRepository>()
|
||||||
|
.AddScoped<IKillRepository, KillRepository>();
|
||||||
|
}
|
||||||
|
}
|
||||||
21
Infrastructure/Infrastructure.csproj
Normal file
21
Infrastructure/Infrastructure.csproj
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<LangVersion>latest</LangVersion>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Application\Application.csproj" />
|
||||||
|
<ProjectReference Include="..\Domain\Domain.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Bogus" Version="35.6.5" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="10.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
34
Infrastructure/Repositories/KillRepository.cs
Normal file
34
Infrastructure/Repositories/KillRepository.cs
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
using Application.Interfaces.Repositories;
|
||||||
|
using Domain.Entities;
|
||||||
|
using Infrastructure.Database;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace Infrastructure.Repositories;
|
||||||
|
|
||||||
|
public class KillRepository(AppDbContext context) : IKillRepository
|
||||||
|
{
|
||||||
|
public IEnumerable<Kill> GetAllKills()
|
||||||
|
{
|
||||||
|
context.Database.EnsureCreated();
|
||||||
|
return context.Kills.AsNoTracking();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGetKillById(int id, out Kill? kill)
|
||||||
|
{
|
||||||
|
kill = context.Kills.FirstOrDefault(k => k.Id == id);
|
||||||
|
|
||||||
|
return kill != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddKill(Kill kill)
|
||||||
|
{
|
||||||
|
context.Kills.Add(kill);
|
||||||
|
context.SaveChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool RemoveKill(Kill kill)
|
||||||
|
{
|
||||||
|
context.Kills.Remove(kill);
|
||||||
|
return context.SaveChanges() > 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
33
Infrastructure/Repositories/UserRepository.cs
Normal file
33
Infrastructure/Repositories/UserRepository.cs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
using Application.Interfaces.Repositories;
|
||||||
|
using Domain.Entities;
|
||||||
|
using Infrastructure.Database;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace Infrastructure.Repositories;
|
||||||
|
|
||||||
|
public class UserRepository(AppDbContext context) : IUserRepository
|
||||||
|
{
|
||||||
|
public IEnumerable<User> GetAllUsers()
|
||||||
|
{
|
||||||
|
context.Database.EnsureCreated();
|
||||||
|
return context.Users.AsNoTracking();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGetUserById(int id, out User? user)
|
||||||
|
{
|
||||||
|
user = context.Users.FirstOrDefault(u => u.Id == id);
|
||||||
|
return user != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddUser(User user)
|
||||||
|
{
|
||||||
|
context.Users.Add(user);
|
||||||
|
return context.SaveChanges() != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool UpdateUser(User user)
|
||||||
|
{
|
||||||
|
context.Users.Update(user);
|
||||||
|
return context.SaveChanges() != 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
28
Presentation/GraphQL/DataLoaders/KillsDataLoader.cs
Normal file
28
Presentation/GraphQL/DataLoaders/KillsDataLoader.cs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
using Application.Interfaces.Services;
|
||||||
|
using Domain.Entities;
|
||||||
|
using GreenDonut.Data;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
namespace GraphQLTEST.GraphQL.DataLoaders;
|
||||||
|
|
||||||
|
public class KillsByUserDataLoader : GroupedDataLoader<int, Kill>{
|
||||||
|
private readonly IServiceProvider _serviceProvider;
|
||||||
|
|
||||||
|
public KillsByUserDataLoader(
|
||||||
|
IServiceProvider serviceProvider,
|
||||||
|
IBatchScheduler batchScheduler,
|
||||||
|
DataLoaderOptions options): base(batchScheduler, options){
|
||||||
|
_serviceProvider = serviceProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task<ILookup<int, Kill>> LoadGroupedBatchAsync(IReadOnlyList<int> keys, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
await using var scope = _serviceProvider.CreateAsyncScope();
|
||||||
|
var service = scope.ServiceProvider.GetRequiredService<IKillService>();
|
||||||
|
|
||||||
|
return await service.GetKillsByUserId(keys)
|
||||||
|
.ToAsyncEnumerable()
|
||||||
|
.ToLookupAsync(k => k.UserId, cancellationToken: cancellationToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
12
Presentation/GraphQL/ErrorFilters/LoggingErrorFilter.cs
Normal file
12
Presentation/GraphQL/ErrorFilters/LoggingErrorFilter.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
using HotChocolate.Execution;
|
||||||
|
|
||||||
|
namespace GraphQLTEST.GraphQL.ErrorFilters;
|
||||||
|
|
||||||
|
public class LoggingErrorFilter : IErrorFilter
|
||||||
|
{
|
||||||
|
public IError OnError(IError error)
|
||||||
|
{
|
||||||
|
Console.WriteLine(error.Exception?.ToString() ?? error.Message);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
}
|
||||||
23
Presentation/GraphQL/ErrorFilters/UserFriendlyErrorFilter.cs
Normal file
23
Presentation/GraphQL/ErrorFilters/UserFriendlyErrorFilter.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using Application.Exceptions;
|
||||||
|
using HotChocolate.Execution;
|
||||||
|
|
||||||
|
namespace GraphQLTEST.GraphQL.ErrorFilters;
|
||||||
|
|
||||||
|
public class UserFriendlyErrorFilter : IErrorFilter
|
||||||
|
{
|
||||||
|
public IError OnError(IError error)
|
||||||
|
{
|
||||||
|
if (error.Exception is BaseException baseException)
|
||||||
|
{
|
||||||
|
return ErrorBuilder
|
||||||
|
.FromError(error)
|
||||||
|
.SetMessage(baseException?.Message ?? "Unknown Error")
|
||||||
|
.SetExtension("errorCategory", baseException?.Category)
|
||||||
|
.SetExtension("errorCode", baseException?.GetType().Name)
|
||||||
|
.Build();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ErrorBuilder.FromError(error).SetMessage(error.Exception?.Message ?? "Unknown Error").Build();
|
||||||
|
}
|
||||||
|
}
|
||||||
6
Presentation/GraphQL/MutationType.cs
Normal file
6
Presentation/GraphQL/MutationType.cs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
namespace GraphQLTEST.GraphQL;
|
||||||
|
|
||||||
|
public class MutationType
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
17
Presentation/GraphQL/Mutations/KillMutations.cs
Normal file
17
Presentation/GraphQL/Mutations/KillMutations.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
using Application.Interfaces.Services;
|
||||||
|
using Domain.Entities;
|
||||||
|
using HotChocolate.Subscriptions;
|
||||||
|
|
||||||
|
namespace GraphQLTEST.GraphQL.Mutations;
|
||||||
|
|
||||||
|
[ExtendObjectType(nameof(MutationType))]
|
||||||
|
public class KillMutations
|
||||||
|
{
|
||||||
|
public async Task<Kill> RemoveKill(int id, [Service] IKillService service, [Service] ITopicEventSender eventSender, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var kill = service.GetKillById(id);
|
||||||
|
service.RemoveKill(kill);
|
||||||
|
await eventSender.SendAsync(nameof(RemoveKill), kill, cancellationToken);
|
||||||
|
return kill;
|
||||||
|
}
|
||||||
|
}
|
||||||
32
Presentation/GraphQL/Mutations/UserMutations.cs
Normal file
32
Presentation/GraphQL/Mutations/UserMutations.cs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
using Application;
|
||||||
|
using Application.Interfaces.Services;
|
||||||
|
using Application.Services;
|
||||||
|
using Domain.Entities;
|
||||||
|
using GraphQLTEST.GraphQL.Subscriptions;
|
||||||
|
using HotChocolate.Subscriptions;
|
||||||
|
|
||||||
|
namespace GraphQLTEST.GraphQL.Mutations;
|
||||||
|
|
||||||
|
[ExtendObjectType(nameof(MutationType))]
|
||||||
|
public class UserMutations
|
||||||
|
{
|
||||||
|
public async Task<bool> AddUser(string username, string email, string password, [Service] IUserService service) =>
|
||||||
|
await Task.Run(() => service.CreateUser(username, password, email));
|
||||||
|
|
||||||
|
public async Task<Kill> AddKill(
|
||||||
|
string victim,
|
||||||
|
double damage,
|
||||||
|
int userId,
|
||||||
|
[Service] IKillService killService,
|
||||||
|
[Service] IUserService userService,
|
||||||
|
[Service] ITopicEventSender eventSender,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var user = userService.GetUserById(userId);
|
||||||
|
var kill = new Kill
|
||||||
|
{ Id = Random.Shared.Next(0, 100), Damage = damage, User = user, UserId = user.Id, Victim = victim };
|
||||||
|
killService.AddKill(kill);
|
||||||
|
await eventSender.SendAsync(nameof(UserSubscriptions.KillAdded), kill, cancellationToken);
|
||||||
|
return kill;
|
||||||
|
}
|
||||||
|
}
|
||||||
7
Presentation/GraphQL/Queries/KillQueries.cs
Normal file
7
Presentation/GraphQL/Queries/KillQueries.cs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
namespace GraphQLTEST.GraphQL.Queries;
|
||||||
|
|
||||||
|
[QueryType]
|
||||||
|
public class KillQueries
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
13
Presentation/GraphQL/Queries/UserQueries.cs
Normal file
13
Presentation/GraphQL/Queries/UserQueries.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
using Application;
|
||||||
|
using Application.Interfaces.Services;
|
||||||
|
using Domain.Entities;
|
||||||
|
|
||||||
|
namespace GraphQLTEST.GraphQL.Queries;
|
||||||
|
|
||||||
|
[QueryType]
|
||||||
|
public class UserQueries
|
||||||
|
{
|
||||||
|
[UseProjection]
|
||||||
|
[UseFiltering]
|
||||||
|
public IEnumerable<User> GetUsers([Service] IUserService service) => service.GetAllUsers();
|
||||||
|
}
|
||||||
6
Presentation/GraphQL/SubscriptionType.cs
Normal file
6
Presentation/GraphQL/SubscriptionType.cs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
namespace GraphQLTEST.GraphQL;
|
||||||
|
|
||||||
|
public class SubscriptionType
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
13
Presentation/GraphQL/Subscriptions/UserSubscriptions.cs
Normal file
13
Presentation/GraphQL/Subscriptions/UserSubscriptions.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
using Domain.Entities;
|
||||||
|
using GraphQLTEST.GraphQL.Mutations;
|
||||||
|
using HotChocolate.Execution;
|
||||||
|
using HotChocolate.Subscriptions;
|
||||||
|
|
||||||
|
namespace GraphQLTEST.GraphQL.Subscriptions;
|
||||||
|
|
||||||
|
[ExtendObjectType(nameof(SubscriptionType))]
|
||||||
|
public class UserSubscriptions
|
||||||
|
{
|
||||||
|
[Subscribe]
|
||||||
|
public Kill KillAdded([EventMessage] Kill kill) => kill;
|
||||||
|
}
|
||||||
12
Presentation/GraphQL/Types/KillNode.cs
Normal file
12
Presentation/GraphQL/Types/KillNode.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
using Domain.Entities;
|
||||||
|
|
||||||
|
namespace GraphQLTEST.GraphQL.Types;
|
||||||
|
|
||||||
|
public class KillNode : ObjectType<Kill>
|
||||||
|
{
|
||||||
|
protected override void Configure(IObjectTypeDescriptor<Kill> descriptor)
|
||||||
|
{
|
||||||
|
descriptor.Ignore(x => x.Id);
|
||||||
|
descriptor.Ignore(x => x.UserId);
|
||||||
|
}
|
||||||
|
}
|
||||||
26
Presentation/GraphQL/Types/UserNode.cs
Normal file
26
Presentation/GraphQL/Types/UserNode.cs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
using System.Security.Principal;
|
||||||
|
using Application.Interfaces.Services;
|
||||||
|
using Domain.Entities;
|
||||||
|
using GraphQLTEST.GraphQL.DataLoaders;
|
||||||
|
using GreenDonut.Data;
|
||||||
|
using HotChocolate.Types.Pagination;
|
||||||
|
|
||||||
|
namespace GraphQLTEST.GraphQL.Types;
|
||||||
|
|
||||||
|
public class UserNode : ObjectType<User>
|
||||||
|
{
|
||||||
|
protected override void Configure(IObjectTypeDescriptor<User> descriptor)
|
||||||
|
{
|
||||||
|
descriptor.Ignore(x => x.Id);
|
||||||
|
descriptor.Ignore(x => x.Password);
|
||||||
|
descriptor.Field(x => x.Kills)
|
||||||
|
.UsePaging()
|
||||||
|
.UseFiltering()
|
||||||
|
.ParentRequires<User>(x => nameof(x.Id))
|
||||||
|
.Resolve(async (r, t) =>
|
||||||
|
{
|
||||||
|
User parent = r.Parent<User>();
|
||||||
|
return await r.DataLoader<KillsByUserDataLoader>().LoadAsync(parent.Id, t);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
30
Presentation/Presentation.csproj
Normal file
30
Presentation/Presentation.csproj
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<LangVersion>latest</LangVersion>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<RootNamespace>GraphQLTEST</RootNamespace>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="GreenDonut.Data" Version="16.0.0-p.10.1" />
|
||||||
|
<PackageReference Include="GreenDonut.Data.EntityFramework" Version="16.0.0-p.10.1" />
|
||||||
|
<PackageReference Include="HotChocolate" Version="16.0.0-p.10.1" />
|
||||||
|
<PackageReference Include="HotChocolate.AspNetCore" Version="16.0.0-p.10.1" />
|
||||||
|
<PackageReference Include="HotChocolate.AspNetCore.CommandLine" Version="16.0.0-p.10.1" />
|
||||||
|
<PackageReference Include="HotChocolate.AspNetCore.Subscriptions" Version="10.5.5" />
|
||||||
|
<PackageReference Include="HotChocolate.Data" Version="16.0.0-p.10.1" />
|
||||||
|
<PackageReference Include="HotChocolate.Types.Analyzers" Version="16.0.0-p.10.1" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.3.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Application\Application.csproj" />
|
||||||
|
<ProjectReference Include="..\Domain\Domain.csproj" />
|
||||||
|
<ProjectReference Include="..\Infrastructure\Infrastructure.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
42
Presentation/Program.cs
Normal file
42
Presentation/Program.cs
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
using Application;
|
||||||
|
using GraphQLTEST.GraphQL;
|
||||||
|
using GraphQLTEST.GraphQL.ErrorFilters;
|
||||||
|
using GraphQLTEST.GraphQL.Mutations;
|
||||||
|
using Infrastructure;
|
||||||
|
using Infrastructure.Database;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
|
||||||
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
|
builder.Services.AddApplication();
|
||||||
|
builder.Services.AddInfrastructure();
|
||||||
|
|
||||||
|
builder
|
||||||
|
.Services.AddGraphQLServer()
|
||||||
|
.AddMutationType<MutationType>()
|
||||||
|
.AddSubscriptionType<SubscriptionType>()
|
||||||
|
.AddInMemorySubscriptions()
|
||||||
|
.AddTypes()
|
||||||
|
.AddPagingArguments()
|
||||||
|
.AddQueryContext()
|
||||||
|
.AddSorting()
|
||||||
|
.AddFiltering()
|
||||||
|
.AddProjections()
|
||||||
|
.AddErrorFilter<LoggingErrorFilter>()
|
||||||
|
.AddErrorFilter<UserFriendlyErrorFilter>()
|
||||||
|
.AddMutationConventions(
|
||||||
|
new MutationConventionOptions
|
||||||
|
{
|
||||||
|
InputArgumentName = "input",
|
||||||
|
InputTypeNamePattern = "{MutationName}Input",
|
||||||
|
PayloadTypeNamePattern = "{MutationName}Payload",
|
||||||
|
PayloadErrorTypeNamePattern = "{MutationName}Error",
|
||||||
|
PayloadErrorsFieldName = "errors",
|
||||||
|
ApplyToAllMutations = true,
|
||||||
|
});
|
||||||
|
var app = builder.Build();
|
||||||
|
|
||||||
|
app.MapGraphQL();
|
||||||
|
app.RunWithGraphQLCommands(args);
|
||||||
1
Presentation/Properties/ModuleInfo.cs
Normal file
1
Presentation/Properties/ModuleInfo.cs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
[assembly: Module("Types")]
|
||||||
Reference in New Issue
Block a user