diff --git a/MarketService/GraphTypes/AddressType.cs b/MarketService/GraphTypes/AddressType.cs new file mode 100644 index 0000000..23a9af4 --- /dev/null +++ b/MarketService/GraphTypes/AddressType.cs @@ -0,0 +1,67 @@ +using HotChocolate.Language; +using Libplanet.Crypto; + +namespace MarketService.GraphTypes; + +public class AddressType : ScalarType +{ + 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; + } +} diff --git a/MarketService/GraphTypes/FungibleAssetValueProductFilterType.cs b/MarketService/GraphTypes/FungibleAssetValueProductFilterType.cs new file mode 100644 index 0000000..941877e --- /dev/null +++ b/MarketService/GraphTypes/FungibleAssetValueProductFilterType.cs @@ -0,0 +1,13 @@ +using HotChocolate.Data.Filters; +using MarketService.Models; + +namespace MarketService.GraphTypes; + +public class FungibleAssetValueProductFilterType: FilterInputType +{ + protected override void Configure(IFilterInputTypeDescriptor descriptor) + { + descriptor.Field(f => f.SellerAgentAddress).Type(); + descriptor.Field(f => f.SellerAvatarAddress).Type(); + } +} diff --git a/MarketService/GraphTypes/FungibleAssetValueProductModelType.cs b/MarketService/GraphTypes/FungibleAssetValueProductModelType.cs new file mode 100644 index 0000000..36c7962 --- /dev/null +++ b/MarketService/GraphTypes/FungibleAssetValueProductModelType.cs @@ -0,0 +1,45 @@ +using MarketService.Models; + +namespace MarketService.GraphTypes; + +public class FungibleAssetValueProductModelType : ObjectType +{ + protected override void Configure(IObjectTypeDescriptor descriptor) + { + descriptor.BindFieldsExplicitly(); + descriptor + .Field(f => f.ProductId) + .Type(); + descriptor + .Field(f => f.SellerAgentAddress) + .Type(); + descriptor + .Field(f => f.SellerAvatarAddress) + .Type(); + descriptor + .Field(f => f.Price) + .Type(); + descriptor + .Field(f => f.Quantity) + .Type(); + descriptor + .Field(f => f.RegisteredBlockIndex) + .Type(); + descriptor + .Field(f => f.Exist) + .Type(); + descriptor + .Field(f => f.Legacy) + .Type(); + descriptor + .Field(f => f.CreatedAt) + .Type(); + descriptor + .Field(f => f.UnitPrice) + .Type(); + descriptor.Field(f => f.DecimalPlaces) + .Type>(); + descriptor.Field(f => f.Ticker) + .Type(); + } +} diff --git a/MarketService/GraphTypes/ItemProductFilterType.cs b/MarketService/GraphTypes/ItemProductFilterType.cs new file mode 100644 index 0000000..e2e98e7 --- /dev/null +++ b/MarketService/GraphTypes/ItemProductFilterType.cs @@ -0,0 +1,13 @@ +using HotChocolate.Data.Filters; +using MarketService.Models; + +namespace MarketService.GraphTypes; + +public class ItemProductFilterType : FilterInputType +{ + protected override void Configure(IFilterInputTypeDescriptor descriptor) + { + descriptor.Field(f => f.SellerAgentAddress).Type(); + descriptor.Field(f => f.SellerAvatarAddress).Type(); + } +} diff --git a/MarketService/GraphTypes/ItemProductModelType.cs b/MarketService/GraphTypes/ItemProductModelType.cs new file mode 100644 index 0000000..5450ed5 --- /dev/null +++ b/MarketService/GraphTypes/ItemProductModelType.cs @@ -0,0 +1,60 @@ +using MarketService.Models; + +namespace MarketService.GraphTypes; + +public class ItemProductModelType : ObjectType +{ + protected override void Configure(IObjectTypeDescriptor descriptor) + { + descriptor.BindFieldsExplicitly(); + descriptor + .Field(f => f.ProductId) + .Type(); + descriptor + .Field(f => f.SellerAgentAddress) + .Type(); + descriptor + .Field(f => f.SellerAvatarAddress) + .Type(); + descriptor + .Field(f => f.Price) + .Type(); + descriptor + .Field(f => f.Quantity) + .Type(); + descriptor + .Field(f => f.RegisteredBlockIndex) + .Type(); + descriptor + .Field(f => f.Exist) + .Type(); + descriptor + .Field(f => f.Legacy) + .Type(); + descriptor + .Field(f => f.CreatedAt) + .Type(); + descriptor + .Field(f => f.UnitPrice) + .Type(); + descriptor.Field(f => f.ItemId) + .Type>(); + descriptor.Field(f => f.Grade) + .Type>(); + descriptor + .Field(f => f.CreatedAt) + .Type(); + 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>(); + } +} diff --git a/MarketService/GraphTypes/ProductFilterType.cs b/MarketService/GraphTypes/ProductFilterType.cs new file mode 100644 index 0000000..d9da218 --- /dev/null +++ b/MarketService/GraphTypes/ProductFilterType.cs @@ -0,0 +1,22 @@ +using HotChocolate.Data.Filters; +using Libplanet.Crypto; +using MarketService.Models; + +namespace MarketService.GraphTypes; + +public class ProductFilterType : FilterInputType +{ + protected override void Configure(IFilterInputTypeDescriptor descriptor) + { + descriptor.Field(f => f.SellerAgentAddress).Type(); + descriptor.Field(f => f.SellerAvatarAddress).Type(); + } + + public class CustomAddressOperationFilterInputType : StringOperationFilterInputType + { + protected override void Configure(IFilterInputTypeDescriptor descriptor) + { + descriptor.Operation(DefaultFilterOperations.Equals).Type(); + } + } +} diff --git a/MarketService/GraphTypes/ProductModelType.cs b/MarketService/GraphTypes/ProductModelType.cs new file mode 100644 index 0000000..f2a6bd8 --- /dev/null +++ b/MarketService/GraphTypes/ProductModelType.cs @@ -0,0 +1,12 @@ +using MarketService.Models; + +namespace MarketService.GraphTypes; + +public class ProductModelType : UnionType +{ + protected override void Configure(IUnionTypeDescriptor descriptor) + { + descriptor.Type(); + descriptor.Type(); + } +} diff --git a/MarketService/GraphTypes/QueryType.cs b/MarketService/GraphTypes/QueryType.cs new file mode 100644 index 0000000..e26d14d --- /dev/null +++ b/MarketService/GraphTypes/QueryType.cs @@ -0,0 +1,31 @@ +namespace MarketService.GraphTypes; + +public class QueryType : ObjectType +{ + protected override void Configure(IObjectTypeDescriptor descriptor) + { + descriptor + .Field(f => Query.GetProducts(default!)) + .Type>() + .UsePaging() + .UseProjection() + .UseFiltering() + .UseSorting(); + + descriptor + .Field(f => Query.GetFavProducts(default!)) + .Type>() + .UsePaging() + .UseProjection() + .UseFiltering() + .UseSorting(); + + descriptor + .Field(f => Query.GetItemProducts(default!)) + .Type>() + .UsePaging() + .UseProjection() + .UseFiltering() + .UseSorting(); + } +} diff --git a/MarketService/GraphTypes/SkillModelType.cs b/MarketService/GraphTypes/SkillModelType.cs new file mode 100644 index 0000000..e255995 --- /dev/null +++ b/MarketService/GraphTypes/SkillModelType.cs @@ -0,0 +1,11 @@ +using MarketService.Models; + +namespace MarketService.GraphTypes; + +public class SkillModelType : ObjectType +{ + protected override void Configure(IObjectTypeDescriptor descriptor) + { + descriptor.Ignore(f => f.ToResponse()); + } +} diff --git a/MarketService/GraphTypes/StatModelType.cs b/MarketService/GraphTypes/StatModelType.cs new file mode 100644 index 0000000..13ec9cb --- /dev/null +++ b/MarketService/GraphTypes/StatModelType.cs @@ -0,0 +1,11 @@ +using MarketService.Models; + +namespace MarketService.GraphTypes; + +public class StatModelType: ObjectType +{ + protected override void Configure(IObjectTypeDescriptor descriptor) + { + descriptor.Ignore(f => f.ToResponse()); + } +} diff --git a/MarketService/MarketService.csproj b/MarketService/MarketService.csproj index 33b45f5..9e59b84 100644 --- a/MarketService/MarketService.csproj +++ b/MarketService/MarketService.csproj @@ -13,6 +13,8 @@ + + diff --git a/MarketService/Program.cs b/MarketService/Program.cs index 4770ccb..0cd031b 100644 --- a/MarketService/Program.cs +++ b/MarketService/Program.cs @@ -1,4 +1,6 @@ using System.Text.Json.Serialization; +using HotChocolate.Types.Pagination; +using MarketService.GraphTypes; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Diagnostics; @@ -88,6 +90,15 @@ public void ConfigureServices(IServiceCollection services) services.AddHealthChecks() .AddDbContextCheck() .AddCheck(nameof(RpcNodeHealthCheck)); + services + .AddGraphQLServer() + .RegisterDbContext() + .AddQueryType() + .AddErrorFilter() + .AddProjections() + .AddFiltering() + .AddSorting() + .SetPagingOptions(new PagingOptions()); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) @@ -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); + } + } } diff --git a/MarketService/Query.cs b/MarketService/Query.cs new file mode 100644 index 0000000..c6f27a1 --- /dev/null +++ b/MarketService/Query.cs @@ -0,0 +1,22 @@ +using MarketService.Models; +using Microsoft.EntityFrameworkCore; + +namespace MarketService; + +public class Query +{ + public static IQueryable GetProducts([Service] MarketContext dbContext) + { + return dbContext.Products.AsNoTracking().AsQueryable(); + } + + public static IQueryable GetFavProducts([Service] MarketContext dbContext) + { + return dbContext.FungibleAssetValueProducts.AsNoTracking().AsQueryable(); + } + + public static IQueryable GetItemProducts([Service] MarketContext dbContext) + { + return dbContext.ItemProducts.AsNoTracking().AsQueryable(); + } +}