From a4e4495550ecf6a2be78e74233420e55833872c8 Mon Sep 17 00:00:00 2001 From: Ansul Goenka Date: Tue, 19 Apr 2022 17:21:50 -0500 Subject: [PATCH] Fixing resolvers --- .gitattributes | 63 ++++++ Author.cs | 12 ++ Book.cs | 14 ++ Data/DataRepository.cs | 86 ++++++++ DemoChoco.csproj | 14 ++ DemoChoco.sln | 25 +++ Models/Alien.cs | 9 + Models/Cat.cs | 21 ++ Models/CatCommand.cs | 9 + Models/ComplexInput.cs | 11 ++ Models/ComplexInput2.cs | 11 ++ Models/Dog.cs | 26 +++ Models/DogCommand.cs | 11 ++ Models/Human.cs | 9 + Models/IPet.cs | 7 + Models/ISentient.cs | 9 + Models/Query.cs | 107 ++++++++++ Program.cs | 57 ++++++ .../profile.arm.json | 113 +++++++++++ Properties/launchSettings.json | 28 +++ Types/AlienType.cs | 14 ++ Types/ArgumentsType.cs | 183 ++++++++++++++++++ Types/BeingType.cs | 14 ++ Types/CatInputType.cs | 16 ++ Types/CatOrDogType.cs | 15 ++ Types/CatType.cs | 40 ++++ Types/Complex2InputType.cs | 19 ++ Types/Complex3InputType.cs | 49 +++++ Types/ComplexDirective.cs | 24 +++ Types/ComplexInputType.cs | 13 ++ Types/CustomDirectiveType.cs | 37 ++++ Types/DogInputType.cs | 16 ++ Types/DogOrHumanType.cs | 15 ++ Types/DogType.cs | 19 ++ Types/FurColor.cs | 14 ++ Types/HumanOrAlienType.cs | 15 ++ Types/HumanType.cs | 25 +++ Types/IntelligentType.cs | 14 ++ Types/InvalidScalar.cs | 36 ++++ Types/MessageType.cs | 21 ++ Types/MutationType.cs | 39 ++++ Types/PetInputType.cs | 15 ++ Types/PetType.cs | 15 ++ Types/QueryType.cs | 46 +++++ Types/SentientType.cs | 14 ++ Types/SubscriptionType.cs | 25 +++ ValidationUtils.cs | 21 ++ appsettings.Development.json | 8 + appsettings.json | 9 + 49 files changed, 1433 insertions(+) create mode 100644 .gitattributes create mode 100644 Author.cs create mode 100644 Book.cs create mode 100644 Data/DataRepository.cs create mode 100644 DemoChoco.csproj create mode 100644 DemoChoco.sln create mode 100644 Models/Alien.cs create mode 100644 Models/Cat.cs create mode 100644 Models/CatCommand.cs create mode 100644 Models/ComplexInput.cs create mode 100644 Models/ComplexInput2.cs create mode 100644 Models/Dog.cs create mode 100644 Models/DogCommand.cs create mode 100644 Models/Human.cs create mode 100644 Models/IPet.cs create mode 100644 Models/ISentient.cs create mode 100644 Models/Query.cs create mode 100644 Program.cs create mode 100644 Properties/ServiceDependencies/DemoChoco20220411182001 - Web Deploy/profile.arm.json create mode 100644 Properties/launchSettings.json create mode 100644 Types/AlienType.cs create mode 100644 Types/ArgumentsType.cs create mode 100644 Types/BeingType.cs create mode 100644 Types/CatInputType.cs create mode 100644 Types/CatOrDogType.cs create mode 100644 Types/CatType.cs create mode 100644 Types/Complex2InputType.cs create mode 100644 Types/Complex3InputType.cs create mode 100644 Types/ComplexDirective.cs create mode 100644 Types/ComplexInputType.cs create mode 100644 Types/CustomDirectiveType.cs create mode 100644 Types/DogInputType.cs create mode 100644 Types/DogOrHumanType.cs create mode 100644 Types/DogType.cs create mode 100644 Types/FurColor.cs create mode 100644 Types/HumanOrAlienType.cs create mode 100644 Types/HumanType.cs create mode 100644 Types/IntelligentType.cs create mode 100644 Types/InvalidScalar.cs create mode 100644 Types/MessageType.cs create mode 100644 Types/MutationType.cs create mode 100644 Types/PetInputType.cs create mode 100644 Types/PetType.cs create mode 100644 Types/QueryType.cs create mode 100644 Types/SentientType.cs create mode 100644 Types/SubscriptionType.cs create mode 100644 ValidationUtils.cs create mode 100644 appsettings.Development.json create mode 100644 appsettings.json diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/Author.cs b/Author.cs new file mode 100644 index 0000000..93e493f --- /dev/null +++ b/Author.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace DemoChoco +{ + public class Author + { + public string Name { get; set; } + } +} diff --git a/Book.cs b/Book.cs new file mode 100644 index 0000000..7e42bf4 --- /dev/null +++ b/Book.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace DemoChoco +{ + public class Book + { + public string Title { get; set; } + + public Author Author { get; set; } + } +} diff --git a/Data/DataRepository.cs b/Data/DataRepository.cs new file mode 100644 index 0000000..31f282d --- /dev/null +++ b/Data/DataRepository.cs @@ -0,0 +1,86 @@ +using HotChocolate.Validation; +using System.Globalization; + +namespace DemoChoco.Data +{ + public class DataRepository + { + public List humans = new List + { + new Human + { + Name = "foo", + Address = "foo" + }, + new Human + { + Name = "foo2", + Address = "foo2" + } + }; + + public List dogs = new List + { + new Dog + { + Barks = true, + BarkVolume = 1, + Name = "Tofu", + Nickname = "Tofu", + Owner = new Human + { + Name = "foo", + Address = "foo" + } + }, + new Dog + { + Barks = true, + BarkVolume = 3, + Name = "Ink", + Nickname = "Ink" + } + }; + + public List cats = new List + { + new Cat + { + MeowVolume = 1, + Name = "Tofu", + Nickname = "Tofu" + }, + new Cat + { + MeowVolume = 3, + Name = "Ink", + Nickname = "Ink" + } + }; + + public string[] stringList = + { + "foo", "asd", "bar", "baz" + }; + + public void AddCat(List cat) + { + cats.Add(new Cat + { + Name = (string)cat[0], + MeowVolume = (int?)cat[2], + Nickname = (string)cat[1] + }); + } + + public void AddDog(List dog) + { + dogs.Add(new Dog + { + Name = (string)dog[0], + BarkVolume = (int?)dog[2], + Nickname = (string)dog[1] + }); + } + } +} diff --git a/DemoChoco.csproj b/DemoChoco.csproj new file mode 100644 index 0000000..928e2ed --- /dev/null +++ b/DemoChoco.csproj @@ -0,0 +1,14 @@ + + + + net6.0 + enable + enable + true + + + + + + + diff --git a/DemoChoco.sln b/DemoChoco.sln new file mode 100644 index 0000000..59e651d --- /dev/null +++ b/DemoChoco.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.1.32228.430 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DemoChoco", "DemoChoco.csproj", "{C9E76BAD-F7E1-44F5-ACF3-C30828F90FAD}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C9E76BAD-F7E1-44F5-ACF3-C30828F90FAD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C9E76BAD-F7E1-44F5-ACF3-C30828F90FAD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C9E76BAD-F7E1-44F5-ACF3-C30828F90FAD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C9E76BAD-F7E1-44F5-ACF3-C30828F90FAD}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {3F5908EA-4FFD-41EE-B616-3CE13F232F7C} + EndGlobalSection +EndGlobal diff --git a/Models/Alien.cs b/Models/Alien.cs new file mode 100644 index 0000000..056024b --- /dev/null +++ b/Models/Alien.cs @@ -0,0 +1,9 @@ +namespace HotChocolate.Validation +{ + public class Alien + : ISentient + { + public string Name { get; set; } + public string HomePlanet { get; set; } + } +} diff --git a/Models/Cat.cs b/Models/Cat.cs new file mode 100644 index 0000000..483d745 --- /dev/null +++ b/Models/Cat.cs @@ -0,0 +1,21 @@ +using HotChocolate.Validation.Types; + +namespace HotChocolate.Validation +{ + public class Cat + : IPet + { + public string Name { get; set; } + + public string Nickname { get; set; } + + public int? MeowVolume { get; set; } + + public FurColor? FurColor { get; set; } + + public bool DoesKnowCommand(CatCommand catCommand) + { + return true; + } + } +} diff --git a/Models/CatCommand.cs b/Models/CatCommand.cs new file mode 100644 index 0000000..61c86b6 --- /dev/null +++ b/Models/CatCommand.cs @@ -0,0 +1,9 @@ +namespace HotChocolate.Validation +{ + public enum CatCommand + { + JUMP + } + + +} diff --git a/Models/ComplexInput.cs b/Models/ComplexInput.cs new file mode 100644 index 0000000..afa6966 --- /dev/null +++ b/Models/ComplexInput.cs @@ -0,0 +1,11 @@ +namespace HotChocolate.Validation +{ + public class ComplexInput + { + public string? Name { get; set; } + + public string? Owner { get; set; } + + public ComplexInput? Child { get; set; } + } +} diff --git a/Models/ComplexInput2.cs b/Models/ComplexInput2.cs new file mode 100644 index 0000000..5f63e52 --- /dev/null +++ b/Models/ComplexInput2.cs @@ -0,0 +1,11 @@ +namespace HotChocolate.Validation +{ + public class ComplexInput2 + { + public string Name { get; set; } + + public string Owner { get; set; } + + public ComplexInput2 Child { get; set; } + } +} diff --git a/Models/Dog.cs b/Models/Dog.cs new file mode 100644 index 0000000..5e8a7fa --- /dev/null +++ b/Models/Dog.cs @@ -0,0 +1,26 @@ +namespace HotChocolate.Validation +{ + public class Dog + : IPet + { + public string Name { get; set; } + + public string? Nickname { get; set; } + + public int? BarkVolume { get; set; } + + public bool Barks { get; set; } + + public Human? Owner { get; set; } + + public bool DoesKnowCommand(DogCommand dogCommand) + { + return true; + } + + public bool IsHouseTrained(bool? atOtherHomes) + { + return true; + } + } +} diff --git a/Models/DogCommand.cs b/Models/DogCommand.cs new file mode 100644 index 0000000..91927ef --- /dev/null +++ b/Models/DogCommand.cs @@ -0,0 +1,11 @@ +namespace HotChocolate.Validation +{ + public enum DogCommand + { + Sit, + Down, + Heel + } + + +} diff --git a/Models/Human.cs b/Models/Human.cs new file mode 100644 index 0000000..8d55a94 --- /dev/null +++ b/Models/Human.cs @@ -0,0 +1,9 @@ +namespace HotChocolate.Validation +{ + public class Human : ISentient + { + public string Name { get; set; } + + public string Address { get; set; } + } +} diff --git a/Models/IPet.cs b/Models/IPet.cs new file mode 100644 index 0000000..de05a57 --- /dev/null +++ b/Models/IPet.cs @@ -0,0 +1,7 @@ +namespace HotChocolate.Validation +{ + public interface IPet + { + string Name { get; } + } +} diff --git a/Models/ISentient.cs b/Models/ISentient.cs new file mode 100644 index 0000000..9851ad7 --- /dev/null +++ b/Models/ISentient.cs @@ -0,0 +1,9 @@ +namespace HotChocolate.Validation +{ + public interface ISentient + { + string Name { get; } + } + + +} diff --git a/Models/Query.cs b/Models/Query.cs new file mode 100644 index 0000000..7abdbb5 --- /dev/null +++ b/Models/Query.cs @@ -0,0 +1,107 @@ +using HotChocolate.Validation.Types; +using Microsoft.AspNetCore.CookiePolicy; +using DemoChoco.Data; + +namespace HotChocolate.Validation +{ + public class Query + { + public Query() + { + A = "A"; + B = "B"; + C = "C"; + D = "D"; + Y = "Y"; + dataRepository = new DataRepository(); + } + + private readonly DataRepository dataRepository; + + public string A { get; set; } + + public string B { get; set; } + + public string C { get; set; } + + public string D { get; set; } + + public string Y { get; set; } + + public Query F1 => new Query(); + + public Query F2 => new Query(); + + public Query F3 => new Query(); + + public Query GetField() => this; + + public Dog? GetDog() + { + return dataRepository.dogs.FirstOrDefault(); + } + + public Dog? FindDog(ComplexInput? complex) + { + if (complex == null) + return null; + + if (complex.Owner != null) + { + return dataRepository.dogs.FirstOrDefault(_ => _.Name == complex.Name && _.Owner?.Name == complex.Owner); + } + return dataRepository.dogs.FirstOrDefault(_ => _.Name == complex.Name); + } + + public Dog FindDog2(ComplexInput2 complex) + { + if (complex.Owner != null) + { + return dataRepository.dogs.FirstOrDefault(_ => _.Name == complex?.Name && _.Owner?.Name == complex.Owner); + } + return dataRepository.dogs.FirstOrDefault(_ => _.Name == complex?.Name); + } + + public bool? BooleanList(bool[]? booleanListArg) + { + return true; + } + + public Human GetHuman() + { + return dataRepository.humans.FirstOrDefault(); + } + + + // TODO: Might wanna fix logic later + public Human GetPet() + { + return dataRepository.humans.FirstOrDefault(); + } + + public object GetCatOrDog() + { + return dataRepository.dogs.FirstOrDefault(); + } + + public object GetDogOrHuman() + { + return dataRepository.humans.FirstOrDefault(); + } + + public string[] GetStringList() + { + return dataRepository.stringList; + } + + public string GetFieldWithArg( + string arg, + string arg1, + string arg2, + string arg3) + { + return arg; + } + + } +} diff --git a/Program.cs b/Program.cs new file mode 100644 index 0000000..5165100 --- /dev/null +++ b/Program.cs @@ -0,0 +1,57 @@ +using DemoChoco; +using HotChocolate.Validation; +using HotChocolate.Validation.Types; + +var builder = WebApplication.CreateBuilder(args); +builder.Services + .AddGraphQLServer() + //.AddQueryType() + .AddQueryType() + .AddMutationType() + .AddType() + .AddType() + .AddType() + .AddType() + .AddType() + .AddType() + .AddType() + .AddType() + .AddType() + .AddType() + .AddSubscriptionType() + .AddType() + .AddType() + .AddType() + .AddType() + .AddDirectiveType() + .AddDirectiveType(new CustomDirectiveType("directive")) + .AddDirectiveType(new CustomDirectiveType("directive1")) + .AddDirectiveType(new CustomDirectiveType("directive2")) + .AddDirectiveType("onMutation", DirectiveLocation.Mutation) + .AddDirectiveType("onQuery", DirectiveLocation.Query) + .AddDirectiveType("onSubscription", DirectiveLocation.Subscription) + .AddDirectiveType("onFragmentDefinition", DirectiveLocation.FragmentDefinition) + .AddDirectiveType("onVariableDefinition", DirectiveLocation.VariableDefinition) + .AddDirectiveType("directiveA", + DirectiveLocation.Field | + DirectiveLocation.FragmentDefinition) + .AddDirectiveType("directiveB", + DirectiveLocation.Field | + DirectiveLocation.FragmentDefinition) + .AddDirectiveType("directiveC", + DirectiveLocation.Field | + DirectiveLocation.FragmentDefinition) + .AddDirectiveType("repeatable", + DirectiveLocation.Field | + DirectiveLocation.FragmentDefinition, + x => x.Repeatable()) + .ModifyOptions(o => + { + o.EnableOneOf = true; + o.StrictValidation = false; + }); +var app = builder.Build(); + +app.MapGraphQL(); + +app.Run(); diff --git a/Properties/ServiceDependencies/DemoChoco20220411182001 - Web Deploy/profile.arm.json b/Properties/ServiceDependencies/DemoChoco20220411182001 - Web Deploy/profile.arm.json new file mode 100644 index 0000000..9619b6e --- /dev/null +++ b/Properties/ServiceDependencies/DemoChoco20220411182001 - Web Deploy/profile.arm.json @@ -0,0 +1,113 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_dependencyType": "compute.appService.windows" + }, + "parameters": { + "resourceGroupName": { + "type": "string", + "defaultValue": "RGBotDemo", + "metadata": { + "description": "Name of the resource group for the resource. It is recommended to put resources under same resource group for better tracking." + } + }, + "resourceGroupLocation": { + "type": "string", + "defaultValue": "eastus2", + "metadata": { + "description": "Location of the resource group. Resource groups could have different location than resources, however by default we use API versions from latest hybrid profile which support all locations for resource types we support." + } + }, + "resourceName": { + "type": "string", + "defaultValue": "DemoChoco20220411182001", + "metadata": { + "description": "Name of the main resource to be created by this template." + } + }, + "resourceLocation": { + "type": "string", + "defaultValue": "[parameters('resourceGroupLocation')]", + "metadata": { + "description": "Location of the resource. By default use resource group's location, unless the resource provider is not supported there." + } + } + }, + "variables": { + "appServicePlan_name": "[concat('Plan', uniqueString(concat(parameters('resourceName'), subscription().subscriptionId)))]", + "appServicePlan_ResourceId": "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', parameters('resourceGroupName'), '/providers/Microsoft.Web/serverFarms/', variables('appServicePlan_name'))]" + }, + "resources": [ + { + "type": "Microsoft.Resources/resourceGroups", + "name": "[parameters('resourceGroupName')]", + "location": "[parameters('resourceGroupLocation')]", + "apiVersion": "2019-10-01" + }, + { + "type": "Microsoft.Resources/deployments", + "name": "[concat(parameters('resourceGroupName'), 'Deployment', uniqueString(concat(parameters('resourceName'), subscription().subscriptionId)))]", + "resourceGroup": "[parameters('resourceGroupName')]", + "apiVersion": "2019-10-01", + "dependsOn": [ + "[parameters('resourceGroupName')]" + ], + "properties": { + "mode": "Incremental", + "template": { + "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [ + { + "location": "[parameters('resourceLocation')]", + "name": "[parameters('resourceName')]", + "type": "Microsoft.Web/sites", + "apiVersion": "2015-08-01", + "tags": { + "[concat('hidden-related:', variables('appServicePlan_ResourceId'))]": "empty" + }, + "dependsOn": [ + "[variables('appServicePlan_ResourceId')]" + ], + "kind": "app", + "properties": { + "name": "[parameters('resourceName')]", + "kind": "app", + "httpsOnly": true, + "reserved": false, + "serverFarmId": "[variables('appServicePlan_ResourceId')]", + "siteConfig": { + "metadata": [ + { + "name": "CURRENT_STACK", + "value": "dotnetcore" + } + ] + } + }, + "identity": { + "type": "SystemAssigned" + } + }, + { + "location": "[parameters('resourceLocation')]", + "name": "[variables('appServicePlan_name')]", + "type": "Microsoft.Web/serverFarms", + "apiVersion": "2015-08-01", + "sku": { + "name": "S1", + "tier": "Standard", + "family": "S", + "size": "S1" + }, + "properties": { + "name": "[variables('appServicePlan_name')]" + } + } + ] + } + } + } + ] +} \ No newline at end of file diff --git a/Properties/launchSettings.json b/Properties/launchSettings.json new file mode 100644 index 0000000..1471da0 --- /dev/null +++ b/Properties/launchSettings.json @@ -0,0 +1,28 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:60156", + "sslPort": 44303 + } + }, + "profiles": { + "DemoChoco": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "applicationUrl": "https://localhost:7090;http://localhost:5074", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/Types/AlienType.cs b/Types/AlienType.cs new file mode 100644 index 0000000..73442e2 --- /dev/null +++ b/Types/AlienType.cs @@ -0,0 +1,14 @@ +using HotChocolate.Types; + +namespace HotChocolate.Validation.Types +{ + public class AlienType + : ObjectType + { + protected override void Configure(IObjectTypeDescriptor descriptor) + { + descriptor.Implements(); + descriptor.Field(t => t.Name).Type>(); + } + } +} diff --git a/Types/ArgumentsType.cs b/Types/ArgumentsType.cs new file mode 100644 index 0000000..36e7e4d --- /dev/null +++ b/Types/ArgumentsType.cs @@ -0,0 +1,183 @@ +using HotChocolate.Types; +using System.Reflection.Metadata.Ecma335; + +namespace HotChocolate.Validation.Types +{ + public class ArgumentsType + : ObjectType + { + public ArgumentsType() + { + } + + protected override void Configure(IObjectTypeDescriptor descriptor) + { + descriptor.Name("Arguments"); + + // multipleReqs(x: Int!, y: Int!): Int! + descriptor.Field("multipleReqs") + .Argument("x", t => t.Type>()) + .Argument("y", t => t.Type>()) + .Type>() + .Resolve(() => 10); + + descriptor.Field("multipleOpts") + .Argument("opt1", t => t.Type()) + .Argument("opt2", t => t.Type()) + .Type>() + .Resolve(() => 11); + + descriptor.Field("multipleOptsAndReqs") + .Argument("req1", t => t.Type>()) + .Argument("req2", t => t.Type>()) + .Argument("opt1", t => t.Type()) + .Argument("opt2", t => t.Type()) + .Type>() + .Resolve(() => 12); + + // booleanArgField(booleanArg: Boolean) : Boolean + descriptor.Field("booleanArgField") + .Argument("booleanArg", t => t.Type()) + .Type() + .Resolve((ctx) => ctx.ArgumentValue("booleanArg")); + + // floatArgField(floatArg: Float): Float + descriptor.Field("floatArgField") + .Argument("floatArg", t => t.Type()) + .Type() + .Resolve((ctx) => ctx.ArgumentValue("floatArg")); + + // nonNullFloatArgField(floatArg: Float): Float + descriptor.Field("nonNullFloatArgField") + .Argument("floatArg", t => t.Type>()) + .Type() + .Resolve((ctx) => ctx.ArgumentValue("floatArg")); + + // intArgField(intArg: Int): Int! + descriptor.Field("intArgField") + .Argument("intArg", t => t.Type()) + .Type>() + .Resolve((ctx) => ctx.ArgumentValue("intArg")); + + // nonNullIntArgField(intArg: Int!): Int! + descriptor.Field("nonNullIntArgField") + .Argument("intArg", t => t.Type>()) + .Type>() + .Resolve((ctx) => ctx.ArgumentValue("intArg")); + + // nonNullBooleanArgField(nonNullBooleanArg: Boolean!): Boolean! + descriptor.Field("nonNullBooleanArgField") + .Argument("nonNullBooleanArg", + t => t.Type>()) + .Type>() + .Resolve((ctx) => ctx.ArgumentValue("nonNullBooleanArg")); + + // booleanListArgField(booleanListArg: [Boolean]!) : [Boolean] + descriptor.Field("booleanListArgField") + .Argument("booleanListArg", + t => t.Type>>()) + .Type>() + .Resolve((ctx) => ctx.ArgumentValue>("booleanListArg")); + + // nonNullBooleanListArgField(booleanListArg: [Boolean!]!) : [Boolean] + descriptor.Field("nonNullBooleanListArgField") + .Argument("booleanListArg", + t => t.Type>>>()) + .Type>() + .Resolve((ctx) => ctx.ArgumentValue>("booleanListArg")); + + // optionalNonNullBooleanArgField(optionalBooleanArg: Boolean! = false) : Boolean! + descriptor.Field("optionalNonNullBooleanArgField") + .Argument("optionalBooleanArg", + t => t.Type>().DefaultValue(false)) + .Argument("y", t => t.Type>()) + .Type>() + .Resolve((ctx) => ctx.ArgumentValue("optionalBooleanArg")); + + // optionalNonNullBooleanArgField2(optionalBooleanArg: Boolean = true) : Boolean! + descriptor.Field("optionalNonNullBooleanArgField2") + .Argument("optionalBooleanArg", + t => t.Type().DefaultValue(true)) + .Type() + .Resolve((ctx) => ctx.ArgumentValue("optionalBooleanArg")); + + // booleanListArgField(booleanListArg: [Boolean]!) : [Boolean] + descriptor.Field("nonNullBooleanListField") + .Argument("nonNullBooleanListArg", + t => t.Type>>()) + .Type>() + .Resolve((ctx) => ctx.ArgumentValue>("nonNullBooleanListArg")); + + // intArgField(intArg: ID): ID! + descriptor.Field("idArgField") + .Argument("idArg", t => t.Type()) + .Type>() + .Resolve((ctx) => ctx.ArgumentValue("idArg")); + + descriptor.Field("nonNullIdArgField") + .Argument("idArg", t => t.Type>()) + .Type>() + .Resolve((ctx) => ctx.ArgumentValue("idArg")); + + // stringArgField(intArg: String): String! + descriptor.Field("stringArgField") + .Argument("stringArg", t => t.Type()) + .Type>() + .Resolve((ctx) => ctx.ArgumentValue("stringArg")); + + descriptor.Field("nonNullStringArgField") + .Argument("stringArg", t => t.Type>()) + .Type>() + .Resolve((ctx) => ctx.ArgumentValue("stringArg")); + + descriptor.Field("stringListArgField") + .Argument("stringListArg", + t => t.Type>()) + .Type>() + .Resolve((ctx) => ctx.ArgumentValue>("stringListArg")); + + // enumArgField(intArg: DogCommand): String! + descriptor.Field("enumArgField") + .Argument("enumArg", t => t.Type>()) + .Type>() + .Resolve((ctx) => ctx.ArgumentValue("enumArg")); + + // "nonNullenumArgField(intArg: DogCommand!): String! + descriptor.Field("nonNullEnumArgField") + .Argument("enumArg", t => t.Type>>()) + .Type>() + .Resolve((ctx) => ctx.ArgumentValue("enumArg")); + + descriptor.Field("complexArgField") + .Argument("complexArg", t => t.Type()) + .Type>() + .Argument("complexArg1", t => t.Type()) + .Type>() + .Argument("complexArg2", t => t.Type()) + .Type>() + .Resolve(() => "test"); + + descriptor.Field("nonNullFieldWithDefault") + .Argument("opt1", t => t.Type>().DefaultValue(0)) + .Type>() + .Resolve(() => "test"); + + descriptor.Field("nonNullFieldWithDefault") + .Argument("nonNullIntArg", t => t.Type>().DefaultValue(0)) + .Type>() + .Resolve(() => "test"); + + descriptor.Field("nonNullField") + .Argument("nonNullIntArg", t => t.Type>()) + .Type>() + .Resolve((ctx) => ctx.ArgumentValue("nonNullIntArg")); + + descriptor.Field("stringListNonNullArgField") + .Argument( + "stringListNonNullArg", + t => t.Type>>()) + .Type>() + .Resolve(() => "test"); + } + } +} diff --git a/Types/BeingType.cs b/Types/BeingType.cs new file mode 100644 index 0000000..73a3949 --- /dev/null +++ b/Types/BeingType.cs @@ -0,0 +1,14 @@ +using HotChocolate.Types; + +namespace HotChocolate.Validation +{ + public class BeingType + : InterfaceType + { + protected override void Configure(IInterfaceTypeDescriptor descriptor) + { + descriptor.Name("Being"); + descriptor.Field("name").Type>(); + } + } +} diff --git a/Types/CatInputType.cs b/Types/CatInputType.cs new file mode 100644 index 0000000..47ab578 --- /dev/null +++ b/Types/CatInputType.cs @@ -0,0 +1,16 @@ +using HotChocolate.Types; + +namespace HotChocolate.Validation.Types +{ + public class CatInputType : InputObjectType + { + protected override void Configure(IInputObjectTypeDescriptor descriptor) + { + descriptor.Name("CatInput"); + + descriptor.Field("name").Type("String!"); + descriptor.Field("nickname").Type("String"); + descriptor.Field("meowVolume").Type("Int"); + } + } +} diff --git a/Types/CatOrDogType.cs b/Types/CatOrDogType.cs new file mode 100644 index 0000000..fbe638c --- /dev/null +++ b/Types/CatOrDogType.cs @@ -0,0 +1,15 @@ +using HotChocolate.Types; + +namespace HotChocolate.Validation.Types +{ + public class CatOrDogType + : UnionType + { + protected override void Configure(IUnionTypeDescriptor descriptor) + { + descriptor.Name("CatOrDog"); + descriptor.Type(); + descriptor.Type(); + } + } +} diff --git a/Types/CatType.cs b/Types/CatType.cs new file mode 100644 index 0000000..8829b67 --- /dev/null +++ b/Types/CatType.cs @@ -0,0 +1,40 @@ +using HotChocolate.Types; + +namespace HotChocolate.Validation.Types +{ + public class CatType + : ObjectType + { + protected override void Configure(IObjectTypeDescriptor descriptor) + { + descriptor.Implements(); + descriptor.Implements(); + descriptor.Implements(); + descriptor.Field(t => t.Name).Type>(); + descriptor.Field(t => t.DoesKnowCommand(default)) + .Argument("catCommand", a => a.Type>>()); + descriptor.Field("furColor").Type().Resolve(() => null); + } + } + + public class MammalType : InterfaceType + { + protected override void Configure(IInterfaceTypeDescriptor descriptor) + { + descriptor.Name("Mammal"); + descriptor.Field("name").Type>(); + } + } + + public class CanineType : InterfaceType + { + protected override void Configure(IInterfaceTypeDescriptor descriptor) + { + descriptor.Name("Canine"); + descriptor.Implements(); + descriptor.Field("name").Type>(); + } + } + + +} diff --git a/Types/Complex2InputType.cs b/Types/Complex2InputType.cs new file mode 100644 index 0000000..4416816 --- /dev/null +++ b/Types/Complex2InputType.cs @@ -0,0 +1,19 @@ +using HotChocolate.Language; +using HotChocolate.Types; + +namespace HotChocolate.Validation.Types +{ + public class Complex2InputType + : InputObjectType + { + protected override void Configure( + IInputObjectTypeDescriptor descriptor) + { + descriptor.Field(t => t.Name) + .Type>(); + descriptor.Field(t => t.Owner) + .Type>() + .DefaultValue(new StringValueNode("1234")); + } + } +} diff --git a/Types/Complex3InputType.cs b/Types/Complex3InputType.cs new file mode 100644 index 0000000..26cf100 --- /dev/null +++ b/Types/Complex3InputType.cs @@ -0,0 +1,49 @@ +using HotChocolate.Types; + +namespace HotChocolate.Validation.Types +{ + public class Complex3InputType + : InputObjectType + { + protected override void Configure( + IInputObjectTypeDescriptor descriptor) + { + descriptor.Field("requiredField") + .Type>(); + + descriptor.Field("intField") + .Type(); + + descriptor.Field("stringField") + .Type(); + + descriptor.Field("booleanField") + .Type(); + + descriptor.Field("stringListField") + .Type>(); + + descriptor.Field("nonNullField") + .Type>() + .DefaultValue(true); + + descriptor.Field("f") + .Type(); + + descriptor.Field("f1") + .Type(); + + descriptor.Field("f2") + .Type(); + + descriptor.Field("f3") + .Type(); + + descriptor.Field("id") + .Type(); + + descriptor.Field("deep") + .Type(); + } + } +} diff --git a/Types/ComplexDirective.cs b/Types/ComplexDirective.cs new file mode 100644 index 0000000..864c921 --- /dev/null +++ b/Types/ComplexDirective.cs @@ -0,0 +1,24 @@ +using HotChocolate.Types; + +namespace HotChocolate.Validation.Types +{ + public class ComplexDirective + : DirectiveType + { + protected override void Configure( + IDirectiveTypeDescriptor descriptor) + { + descriptor.Repeatable(); + + descriptor.Name("complex"); + + descriptor.Location(HotChocolate.Types.DirectiveLocation.Field); + + descriptor.Argument("anyArg") + .Type(); + + descriptor.Argument("stringArg") + .Type(); + } + } +} diff --git a/Types/ComplexInputType.cs b/Types/ComplexInputType.cs new file mode 100644 index 0000000..6343fcd --- /dev/null +++ b/Types/ComplexInputType.cs @@ -0,0 +1,13 @@ +using HotChocolate.Types; + +namespace HotChocolate.Validation.Types +{ + public class ComplexInputType + : InputObjectType + { + protected override void Configure( + IInputObjectTypeDescriptor descriptor) + { + } + } +} diff --git a/Types/CustomDirectiveType.cs b/Types/CustomDirectiveType.cs new file mode 100644 index 0000000..1043110 --- /dev/null +++ b/Types/CustomDirectiveType.cs @@ -0,0 +1,37 @@ +using HotChocolate.Types; + +namespace HotChocolate.Validation.Types +{ + public class CustomDirectiveType + : DirectiveType + { + private readonly string _name; + + public CustomDirectiveType(string name) + { + _name = name; + } + + protected override void Configure( + IDirectiveTypeDescriptor descriptor) + { + descriptor.Repeatable(); + + descriptor.Name(_name); + + descriptor.Location(DirectiveLocation.Field); + + descriptor.Argument("arg") + .Type(); + descriptor.Argument("arg1") + .Type(); + descriptor.Argument("arg2") + .Type(); + descriptor.Argument("arg3") + .Type(); + descriptor.Argument("arg4") + .Type(); + + } + } +} diff --git a/Types/DogInputType.cs b/Types/DogInputType.cs new file mode 100644 index 0000000..0ef9756 --- /dev/null +++ b/Types/DogInputType.cs @@ -0,0 +1,16 @@ +using HotChocolate.Types; + +namespace HotChocolate.Validation.Types +{ + public class DogInputType : InputObjectType + { + protected override void Configure(IInputObjectTypeDescriptor descriptor) + { + descriptor.Name("DogInput"); + + descriptor.Field("name").Type("String!"); + descriptor.Field("nickname").Type("String"); + descriptor.Field("barkVolume").Type("Int"); + } + } +} diff --git a/Types/DogOrHumanType.cs b/Types/DogOrHumanType.cs new file mode 100644 index 0000000..780edad --- /dev/null +++ b/Types/DogOrHumanType.cs @@ -0,0 +1,15 @@ +using HotChocolate.Types; + +namespace HotChocolate.Validation.Types +{ + public class DogOrHumanType + : UnionType + { + protected override void Configure(IUnionTypeDescriptor descriptor) + { + descriptor.Name("DogOrHuman"); + descriptor.Type(); + descriptor.Type(); + } + } +} diff --git a/Types/DogType.cs b/Types/DogType.cs new file mode 100644 index 0000000..c968716 --- /dev/null +++ b/Types/DogType.cs @@ -0,0 +1,19 @@ +using HotChocolate.Types; + +namespace HotChocolate.Validation.Types +{ + public class DogType + : ObjectType + { + protected override void Configure(IObjectTypeDescriptor descriptor) + { + descriptor.Implements(); + descriptor.Implements(); + descriptor.Implements(); + descriptor.Implements(); + descriptor.Field(t => t.Name).Type>(); + descriptor.Field(t => t.DoesKnowCommand(default)) + .Argument("dogCommand", a => a.Type>>()); + } + } +} diff --git a/Types/FurColor.cs b/Types/FurColor.cs new file mode 100644 index 0000000..c74fdac --- /dev/null +++ b/Types/FurColor.cs @@ -0,0 +1,14 @@ +using HotChocolate.Types; + +namespace HotChocolate.Validation.Types +{ + public class FurColor : EnumType + { + protected override void Configure(IEnumTypeDescriptor descriptor) + { + descriptor.Value("RED"); + descriptor.Value("BLUE"); + descriptor.Value("GREEN"); + } + } +} diff --git a/Types/HumanOrAlienType.cs b/Types/HumanOrAlienType.cs new file mode 100644 index 0000000..2587386 --- /dev/null +++ b/Types/HumanOrAlienType.cs @@ -0,0 +1,15 @@ +using HotChocolate.Types; + +namespace HotChocolate.Validation.Types +{ + public class HumanOrAlienType + : UnionType + { + protected override void Configure(IUnionTypeDescriptor descriptor) + { + descriptor.Name("HumanOrAlien"); + descriptor.Type(); + descriptor.Type(); + } + } +} diff --git a/Types/HumanType.cs b/Types/HumanType.cs new file mode 100644 index 0000000..6310590 --- /dev/null +++ b/Types/HumanType.cs @@ -0,0 +1,25 @@ +using HotChocolate.Types; + +namespace HotChocolate.Validation.Types +{ + public class HumanType + : ObjectType + { + protected override void Configure(IObjectTypeDescriptor descriptor) + { + descriptor.Implements(); + descriptor.Implements(); + descriptor.Implements(); + descriptor.Field(t => t.Name).Type>(); + descriptor.Field("iq") + .Type>() + .Resolve(() => ""); + descriptor.Field("pets") + .Type>() + .Resolve(() => ""); + descriptor.Field("relatives") + .Type>() + .Resolve(() => ""); + } + } +} diff --git a/Types/IntelligentType.cs b/Types/IntelligentType.cs new file mode 100644 index 0000000..ac131ce --- /dev/null +++ b/Types/IntelligentType.cs @@ -0,0 +1,14 @@ +using HotChocolate.Types; + +namespace HotChocolate.Validation +{ + public class IntelligentType + : InterfaceType + { + protected override void Configure(IInterfaceTypeDescriptor descriptor) + { + descriptor.Name("Intelligent"); + descriptor.Field("iq").Type>(); + } + } +} diff --git a/Types/InvalidScalar.cs b/Types/InvalidScalar.cs new file mode 100644 index 0000000..a503183 --- /dev/null +++ b/Types/InvalidScalar.cs @@ -0,0 +1,36 @@ +using System; +using HotChocolate.Language; +using HotChocolate.Types; + +#nullable enable + +namespace HotChocolate.Validation.Types +{ + public class InvalidScalar : ScalarType + { + public InvalidScalar() + : base("Invalid", BindingBehavior.Explicit) + { + } + + public override bool IsInstanceOfType(IValueNode literal) + { + return false; + } + + public override object? ParseLiteral(IValueNode valueSyntax) + { + throw new InvalidOperationException(); + } + + public override IValueNode ParseValue(object? value) + { + throw new InvalidOperationException(); + } + + public override IValueNode ParseResult(object? resultValue) + { + throw new InvalidOperationException(); + } + } +} diff --git a/Types/MessageType.cs b/Types/MessageType.cs new file mode 100644 index 0000000..a5f49b6 --- /dev/null +++ b/Types/MessageType.cs @@ -0,0 +1,21 @@ +using HotChocolate.Types; + +namespace HotChocolate.Validation.Types +{ + public class MessageType + : ObjectType + { + protected override void Configure(IObjectTypeDescriptor descriptor) + { + descriptor.Name("Message"); + + descriptor.Field("body") + .Type>() + .Resolve(() => "foo"); + + descriptor.Field("sender") + .Type>() + .Resolve(() => "foo"); + } + } +} diff --git a/Types/MutationType.cs b/Types/MutationType.cs new file mode 100644 index 0000000..41ec46d --- /dev/null +++ b/Types/MutationType.cs @@ -0,0 +1,39 @@ +using DemoChoco.Data; +using HotChocolate.Types; + +namespace HotChocolate.Validation.Types +{ + public class MutationType + : ObjectType + { + private readonly DataRepository dataRepository = new DataRepository(); + + protected override void Configure(IObjectTypeDescriptor descriptor) + { + descriptor.Name("Mutation"); + + descriptor.Field("fieldB") + .Type>() + .Resolve(() => "foo"); + + descriptor.Field("addPet") + .Argument("pet", a => a.Type()) + .Type() + .Resolve((context) => + { + var pets = context.ArgumentValue>>("pet"); + if (pets.TryGetValue("cat", out var cat)) + { + dataRepository.AddCat(cat.Values.ToList()); + } + if (pets.TryGetValue("dog", out var dog)) + { + dataRepository.AddDog(dog.Values.ToList()); + } + return dataRepository.cats.FirstOrDefault(); + }) ; + } + + public Query GetField([Parent] Query query, string a, string b, string c, string d) => new Query { A = a, B = b, C = c, D = d }; + } +} diff --git a/Types/PetInputType.cs b/Types/PetInputType.cs new file mode 100644 index 0000000..23f912d --- /dev/null +++ b/Types/PetInputType.cs @@ -0,0 +1,15 @@ +using HotChocolate.Types; + +namespace HotChocolate.Validation.Types +{ + public class PetInputType : InputObjectType + { + protected override void Configure(IInputObjectTypeDescriptor descriptor) + { + descriptor.Name("PetInput").OneOf(); + + descriptor.Field("cat").Type(); + descriptor.Field("dog").Type(); + } + } +} diff --git a/Types/PetType.cs b/Types/PetType.cs new file mode 100644 index 0000000..988a3d7 --- /dev/null +++ b/Types/PetType.cs @@ -0,0 +1,15 @@ +using HotChocolate.Types; + +namespace HotChocolate.Validation.Types +{ + public class PetType + : InterfaceType + { + protected override void Configure(IInterfaceTypeDescriptor descriptor) + { + descriptor.Name("Pet"); + descriptor.Implements(); + descriptor.Field("name").Type>(); + } + } +} diff --git a/Types/QueryType.cs b/Types/QueryType.cs new file mode 100644 index 0000000..e45f0c4 --- /dev/null +++ b/Types/QueryType.cs @@ -0,0 +1,46 @@ +using DemoChoco; +using HotChocolate.Types; + +namespace HotChocolate.Validation.Types +{ + public class QueryType : ObjectType + { + protected override void Configure(IObjectTypeDescriptor descriptor) + { + descriptor.Field("arguments") + .Type() + .Resolve(new ArgumentsType()); + + descriptor.Field("invalidArg") + .Type() + .Argument("arg", a => a.Type()) + .Resolve((ctx) => ctx.ArgumentValue("arg")); + + descriptor.Field("anyArg") + .Type() + .Argument("arg", a => a.Type()) + .Resolve((ctx) => ctx.ArgumentValue("arg")); + + descriptor.Field("field") + .Argument("a", a => a.Type()) + .Argument("b", a => a.Type()) + .Argument("c", a => a.Type()) + .Argument("d", a => a.Type()) + .Type() + .Resolve(() => new Query()); + + descriptor.Field(t => t.GetCatOrDog()) + .Type(); + + descriptor.Field(t => t.GetDogOrHuman()) + .Type(); + + descriptor.Field("nonNull") + .Argument("a", a => a.Type>().DefaultValue("abc")) + .Resolve((ctx) => ctx.ArgumentValue("a")); + } + + + + } +} diff --git a/Types/SentientType.cs b/Types/SentientType.cs new file mode 100644 index 0000000..eaef90a --- /dev/null +++ b/Types/SentientType.cs @@ -0,0 +1,14 @@ +using HotChocolate.Types; + +namespace HotChocolate.Validation.Types +{ + public class SentientType + : InterfaceType + { + protected override void Configure(IInterfaceTypeDescriptor descriptor) + { + descriptor.Name("Sentient"); + descriptor.Field("name").Type>(); + } + } +} diff --git a/Types/SubscriptionType.cs b/Types/SubscriptionType.cs new file mode 100644 index 0000000..0804767 --- /dev/null +++ b/Types/SubscriptionType.cs @@ -0,0 +1,25 @@ +using HotChocolate.Types; + +namespace HotChocolate.Validation.Types +{ + public class SubscriptionType + : ObjectType + { + protected override void Configure(IObjectTypeDescriptor descriptor) + { + descriptor.Name("Subscription"); + + descriptor.Field("newMessage") + .Type>() + .Resolve(() => "foo"); + + descriptor.Field("disallowedSecondRootField") + .Type>() + .Resolve(() => "foo"); + + descriptor.Field("disallowedThirdRootField") + .Type>() + .Resolve(() => "foo"); + } + } +} diff --git a/ValidationUtils.cs b/ValidationUtils.cs new file mode 100644 index 0000000..0b5813f --- /dev/null +++ b/ValidationUtils.cs @@ -0,0 +1,21 @@ +using HotChocolate.Execution.Configuration; + +namespace DemoChoco +{ + public static class ValidationUtils + { + public static IRequestExecutorBuilder AddDirectiveType( + this IRequestExecutorBuilder builder, + string name, + DirectiveLocation location) => + AddDirectiveType(builder, name, location, x => x); + + public static IRequestExecutorBuilder AddDirectiveType( + this IRequestExecutorBuilder builder, + string name, + DirectiveLocation location, + Func configure) => + builder.AddDirectiveType(new DirectiveType(x => + configure(x.Name(name).Location(location)))); + } +} diff --git a/appsettings.Development.json b/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/appsettings.json b/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +}