initial commit
This commit is contained in:
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