Skip to content

Commit

Permalink
Introduce GraphQL
Browse files Browse the repository at this point in the history
  • Loading branch information
ipdae committed May 23, 2024
1 parent 4da8c35 commit e0907e0
Show file tree
Hide file tree
Showing 13 changed files with 330 additions and 0 deletions.
67 changes: 67 additions & 0 deletions MarketService/GraphTypes/AddressType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
using HotChocolate.Language;
using Libplanet.Crypto;

namespace MarketService.GraphTypes;

public class AddressType : ScalarType<Address, StringValueNode>
{
public AddressType() : base("address")
{
}

public override IValueNode ParseResult(object? resultValue)
{
return ParseValue(resultValue);
}

protected override Address ParseLiteral(StringValueNode valueSyntax)
{
return new Address(valueSyntax.Value);
}

protected override StringValueNode ParseValue(Address runtimeValue)
{
return new(Serialize(runtimeValue));
}

private static string Serialize(Address runtimeValue)
{
return runtimeValue.ToString();
}

public override bool TrySerialize(object? runtimeValue, out object? resultValue)
{
if (runtimeValue is null)
{
resultValue = null;
return true;
}

if (runtimeValue is Address a)
{
resultValue = Serialize(a);
return true;
}

resultValue = null;
return false;
}

public override bool TryDeserialize(object? resultValue, out object? runtimeValue)
{
if (resultValue is null)
{
runtimeValue = null;
return true;
}

if (resultValue is Address)
{
runtimeValue = resultValue;
return true;
}

runtimeValue = null;
return false;
}
}
13 changes: 13 additions & 0 deletions MarketService/GraphTypes/FungibleAssetValueProductFilterType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using HotChocolate.Data.Filters;
using MarketService.Models;

namespace MarketService.GraphTypes;

public class FungibleAssetValueProductFilterType: FilterInputType<FungibleAssetValueProductModel>
{
protected override void Configure(IFilterInputTypeDescriptor<FungibleAssetValueProductModel> descriptor)
{
descriptor.Field(f => f.SellerAgentAddress).Type<ProductFilterType.CustomAddressOperationFilterInputType>();
descriptor.Field(f => f.SellerAvatarAddress).Type<ProductFilterType.CustomAddressOperationFilterInputType>();
}
}
45 changes: 45 additions & 0 deletions MarketService/GraphTypes/FungibleAssetValueProductModelType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using MarketService.Models;

namespace MarketService.GraphTypes;

public class FungibleAssetValueProductModelType : ObjectType<FungibleAssetValueProductModel>
{
protected override void Configure(IObjectTypeDescriptor<FungibleAssetValueProductModel> descriptor)
{
descriptor.BindFieldsExplicitly();
descriptor
.Field(f => f.ProductId)
.Type<UuidType>();
descriptor
.Field(f => f.SellerAgentAddress)
.Type<AddressType>();
descriptor
.Field(f => f.SellerAvatarAddress)
.Type<AddressType>();
descriptor
.Field(f => f.Price)
.Type<DecimalType>();
descriptor
.Field(f => f.Quantity)
.Type<DecimalType>();
descriptor
.Field(f => f.RegisteredBlockIndex)
.Type<LongType>();
descriptor
.Field(f => f.Exist)
.Type<BooleanType>();
descriptor
.Field(f => f.Legacy)
.Type<BooleanType>();
descriptor
.Field(f => f.CreatedAt)
.Type<DateTimeType>();
descriptor
.Field(f => f.UnitPrice)
.Type<DecimalType>();
descriptor.Field(f => f.DecimalPlaces)
.Type<NonNullType<ByteType>>();
descriptor.Field(f => f.Ticker)
.Type<StringType>();
}
}
13 changes: 13 additions & 0 deletions MarketService/GraphTypes/ItemProductFilterType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using HotChocolate.Data.Filters;
using MarketService.Models;

namespace MarketService.GraphTypes;

public class ItemProductFilterType : FilterInputType<ItemProductModel>
{
protected override void Configure(IFilterInputTypeDescriptor<ItemProductModel> descriptor)
{
descriptor.Field(f => f.SellerAgentAddress).Type<ProductFilterType.CustomAddressOperationFilterInputType>();
descriptor.Field(f => f.SellerAvatarAddress).Type<ProductFilterType.CustomAddressOperationFilterInputType>();
}
}
60 changes: 60 additions & 0 deletions MarketService/GraphTypes/ItemProductModelType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using MarketService.Models;

namespace MarketService.GraphTypes;

public class ItemProductModelType : ObjectType<ItemProductModel>
{
protected override void Configure(IObjectTypeDescriptor<ItemProductModel> descriptor)
{
descriptor.BindFieldsExplicitly();
descriptor
.Field(f => f.ProductId)
.Type<UuidType>();
descriptor
.Field(f => f.SellerAgentAddress)
.Type<AddressType>();
descriptor
.Field(f => f.SellerAvatarAddress)
.Type<AddressType>();
descriptor
.Field(f => f.Price)
.Type<DecimalType>();
descriptor
.Field(f => f.Quantity)
.Type<DecimalType>();
descriptor
.Field(f => f.RegisteredBlockIndex)
.Type<LongType>();
descriptor
.Field(f => f.Exist)
.Type<BooleanType>();
descriptor
.Field(f => f.Legacy)
.Type<BooleanType>();
descriptor
.Field(f => f.CreatedAt)
.Type<DateTimeType>();
descriptor
.Field(f => f.UnitPrice)
.Type<DecimalType>();
descriptor.Field(f => f.ItemId)
.Type<NonNullType<IntType>>();
descriptor.Field(f => f.Grade)
.Type<NonNullType<IntType>>();
descriptor
.Field(f => f.CreatedAt)
.Type<DateTimeType>();
descriptor.Field(f => f.ItemType);
descriptor.Field(f => f.ItemSubType);
descriptor.Field(f => f.ElementalType);
descriptor.Field(f => f.SetId);
descriptor.Field(f => f.CombatPoint);
descriptor.Field(f => f.Level);
descriptor.Field(f => f.Crystal);
descriptor.Field(f => f.CrystalPerPrice);
descriptor.Field(f => f.OptionCountFromCombination);
descriptor
.Field(f => f.Skills)
.Type<ListType<SkillModelType>>();
}
}
22 changes: 22 additions & 0 deletions MarketService/GraphTypes/ProductFilterType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using HotChocolate.Data.Filters;
using Libplanet.Crypto;
using MarketService.Models;

namespace MarketService.GraphTypes;

public class ProductFilterType : FilterInputType<ProductModel>
{
protected override void Configure(IFilterInputTypeDescriptor<ProductModel> descriptor)
{
descriptor.Field(f => f.SellerAgentAddress).Type<CustomAddressOperationFilterInputType>();
descriptor.Field(f => f.SellerAvatarAddress).Type<CustomAddressOperationFilterInputType>();
}

public class CustomAddressOperationFilterInputType : StringOperationFilterInputType
{
protected override void Configure(IFilterInputTypeDescriptor descriptor)
{
descriptor.Operation(DefaultFilterOperations.Equals).Type<AddressType>();
}
}
}
12 changes: 12 additions & 0 deletions MarketService/GraphTypes/ProductModelType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using MarketService.Models;

namespace MarketService.GraphTypes;

public class ProductModelType : UnionType<ProductModel>
{
protected override void Configure(IUnionTypeDescriptor descriptor)
{
descriptor.Type<FungibleAssetValueProductModelType>();
descriptor.Type<ItemProductModelType>();
}
}
31 changes: 31 additions & 0 deletions MarketService/GraphTypes/QueryType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
namespace MarketService.GraphTypes;

public class QueryType : ObjectType<Query>
{
protected override void Configure(IObjectTypeDescriptor<Query> descriptor)
{
descriptor
.Field(f => Query.GetProducts(default!))
.Type<ListType<ProductModelType>>()
.UsePaging<ProductModelType>()
.UseProjection()
.UseFiltering<ProductFilterType>()
.UseSorting();

descriptor
.Field(f => Query.GetFavProducts(default!))
.Type<ListType<FungibleAssetValueProductModelType>>()
.UsePaging<FungibleAssetValueProductModelType>()
.UseProjection()
.UseFiltering<FungibleAssetValueProductFilterType>()
.UseSorting();

descriptor
.Field(f => Query.GetItemProducts(default!))
.Type<ListType<ItemProductModelType>>()
.UsePaging<ItemProductModelType>()
.UseProjection()
.UseFiltering<ItemProductFilterType>()
.UseSorting();
}
}
11 changes: 11 additions & 0 deletions MarketService/GraphTypes/SkillModelType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using MarketService.Models;

namespace MarketService.GraphTypes;

public class SkillModelType : ObjectType<SkillModel>
{
protected override void Configure(IObjectTypeDescriptor<SkillModel> descriptor)
{
descriptor.Ignore(f => f.ToResponse());
}
}
11 changes: 11 additions & 0 deletions MarketService/GraphTypes/StatModelType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using MarketService.Models;

namespace MarketService.GraphTypes;

public class StatModelType: ObjectType<StatModel>
{
protected override void Configure(IObjectTypeDescriptor<StatModel> descriptor)
{
descriptor.Ignore(f => f.ToResponse());
}
}
2 changes: 2 additions & 0 deletions MarketService/MarketService.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
<PackageReference Include="EFCore.NamingConventions" Version="7.0.2" />
<PackageReference Include="Grpc.Core" Version="2.41.0" />
<PackageReference Include="Grpc.Core.Api" Version="2.41.0" />
<PackageReference Include="HotChocolate.AspNetCore" Version="13.9.0" />
<PackageReference Include="HotChocolate.Data.EntityFramework" Version="13.9.0" />
<PackageReference Include="MagicOnion.Client" Version="5.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.2">
Expand Down
21 changes: 21 additions & 0 deletions MarketService/Program.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System.Text.Json.Serialization;
using HotChocolate.Types.Pagination;
using MarketService.GraphTypes;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics;

Expand Down Expand Up @@ -88,6 +90,15 @@ public void ConfigureServices(IServiceCollection services)
services.AddHealthChecks()
.AddDbContextCheck<MarketContext>()
.AddCheck<RpcNodeHealthCheck>(nameof(RpcNodeHealthCheck));
services
.AddGraphQLServer()
.RegisterDbContext<MarketContext>()
.AddQueryType<QueryType>()
.AddErrorFilter<GraphqlErrorFilter>()
.AddProjections()
.AddFiltering()
.AddSorting()
.SetPagingOptions(new PagingOptions());
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
Expand All @@ -101,8 +112,18 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapGraphQL();
endpoints.MapControllers();
endpoints.MapHealthChecks("/ping");
});
}

public class GraphqlErrorFilter : IErrorFilter
{
public IError OnError(IError error)
{
var msg = error.Exception?.Message ?? error.Message;
return error.WithMessage(msg);
}
}
}
22 changes: 22 additions & 0 deletions MarketService/Query.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using MarketService.Models;
using Microsoft.EntityFrameworkCore;

namespace MarketService;

public class Query
{
public static IQueryable<ProductModel> GetProducts([Service] MarketContext dbContext)
{
return dbContext.Products.AsNoTracking().AsQueryable();
}

public static IQueryable<FungibleAssetValueProductModel> GetFavProducts([Service] MarketContext dbContext)
{
return dbContext.FungibleAssetValueProducts.AsNoTracking().AsQueryable();
}

public static IQueryable<ItemProductModel> GetItemProducts([Service] MarketContext dbContext)
{
return dbContext.ItemProducts.AsNoTracking().AsQueryable();
}
}

0 comments on commit e0907e0

Please sign in to comment.