├── .gitignore ├── Editor.meta ├── Editor ├── LastAbyss.SimpleGraphQL.Editor.asmdef ├── LastAbyss.SimpleGraphQL.Editor.asmdef.meta ├── LinkXmlInjector.cs ├── LinkXmlInjector.cs.meta ├── SimpleGraphQL.meta └── SimpleGraphQL │ ├── GraphQLImporterV1.cs │ └── GraphQLImporterV1.cs.meta ├── LICENSE.md ├── LICENSE.md.meta ├── Plugins.meta ├── Plugins ├── LastAbyss.SimpleGraphQL.Plugins.asmdef ├── LastAbyss.SimpleGraphQL.Plugins.asmdef.meta ├── SimpleGraphQL.meta └── SimpleGraphQL │ ├── GraphQLParser.meta │ ├── GraphQLParser │ ├── AST.meta │ ├── AST │ │ ├── ASTNode.cs │ │ ├── ASTNode.cs.meta │ │ ├── Enums.cs │ │ ├── Enums.cs.meta │ │ ├── GraphQLArgument.cs │ │ ├── GraphQLArgument.cs.meta │ │ ├── GraphQLComment.cs │ │ ├── GraphQLComment.cs.meta │ │ ├── GraphQLDirective.cs │ │ ├── GraphQLDirective.cs.meta │ │ ├── GraphQLDirectiveDefinition.cs │ │ ├── GraphQLDirectiveDefinition.cs.meta │ │ ├── GraphQLDocument.cs │ │ ├── GraphQLDocument.cs.meta │ │ ├── GraphQLEnumTypeDefinition.cs │ │ ├── GraphQLEnumTypeDefinition.cs.meta │ │ ├── GraphQLEnumValueDefinition.cs │ │ ├── GraphQLEnumValueDefinition.cs.meta │ │ ├── GraphQLFieldDefinition.cs │ │ ├── GraphQLFieldDefinition.cs.meta │ │ ├── GraphQLFieldSelection.cs │ │ ├── GraphQLFieldSelection.cs.meta │ │ ├── GraphQLFragmentDefinition.cs │ │ ├── GraphQLFragmentDefinition.cs.meta │ │ ├── GraphQLFragmentSpread.cs │ │ ├── GraphQLFragmentSpread.cs.meta │ │ ├── GraphQLInlineFragment.cs │ │ ├── GraphQLInlineFragment.cs.meta │ │ ├── GraphQLInputObjectTypeDefinition.cs │ │ ├── GraphQLInputObjectTypeDefinition.cs.meta │ │ ├── GraphQLInputValueDefinition.cs │ │ ├── GraphQLInputValueDefinition.cs.meta │ │ ├── GraphQLInterfaceTypeDefinition.cs │ │ ├── GraphQLInterfaceTypeDefinition.cs.meta │ │ ├── GraphQLListType.cs │ │ ├── GraphQLListType.cs.meta │ │ ├── GraphQLListValue.cs │ │ ├── GraphQLListValue.cs.meta │ │ ├── GraphQLLocation.cs │ │ ├── GraphQLLocation.cs.meta │ │ ├── GraphQLName.cs │ │ ├── GraphQLName.cs.meta │ │ ├── GraphQLNamedType.cs │ │ ├── GraphQLNamedType.cs.meta │ │ ├── GraphQLNonNullType.cs │ │ ├── GraphQLNonNullType.cs.meta │ │ ├── GraphQLObjectField.cs │ │ ├── GraphQLObjectField.cs.meta │ │ ├── GraphQLObjectTypeDefinition.cs │ │ ├── GraphQLObjectTypeDefinition.cs.meta │ │ ├── GraphQLObjectValue.cs │ │ ├── GraphQLObjectValue.cs.meta │ │ ├── GraphQLOperationDefinition.cs │ │ ├── GraphQLOperationDefinition.cs.meta │ │ ├── GraphQLOperationTypeDefinition.cs │ │ ├── GraphQLOperationTypeDefinition.cs.meta │ │ ├── GraphQLScalarTypeDefinition.cs │ │ ├── GraphQLScalarTypeDefinition.cs.meta │ │ ├── GraphQLScalarValue.cs │ │ ├── GraphQLScalarValue.cs.meta │ │ ├── GraphQLSchemaDefinition.cs │ │ ├── GraphQLSchemaDefinition.cs.meta │ │ ├── GraphQLSelectionSet.cs │ │ ├── GraphQLSelectionSet.cs.meta │ │ ├── GraphQLType.cs │ │ ├── GraphQLType.cs.meta │ │ ├── GraphQLTypeDefinition.cs │ │ ├── GraphQLTypeDefinition.cs.meta │ │ ├── GraphQLTypeExtensionDefinition.cs │ │ ├── GraphQLTypeExtensionDefinition.cs.meta │ │ ├── GraphQLUnionTypeDefinition.cs │ │ ├── GraphQLUnionTypeDefinition.cs.meta │ │ ├── GraphQLValue.cs │ │ ├── GraphQLValue.cs.meta │ │ ├── GraphQLVariable.cs │ │ ├── GraphQLVariable.cs.meta │ │ ├── GraphQLVariableDefinition.cs │ │ ├── GraphQLVariableDefinition.cs.meta │ │ ├── IHasDirectivesNode.cs │ │ ├── IHasDirectivesNode.cs.meta │ │ ├── INamedNode.cs │ │ └── INamedNode.cs.meta │ ├── Cache.meta │ ├── Cache │ │ ├── ConcurrentDictionaryCache.cs │ │ ├── ConcurrentDictionaryCache.cs.meta │ │ ├── DictionaryCache.cs │ │ ├── DictionaryCache.cs.meta │ │ ├── ILexemeCache.cs │ │ ├── ILexemeCache.cs.meta │ │ ├── NoCache.cs │ │ ├── NoCache.cs.meta │ │ ├── StringHelper.cs │ │ └── StringHelper.cs.meta │ ├── Exceptions.meta │ ├── Exceptions │ │ ├── GraphQLSyntaxErrorException.cs │ │ └── GraphQLSyntaxErrorException.cs.meta │ ├── GraphQLAstVisitor.cs │ ├── GraphQLAstVisitor.cs.meta │ ├── ILexer.cs │ ├── ILexer.cs.meta │ ├── ISource.cs │ ├── ISource.cs.meta │ ├── LICENSE.md │ ├── LICENSE.md.meta │ ├── Lexer.cs │ ├── Lexer.cs.meta │ ├── LexerContext.cs │ ├── LexerContext.cs.meta │ ├── Location.cs │ ├── Location.cs.meta │ ├── Parser.cs │ ├── Parser.cs.meta │ ├── ParserContext.cs │ ├── ParserContext.cs.meta │ ├── Source.cs │ ├── Source.cs.meta │ ├── Token.cs │ ├── Token.cs.meta │ ├── TokenKind.cs │ └── TokenKind.cs.meta │ ├── Utils.cs │ └── Utils.cs.meta ├── README.md ├── README.md.meta ├── Runtime.meta ├── Runtime ├── LastAbyss.SimpleGraphQL.Runtime.asmdef ├── LastAbyss.SimpleGraphQL.Runtime.asmdef.meta ├── SimpleGraphQL.meta └── SimpleGraphQL │ ├── GraphQLClient.cs │ ├── GraphQLClient.cs.meta │ ├── GraphQLConfig.cs │ ├── GraphQLConfig.cs.meta │ ├── GraphQLFile.cs │ ├── GraphQLFile.cs.meta │ ├── HttpUtils.cs │ ├── HttpUtils.cs.meta │ ├── MurmurHash2.cs │ ├── MurmurHash2.cs.meta │ ├── Query.cs │ ├── Query.cs.meta │ ├── Request.cs │ ├── Request.cs.meta │ ├── Response.cs │ ├── Response.cs.meta │ ├── UnityWebRequestException.cs │ ├── UnityWebRequestException.cs.meta │ ├── YieldInstructions.meta │ └── YieldInstructions │ ├── WaitForSend.cs │ └── WaitForSend.cs.meta ├── Tests.meta ├── Tests ├── Runtime.meta └── Runtime │ ├── LastAbyss.SimpleGraphQL.Runtime.Tests.asmdef │ ├── LastAbyss.SimpleGraphQL.Runtime.Tests.asmdef.meta │ ├── QueryTests.cs │ ├── QueryTests.cs.meta │ ├── UnityTestAsyncExtensions.cs │ ├── UnityTestAsyncExtensions.cs.meta │ ├── sample.graphql │ └── sample.graphql.meta ├── link.xml ├── link.xml.meta ├── package.json └── package.json.meta /.gitignore: -------------------------------------------------------------------------------- 1 | # This .gitignore file should be placed at the root of your Unity project directory 2 | # 3 | # Get latest from https://github.com/github/gitignore/blob/master/Unity.gitignore 4 | # 5 | /[Ll]ibrary/ 6 | /[Tt]emp/ 7 | /[Oo]bj/ 8 | /[Bb]uild/ 9 | /[Bb]uilds/ 10 | /[Ll]ogs/ 11 | /[Mm]emoryCaptures/ 12 | 13 | # Asset meta data should only be ignored when the corresponding asset is also ignored 14 | !/[Aa]ssets/**/*.meta 15 | 16 | # Uncomment this line if you wish to ignore the asset store tools plugin 17 | # /[Aa]ssets/AssetStoreTools* 18 | 19 | # Autogenerated Jetbrains Rider plugin 20 | [Aa]ssets/Plugins/Editor/JetBrains* 21 | 22 | # Visual Studio cache directory 23 | .vs/ 24 | 25 | # Gradle cache directory 26 | .gradle/ 27 | 28 | .idea 29 | 30 | # Autogenerated VS/MD/Consulo solution and project files 31 | ExportedObj/ 32 | .consulo/ 33 | *.csproj 34 | *.unityproj 35 | *.sln 36 | *.suo 37 | *.tmp 38 | *.user 39 | *.userprefs 40 | *.pidb 41 | *.booproj 42 | *.svd 43 | *.pdb 44 | *.mdb 45 | *.opendb 46 | *.VC.db 47 | 48 | # Unity3D generated meta files 49 | *.pidb.meta 50 | *.pdb.meta 51 | *.mdb.meta 52 | 53 | # Unity3D generated file on crash reports 54 | sysinfo.txt 55 | 56 | # Builds 57 | *.apk 58 | *.unitypackage 59 | 60 | # Crashlytics generated file 61 | crashlytics-build.properties 62 | 63 | -------------------------------------------------------------------------------- /Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7b059e40fd6aad1418656a4730b8e80f 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/LastAbyss.SimpleGraphQL.Editor.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "LastAbyss.SimpleGraphQL.Editor", 3 | "references": [ 4 | "GUID:d9c4a3993822f42439e43ee7d2d1f243", 5 | "GUID:15e3c116196bd394da80b1072fff8aa8" 6 | ], 7 | "includePlatforms": [ 8 | "Editor" 9 | ], 10 | "excludePlatforms": [], 11 | "allowUnsafeCode": false, 12 | "overrideReferences": false, 13 | "precompiledReferences": [], 14 | "autoReferenced": true, 15 | "defineConstraints": [], 16 | "versionDefines": [], 17 | "noEngineReferences": false 18 | } -------------------------------------------------------------------------------- /Editor/LastAbyss.SimpleGraphQL.Editor.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fba7100f46275f642aca6c17b8224075 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Editor/LinkXmlInjector.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using UnityEditor; 3 | using UnityEditor.Build; 4 | using UnityEditor.Build.Reporting; 5 | using UnityEditor.UnityLinker; 6 | 7 | namespace SimpleGraphQL 8 | { 9 | internal class LinkXmlInjector : IUnityLinkerProcessor 10 | { 11 | int IOrderedCallback.callbackOrder => 0; 12 | 13 | string IUnityLinkerProcessor.GenerateAdditionalLinkXmlFile(BuildReport report, 14 | UnityLinkerBuildPipelineData data) 15 | { 16 | // This is pretty ugly, but it was the only thing I could think of in order to reliably get the path to link.xml 17 | const string linkXmlGuid = "9bbe747a148f00540828ab8521feb770"; 18 | var assetPath = AssetDatabase.GUIDToAssetPath(linkXmlGuid); 19 | // assets paths are relative to the unity project root, but they don't correspond to actual folders for 20 | // Packages that are embedded. I.e. it won't work if a package is installed as a git submodule 21 | // So resolve it to an absolute path: 22 | return Path.GetFullPath(assetPath); 23 | } 24 | 25 | #if !UNITY_2021_2_OR_NEWER 26 | void IUnityLinkerProcessor.OnBeforeRun(BuildReport report, UnityLinkerBuildPipelineData data) 27 | { 28 | } 29 | 30 | void IUnityLinkerProcessor.OnAfterRun(BuildReport report, UnityLinkerBuildPipelineData data) 31 | { 32 | } 33 | #endif 34 | } 35 | } -------------------------------------------------------------------------------- /Editor/LinkXmlInjector.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c8fd0dba505247129d30f405770dcd49 3 | timeCreated: 1623269528 -------------------------------------------------------------------------------- /Editor/SimpleGraphQL.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0bad978491e82a649b06928923fabdf8 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/SimpleGraphQL/GraphQLImporterV1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using UnityEngine; 6 | using SimpleGraphQL.GraphQLParser; 7 | using SimpleGraphQL.GraphQLParser.AST; 8 | 9 | // ifdef for different unity versions 10 | #if UNITY_2020_2_OR_NEWER 11 | using UnityEditor.AssetImporters; 12 | 13 | #elif UNITY_2017_1_OR_NEWER 14 | using UnityEditor.Experimental.AssetImporters; 15 | #endif 16 | 17 | namespace SimpleGraphQL 18 | { 19 | [ScriptedImporter(1, "graphql")] 20 | public class GraphQLImporterV1 : ScriptedImporter 21 | { 22 | public override void OnImportAsset(AssetImportContext ctx) 23 | { 24 | var lexer = new Lexer(); 25 | var parser = new Parser(lexer); 26 | string contents = File.ReadAllText(ctx.assetPath); 27 | string fileName = Path.GetFileNameWithoutExtension(ctx.assetPath); 28 | var queryFile = ScriptableObject.CreateInstance(); 29 | 30 | GraphQLDocument graphQLDocument = parser.Parse(new Source(contents)); 31 | 32 | List operations = graphQLDocument.Definitions 33 | .FindAll(x => x.Kind == ASTNodeKind.OperationDefinition) 34 | .Select(x => (GraphQLOperationDefinition) x) 35 | .ToList(); 36 | 37 | if (operations.Count > 0) 38 | { 39 | foreach (GraphQLOperationDefinition operation in operations) 40 | { 41 | // Check for multiple anonymous queries (not allowed by graphQL) 42 | // Also checks for anonymous queries inside a file with named queries 43 | if (queryFile.Queries.Count > 1 && operation.Name == null) 44 | { 45 | throw new ArgumentException( 46 | $"Multiple anonymous queries/anonymous query with named query found within: {ctx.assetPath}\nPlease ensure that there is either only one anonymous query, or all queries are named within the file!"); 47 | } 48 | 49 | if (!Enum.TryParse(operation.Operation.ToString(), out OperationType operationType)) 50 | { 51 | Debug.LogWarning("Unable to convert operation type in " + ctx.assetPath); 52 | } 53 | 54 | queryFile.Queries.Add(new Query 55 | { 56 | FileName = fileName, 57 | OperationName = operation.Name?.Value, 58 | OperationType = operationType, 59 | Source = contents 60 | }); 61 | } 62 | } 63 | else 64 | { 65 | throw new ArgumentException( 66 | $"There were no operation definitions inside this graphql: {ctx.assetPath}\nPlease ensure that there is at least one operation defined!"); 67 | } 68 | 69 | ctx.AddObjectToAsset("QueryScriptableObject", queryFile); 70 | ctx.SetMainObject(queryFile); 71 | } 72 | } 73 | } -------------------------------------------------------------------------------- /Editor/SimpleGraphQL/GraphQLImporterV1.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1d33fc8355b800b49883cbcc4d3b2b9c 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Last Abyss Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LICENSE.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2999524cb1f5ee944b5638347a346797 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Plugins.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: eb732c8864c7be04196fc7f6e43be50e 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Plugins/LastAbyss.SimpleGraphQL.Plugins.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "LastAbyss.SimpleGraphQL.Plugins", 3 | "references": [ 4 | ], 5 | "excludePlatforms": [], 6 | "allowUnsafeCode": false, 7 | "overrideReferences": false, 8 | "precompiledReferences": [], 9 | "autoReferenced": true, 10 | "defineConstraints": [], 11 | "versionDefines": [], 12 | "noEngineReferences": false 13 | } -------------------------------------------------------------------------------- /Plugins/LastAbyss.SimpleGraphQL.Plugins.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 15e3c116196bd394da80b1072fff8aa8 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 512d31505eba4ccb9eeeaf5871f5e3c8 3 | timeCreated: 1589081400 -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b7df4c30c24f4ee3a0e0b6333a43d71e 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 022d8d5fc15c4ed1a712d121088f380e 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/ASTNode.cs: -------------------------------------------------------------------------------- 1 | namespace SimpleGraphQL.GraphQLParser.AST 2 | { 3 | public abstract class ASTNode 4 | { 5 | public abstract ASTNodeKind Kind { get; } 6 | 7 | public GraphQLLocation Location { get; set; } 8 | 9 | public GraphQLComment Comment { get; set; } 10 | } 11 | } -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/ASTNode.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 43bdb41dd6494ff290ab06c915bb7eec 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/Enums.cs: -------------------------------------------------------------------------------- 1 | namespace SimpleGraphQL.GraphQLParser.AST 2 | { 3 | public enum ASTNodeKind 4 | { 5 | Name, 6 | Document, 7 | OperationDefinition, 8 | VariableDefinition, 9 | Variable, 10 | SelectionSet, 11 | Field, 12 | Argument, 13 | FragmentSpread, 14 | InlineFragment, 15 | FragmentDefinition, 16 | IntValue, 17 | FloatValue, 18 | StringValue, 19 | BooleanValue, 20 | EnumValue, 21 | ListValue, 22 | ObjectValue, 23 | ObjectField, 24 | Directive, 25 | NamedType, 26 | ListType, 27 | NonNullType, 28 | NullValue, 29 | SchemaDefinition, 30 | OperationTypeDefinition, 31 | ScalarTypeDefinition, 32 | ObjectTypeDefinition, 33 | FieldDefinition, 34 | InputValueDefinition, 35 | InterfaceTypeDefinition, 36 | UnionTypeDefinition, 37 | EnumTypeDefinition, 38 | EnumValueDefinition, 39 | InputObjectTypeDefinition, 40 | TypeExtensionDefinition, 41 | DirectiveDefinition, 42 | Comment, 43 | } 44 | 45 | public enum OperationType 46 | { 47 | Query, 48 | Mutation, 49 | Subscription 50 | } 51 | } -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/Enums.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f65294b062854693af42948510b842da 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLArgument.cs: -------------------------------------------------------------------------------- 1 | namespace SimpleGraphQL.GraphQLParser.AST 2 | { 3 | public class GraphQLArgument : ASTNode, INamedNode 4 | { 5 | public override ASTNodeKind Kind => ASTNodeKind.Argument; 6 | 7 | public GraphQLName Name { get; set; } 8 | 9 | public GraphQLValue Value { get; set; } 10 | } 11 | } -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLArgument.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d133ff7838f541e2a73bbe957df55afd 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLComment.cs: -------------------------------------------------------------------------------- 1 | namespace SimpleGraphQL.GraphQLParser.AST 2 | { 3 | public class GraphQLComment : ASTNode 4 | { 5 | public GraphQLComment(string text) 6 | { 7 | Text = text; 8 | } 9 | 10 | public override ASTNodeKind Kind => ASTNodeKind.Comment; 11 | 12 | public string Text { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLComment.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 40589f7e40454cd78f09f0103e775f64 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLDirective.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace SimpleGraphQL.GraphQLParser.AST 4 | { 5 | public class GraphQLDirective : ASTNode, INamedNode 6 | { 7 | public List Arguments { get; set; } 8 | 9 | public override ASTNodeKind Kind => ASTNodeKind.Directive; 10 | 11 | public GraphQLName Name { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLDirective.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9bd4536df9cc4f26acabbed79b1cd889 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLDirectiveDefinition.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace SimpleGraphQL.GraphQLParser.AST 4 | { 5 | public class GraphQLDirectiveDefinition : GraphQLTypeDefinition 6 | { 7 | public List Arguments { get; set; } 8 | 9 | public List Definitions { get; set; } 10 | 11 | public override ASTNodeKind Kind => ASTNodeKind.DirectiveDefinition; 12 | 13 | public List Locations { get; set; } 14 | 15 | public bool Repeatable { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLDirectiveDefinition.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 292b76ad8d34437d9ee1c25ad5acb326 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLDocument.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace SimpleGraphQL.GraphQLParser.AST 4 | { 5 | public class GraphQLDocument : ASTNode 6 | { 7 | public List Definitions { get; set; } 8 | 9 | public override ASTNodeKind Kind => ASTNodeKind.Document; 10 | } 11 | } -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLDocument.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: cf135bc518584f58ab1510c8e228d44d 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLEnumTypeDefinition.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace SimpleGraphQL.GraphQLParser.AST 4 | { 5 | public class GraphQLEnumTypeDefinition : GraphQLTypeDefinition, IHasDirectivesNode 6 | { 7 | public List Directives { get; set; } 8 | 9 | public override ASTNodeKind Kind => ASTNodeKind.EnumTypeDefinition; 10 | 11 | public List Values { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLEnumTypeDefinition.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 445a087851944ce18d769b4c5d7cf4d6 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLEnumValueDefinition.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace SimpleGraphQL.GraphQLParser.AST 4 | { 5 | public class GraphQLEnumValueDefinition : GraphQLTypeDefinition, IHasDirectivesNode 6 | { 7 | public List Directives { get; set; } 8 | 9 | public override ASTNodeKind Kind => ASTNodeKind.EnumValueDefinition; 10 | } 11 | } -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLEnumValueDefinition.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 03302390660145809bcead5c4b60a323 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLFieldDefinition.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace SimpleGraphQL.GraphQLParser.AST 4 | { 5 | public class GraphQLFieldDefinition : GraphQLTypeDefinition, IHasDirectivesNode 6 | { 7 | public List Arguments { get; set; } 8 | 9 | public List Directives { get; set; } 10 | 11 | public override ASTNodeKind Kind => ASTNodeKind.FieldDefinition; 12 | 13 | public GraphQLType Type { get; set; } 14 | } 15 | } -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLFieldDefinition.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d8c18191cb104baf9d712aea016c3ad1 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLFieldSelection.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace SimpleGraphQL.GraphQLParser.AST 4 | { 5 | public class GraphQLFieldSelection : ASTNode, IHasDirectivesNode, INamedNode 6 | { 7 | public GraphQLName Alias { get; set; } 8 | 9 | public List Arguments { get; set; } 10 | 11 | public List Directives { get; set; } 12 | 13 | public override ASTNodeKind Kind => ASTNodeKind.Field; 14 | 15 | public GraphQLName Name { get; set; } 16 | 17 | public GraphQLSelectionSet SelectionSet { get; set; } 18 | } 19 | } -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLFieldSelection.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5ac3ed16c9ef42a9a6510fa84c1b7550 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLFragmentDefinition.cs: -------------------------------------------------------------------------------- 1 | namespace SimpleGraphQL.GraphQLParser.AST 2 | { 3 | public class GraphQLFragmentDefinition : GraphQLInlineFragment, INamedNode 4 | { 5 | public override ASTNodeKind Kind => ASTNodeKind.FragmentDefinition; 6 | 7 | public GraphQLName Name { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLFragmentDefinition.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5b96e6a344fe462baa48d0bd35a82629 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLFragmentSpread.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace SimpleGraphQL.GraphQLParser.AST 4 | { 5 | public class GraphQLFragmentSpread : ASTNode, IHasDirectivesNode, INamedNode 6 | { 7 | public List Directives { get; set; } 8 | 9 | public override ASTNodeKind Kind => ASTNodeKind.FragmentSpread; 10 | 11 | public GraphQLName Name { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLFragmentSpread.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b9929f6f582e4bc6a8e0a8d992adaf5a 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLInlineFragment.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace SimpleGraphQL.GraphQLParser.AST 4 | { 5 | public class GraphQLInlineFragment : ASTNode, IHasDirectivesNode 6 | { 7 | public List Directives { get; set; } 8 | 9 | public override ASTNodeKind Kind => ASTNodeKind.InlineFragment; 10 | 11 | public GraphQLSelectionSet SelectionSet { get; set; } 12 | 13 | public GraphQLNamedType TypeCondition { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLInlineFragment.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e733c763273f478393b3f9a2897153d2 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLInputObjectTypeDefinition.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace SimpleGraphQL.GraphQLParser.AST 4 | { 5 | public class GraphQLInputObjectTypeDefinition : GraphQLTypeDefinition, IHasDirectivesNode 6 | { 7 | public List Directives { get; set; } 8 | 9 | public List Fields { get; set; } 10 | 11 | public override ASTNodeKind Kind => ASTNodeKind.InputObjectTypeDefinition; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLInputObjectTypeDefinition.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d3512b986edf4546a03a31a34875f087 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLInputValueDefinition.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace SimpleGraphQL.GraphQLParser.AST 4 | { 5 | public class GraphQLInputValueDefinition : GraphQLTypeDefinition, IHasDirectivesNode 6 | { 7 | public GraphQLValue DefaultValue { get; set; } 8 | 9 | public List Directives { get; set; } 10 | 11 | public override ASTNodeKind Kind => ASTNodeKind.InputValueDefinition; 12 | 13 | public GraphQLType Type { get; set; } 14 | } 15 | } -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLInputValueDefinition.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9f8224f95d474de8bdbd53857d73e86a 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLInterfaceTypeDefinition.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace SimpleGraphQL.GraphQLParser.AST 4 | { 5 | public class GraphQLInterfaceTypeDefinition : GraphQLTypeDefinition, IHasDirectivesNode 6 | { 7 | public List Directives { get; set; } 8 | 9 | public List Fields { get; set; } 10 | 11 | public override ASTNodeKind Kind => ASTNodeKind.InterfaceTypeDefinition; 12 | } 13 | } -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLInterfaceTypeDefinition.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7eaaf43c290f42578015223a39fe76b9 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLListType.cs: -------------------------------------------------------------------------------- 1 | namespace SimpleGraphQL.GraphQLParser.AST 2 | { 3 | public class GraphQLListType : GraphQLType 4 | { 5 | public override ASTNodeKind Kind => ASTNodeKind.ListType; 6 | 7 | public GraphQLType Type { get; set; } 8 | 9 | public override string ToString() => $"[{Type}]"; 10 | } 11 | } -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLListType.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6036f30fd8f643b2b28c404f5692f29f 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLListValue.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace SimpleGraphQL.GraphQLParser.AST 4 | { 5 | public class GraphQLListValue : GraphQLValue 6 | { 7 | private readonly ASTNodeKind _kind; 8 | 9 | public GraphQLListValue(ASTNodeKind kind) 10 | { 11 | _kind = kind; 12 | } 13 | 14 | public string AstValue { get; set; } 15 | 16 | public override ASTNodeKind Kind => _kind; 17 | 18 | public List Values { get; set; } 19 | 20 | public override string ToString() => AstValue; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLListValue.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 46ff0b607d5f4b8ebc161b32c63134a0 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLLocation.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | 3 | namespace SimpleGraphQL.GraphQLParser.AST 4 | { 5 | [DebuggerDisplay("(Start={Start}, End={End})")] 6 | public readonly struct GraphQLLocation 7 | { 8 | public GraphQLLocation(int start, int end) 9 | { 10 | Start = start; 11 | End = end; 12 | } 13 | 14 | public int End { get; } 15 | 16 | public int Start { get; } 17 | } 18 | } -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLLocation.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: cfa03a59f9d04f9094b625198c511542 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLName.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | 3 | namespace SimpleGraphQL.GraphQLParser.AST 4 | { 5 | [DebuggerDisplay("{Value}")] 6 | public class GraphQLName : ASTNode 7 | { 8 | public override ASTNodeKind Kind => ASTNodeKind.Name; 9 | 10 | public string Value { get; set; } 11 | } 12 | } -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLName.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4e8650125f6f493fa75f4f832e81890f 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLNamedType.cs: -------------------------------------------------------------------------------- 1 | namespace SimpleGraphQL.GraphQLParser.AST 2 | { 3 | public class GraphQLNamedType : GraphQLType, INamedNode 4 | { 5 | public override ASTNodeKind Kind => ASTNodeKind.NamedType; 6 | 7 | public GraphQLName Name { get; set; } 8 | 9 | public override string ToString() => Name?.Value ?? string.Empty; 10 | } 11 | } -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLNamedType.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1628877a01b04ce5a654b45b685d7842 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLNonNullType.cs: -------------------------------------------------------------------------------- 1 | namespace SimpleGraphQL.GraphQLParser.AST 2 | { 3 | public class GraphQLNonNullType : GraphQLType 4 | { 5 | public override ASTNodeKind Kind => ASTNodeKind.NonNullType; 6 | 7 | public GraphQLType Type { get; set; } 8 | 9 | public override string ToString() => Type + "!"; 10 | } 11 | } -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLNonNullType.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9a4dbd24c97042b8af985c3d37a61bc6 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLObjectField.cs: -------------------------------------------------------------------------------- 1 | namespace SimpleGraphQL.GraphQLParser.AST 2 | { 3 | public class GraphQLObjectField : ASTNode, INamedNode 4 | { 5 | public override ASTNodeKind Kind => ASTNodeKind.ObjectField; 6 | 7 | public GraphQLName Name { get; set; } 8 | 9 | public GraphQLValue Value { get; set; } 10 | } 11 | } -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLObjectField.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 44b602750971440db348d2e2a09f9469 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLObjectTypeDefinition.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace SimpleGraphQL.GraphQLParser.AST 4 | { 5 | public class GraphQLObjectTypeDefinition : GraphQLTypeDefinition, IHasDirectivesNode 6 | { 7 | public List Directives { get; set; } 8 | 9 | public List Fields { get; set; } 10 | 11 | public List Interfaces { get; set; } 12 | 13 | public override ASTNodeKind Kind => ASTNodeKind.ObjectTypeDefinition; 14 | } 15 | } -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLObjectTypeDefinition.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ddedc2b0cb054952817264c9c2c91436 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLObjectValue.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace SimpleGraphQL.GraphQLParser.AST 4 | { 5 | public class GraphQLObjectValue : GraphQLValue 6 | { 7 | public List Fields { get; set; } 8 | 9 | public override ASTNodeKind Kind => ASTNodeKind.ObjectValue; 10 | } 11 | } -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLObjectValue.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d02b67ae1fcf410380420612aa9c9d41 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLOperationDefinition.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace SimpleGraphQL.GraphQLParser.AST 4 | { 5 | public class GraphQLOperationDefinition : ASTNode, IHasDirectivesNode, INamedNode 6 | { 7 | public List Directives { get; set; } 8 | 9 | public override ASTNodeKind Kind => ASTNodeKind.OperationDefinition; 10 | 11 | public GraphQLName Name { get; set; } 12 | 13 | public OperationType Operation { get; set; } 14 | 15 | public GraphQLSelectionSet SelectionSet { get; set; } 16 | 17 | public List VariableDefinitions { get; set; } 18 | } 19 | } -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLOperationDefinition.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fb5dd4e82a334209b2f3a5d9c8d60a35 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLOperationTypeDefinition.cs: -------------------------------------------------------------------------------- 1 | namespace SimpleGraphQL.GraphQLParser.AST 2 | { 3 | public class GraphQLOperationTypeDefinition : ASTNode 4 | { 5 | public override ASTNodeKind Kind => ASTNodeKind.OperationTypeDefinition; 6 | 7 | public OperationType Operation { get; set; } 8 | 9 | public GraphQLNamedType Type { get; set; } 10 | } 11 | } -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLOperationTypeDefinition.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1c2d37a6597f4529b9e916ad1e3f8ab5 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLScalarTypeDefinition.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace SimpleGraphQL.GraphQLParser.AST 4 | { 5 | public class GraphQLScalarTypeDefinition : GraphQLTypeDefinition, IHasDirectivesNode 6 | { 7 | public List Directives { get; set; } 8 | 9 | public override ASTNodeKind Kind => ASTNodeKind.ScalarTypeDefinition; 10 | } 11 | } -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLScalarTypeDefinition.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ef28f11ad2034da49faa8ce74ac9cfda 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLScalarValue.cs: -------------------------------------------------------------------------------- 1 | namespace SimpleGraphQL.GraphQLParser.AST 2 | { 3 | public class GraphQLScalarValue : GraphQLValue 4 | { 5 | private readonly ASTNodeKind _kind; 6 | 7 | public GraphQLScalarValue(ASTNodeKind kind) 8 | { 9 | _kind = kind; 10 | } 11 | 12 | public override ASTNodeKind Kind => _kind; 13 | 14 | public string Value { get; set; } 15 | 16 | public override string ToString() => Kind == ASTNodeKind.StringValue ? $"\"{Value}\"" : Value; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLScalarValue.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 30d249f9fd264392a99f3edeee64a19b 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLSchemaDefinition.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace SimpleGraphQL.GraphQLParser.AST 4 | { 5 | public class GraphQLSchemaDefinition : ASTNode, IHasDirectivesNode 6 | { 7 | public List Directives { get; set; } 8 | 9 | public override ASTNodeKind Kind => ASTNodeKind.SchemaDefinition; 10 | 11 | public List OperationTypes { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLSchemaDefinition.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fdba8931f2194e6f8b03484e456264b4 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLSelectionSet.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace SimpleGraphQL.GraphQLParser.AST 4 | { 5 | public class GraphQLSelectionSet : ASTNode 6 | { 7 | public override ASTNodeKind Kind => ASTNodeKind.SelectionSet; 8 | 9 | public List Selections { get; set; } 10 | } 11 | } -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLSelectionSet.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d8212895c2294713baa68e911f378d1a 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLType.cs: -------------------------------------------------------------------------------- 1 | namespace SimpleGraphQL.GraphQLParser.AST 2 | { 3 | public abstract class GraphQLType : ASTNode 4 | { 5 | } 6 | } -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLType.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6661fe9abb0e419ea9e360d8aa0c5bac 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLTypeDefinition.cs: -------------------------------------------------------------------------------- 1 | namespace SimpleGraphQL.GraphQLParser.AST 2 | { 3 | public abstract class GraphQLTypeDefinition : ASTNode, INamedNode 4 | { 5 | public GraphQLName Name { get; set; } 6 | } 7 | } -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLTypeDefinition.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d0bacaa462f4492896335ec5deee9fda 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLTypeExtensionDefinition.cs: -------------------------------------------------------------------------------- 1 | namespace SimpleGraphQL.GraphQLParser.AST 2 | { 3 | public class GraphQLTypeExtensionDefinition : GraphQLTypeDefinition 4 | { 5 | public GraphQLObjectTypeDefinition Definition { get; set; } 6 | 7 | public override ASTNodeKind Kind => ASTNodeKind.TypeExtensionDefinition; 8 | } 9 | } -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLTypeExtensionDefinition.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ff63d17a6dda4b939e71252f98a9eca4 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLUnionTypeDefinition.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace SimpleGraphQL.GraphQLParser.AST 4 | { 5 | public class GraphQLUnionTypeDefinition : GraphQLTypeDefinition, IHasDirectivesNode 6 | { 7 | public List Directives { get; set; } 8 | 9 | public override ASTNodeKind Kind => ASTNodeKind.UnionTypeDefinition; 10 | 11 | public List Types { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLUnionTypeDefinition.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2727aa8545f34d45b1d1bea5f788d1a1 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLValue.cs: -------------------------------------------------------------------------------- 1 | namespace SimpleGraphQL.GraphQLParser.AST 2 | { 3 | public abstract class GraphQLValue : ASTNode 4 | { 5 | } 6 | } -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLValue.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: dd947b3f9dda43088562e8c9693aef07 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLVariable.cs: -------------------------------------------------------------------------------- 1 | namespace SimpleGraphQL.GraphQLParser.AST 2 | { 3 | public class GraphQLVariable : GraphQLValue, INamedNode 4 | { 5 | public override ASTNodeKind Kind => ASTNodeKind.Variable; 6 | 7 | public GraphQLName Name { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLVariable.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2e5112b7bc114e5796907a42fdfc75fa 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLVariableDefinition.cs: -------------------------------------------------------------------------------- 1 | namespace SimpleGraphQL.GraphQLParser.AST 2 | { 3 | public class GraphQLVariableDefinition : ASTNode 4 | { 5 | public object DefaultValue { get; set; } 6 | 7 | public override ASTNodeKind Kind => ASTNodeKind.VariableDefinition; 8 | 9 | public GraphQLType Type { get; set; } 10 | 11 | public GraphQLVariable Variable { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/GraphQLVariableDefinition.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6221afbd1e5e47e094028df7d5955f1f 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/IHasDirectivesNode.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace SimpleGraphQL.GraphQLParser.AST 4 | { 5 | public interface IHasDirectivesNode 6 | { 7 | List Directives { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/IHasDirectivesNode.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a2544b37875c4939880a9cc1b7db8467 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/INamedNode.cs: -------------------------------------------------------------------------------- 1 | namespace SimpleGraphQL.GraphQLParser.AST 2 | { 3 | public interface INamedNode 4 | { 5 | GraphQLName Name { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/AST/INamedNode.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 593b5a49c80641be93346d68ec07b59f 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/Cache.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d2541f3af1884e1f842daa7c7a736db7 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/Cache/ConcurrentDictionaryCache.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Concurrent; 3 | using System.Collections.Generic; 4 | 5 | namespace SimpleGraphQL.GraphQLParser.Cache 6 | { 7 | public sealed class ConcurrentDictionaryCache : ILexemeCache 8 | { 9 | private readonly ConcurrentDictionary _cache = new ConcurrentDictionary(); 10 | private readonly ConcurrentDictionary _intCache = new ConcurrentDictionary(); 11 | private readonly object _listLock = new object(); 12 | 13 | public void Clear() 14 | { 15 | _cache.Clear(); 16 | _intCache.Clear(); 17 | } 18 | 19 | public bool AllowIntCache { get; set; } 20 | 21 | public string GetName(string source, int start, int end) 22 | { 23 | if (start == end) 24 | return string.Empty; 25 | 26 | var hash = StringHelper.GetHashCode(source, start, end); 27 | 28 | if (!_cache.TryGetValue(hash, out var value)) 29 | { 30 | // absolutely new string 31 | string result = source.Substring(start, end - start); 32 | _cache[hash] = result; 33 | return result; 34 | } 35 | else if (value is string str) 36 | { 37 | // the string is already in cache, we need to compare 38 | if (StringHelper.Equals(str, source, start, end)) 39 | { 40 | return str; // cache hit! 41 | } 42 | else 43 | { 44 | // cache miss - hashes are the same but the actual values of the strings are different so need to allocate list with both strings 45 | var result = source.Substring(start, end - start); 46 | var list = new List { str, result }; 47 | _cache[hash] = list; 48 | return result; 49 | } 50 | } 51 | else if (value is List list) 52 | { 53 | lock (_listLock) 54 | { 55 | // comparison by value among all elements of the list 56 | foreach (var element in list) 57 | if (StringHelper.Equals(element, source, start, end)) 58 | return element; // cache hit! 59 | 60 | // an even rarer cache miss - repeated hash collision 61 | var result = source.Substring(start, end - start); 62 | list.Add(result); 63 | return result; 64 | } 65 | } 66 | else 67 | throw new NotSupportedException(); 68 | } 69 | 70 | public string GetInt(string source, int start, int end) 71 | { 72 | if (!AllowIntCache || end - start > 9) 73 | return source.Substring(start, end - start); 74 | 75 | var hash = StringHelper.ParseInt(source, start, end); 76 | 77 | if (!_intCache.TryGetValue(hash, out var value)) 78 | { 79 | // copy into locals to suppress too early closure allocation of Func 80 | var localSource = source; 81 | var localStart = start; 82 | var localEnd = end; 83 | value = _intCache.GetOrAdd(hash, _ => localSource.Substring(localStart, localEnd - localStart)); 84 | } 85 | 86 | return value; 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/Cache/ConcurrentDictionaryCache.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bd6f92d22e5746f193323bd6db65b599 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/Cache/DictionaryCache.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace SimpleGraphQL.GraphQLParser.Cache 5 | { 6 | public sealed class DictionaryCache : ILexemeCache 7 | { 8 | private readonly Dictionary _cache = new Dictionary(); 9 | private readonly Dictionary _intCache = new Dictionary(); 10 | 11 | public void Clear() 12 | { 13 | _cache.Clear(); 14 | _intCache.Clear(); 15 | } 16 | 17 | public bool AllowIntCache { get; set; } 18 | 19 | public string GetName(string source, int start, int end) 20 | { 21 | if (start == end) 22 | return string.Empty; 23 | 24 | var hash = StringHelper.GetHashCode(source, start, end); 25 | 26 | if (!_cache.TryGetValue(hash, out var value)) 27 | { 28 | // absolutely new string 29 | string result = source.Substring(start, end - start); 30 | _cache[hash] = result; 31 | return result; 32 | } 33 | else if (value is string str) 34 | { 35 | // the string is already in cache, we need to compare 36 | if (StringHelper.Equals(str, source, start, end)) 37 | { 38 | return str; // cache hit! 39 | } 40 | else 41 | { 42 | // cache miss - hashes are the same but the actual values of the strings are different so need to allocate list with both strings 43 | var result = source.Substring(start, end - start); 44 | var list = new List { str, result }; 45 | _cache[hash] = list; 46 | return result; 47 | } 48 | } 49 | else if (value is List list) 50 | { 51 | // comparison by value among all elements of the list 52 | foreach (var element in list) 53 | if (StringHelper.Equals(element, source, start, end)) 54 | return element; // cache hit! 55 | 56 | // an even rarer cache miss - repeated hash collision 57 | var result = source.Substring(start, end - start); 58 | list.Add(result); 59 | return result; 60 | } 61 | else 62 | throw new NotSupportedException(); 63 | } 64 | 65 | public string GetInt(string source, int start, int end) 66 | { 67 | if (!AllowIntCache || end - start > 9) 68 | return source.Substring(start, end - start); 69 | 70 | var hash = StringHelper.ParseInt(source, start, end); 71 | 72 | if (!_intCache.TryGetValue(hash, out var value)) 73 | _intCache[hash] = value = source.Substring(start, end - start); 74 | 75 | return value; 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/Cache/DictionaryCache.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 920e198b447c4168a2744270408ed0f2 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/Cache/ILexemeCache.cs: -------------------------------------------------------------------------------- 1 | namespace SimpleGraphQL.GraphQLParser.Cache 2 | { 3 | /// 4 | /// Interface for caching token values. This cache allows you to reuse string values such 5 | /// as field names, argument values received when the is running. 6 | /// 7 | public interface ILexemeCache 8 | { 9 | string GetName(string source, int start, int end); 10 | 11 | string GetInt(string source, int start, int end); 12 | 13 | void Clear(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/Cache/ILexemeCache.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 28b9d88630314c3f860b5ad4fe9a9537 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/Cache/NoCache.cs: -------------------------------------------------------------------------------- 1 | namespace SimpleGraphQL.GraphQLParser.Cache 2 | { 3 | /// 4 | /// implementation without caching. It is used by default. 5 | /// 6 | public sealed class NoCache : ILexemeCache 7 | { 8 | public static readonly NoCache Instance = new NoCache(); 9 | 10 | public string GetName(string source, int start, int end) => source.Substring(start, end - start); 11 | 12 | public string GetInt(string source, int start, int end) => source.Substring(start, end - start); 13 | 14 | public void Clear() { } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/Cache/NoCache.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 48c892ec2b8d41bfb0567d62f0696e3c 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/Cache/StringHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SimpleGraphQL.GraphQLParser.Cache 4 | { 5 | internal static class StringHelper 6 | { 7 | /// 8 | /// Determines the equivalence of the string to a substring from 9 | /// defined by the and index. 10 | /// 11 | /// 12 | /// 13 | /// 14 | /// 15 | /// 16 | public static bool Equals(string str, string source, int start, int end) 17 | { 18 | if (str.Length != end - start) 19 | return false; 20 | 21 | for (int i = 0; i < str.Length; ++i) 22 | if (str[i] != source[start + i]) 23 | return false; 24 | 25 | return true; 26 | } 27 | 28 | /// 29 | /// Determines the hash code of the substring from the specified by 30 | /// the and index. 31 | /// 32 | /// 33 | /// 34 | /// 35 | /// 36 | public static int GetHashCode(string source, int start, int end) 37 | { 38 | if (start > source.Length || end > source.Length || start < 0 || end < 0) 39 | throw new IndexOutOfRangeException(); 40 | 41 | int num1 = 5381; 42 | int num2 = num1; 43 | int num3; 44 | end -= 1; 45 | 46 | for (int i = start; i <= end; i += 2) 47 | { 48 | num3 = source[i]; 49 | num1 = (num1 << 5) + num1 ^ num3; 50 | if (i == end) 51 | break; 52 | int num4 = source[i + 1]; 53 | if (num4 != 0) 54 | num2 = (num2 << 5) + num2 ^ num4; 55 | else 56 | break; 57 | } 58 | 59 | return num1 + num2 * 1566083941; 60 | } 61 | 62 | /// 63 | /// Gets the integer value of the substring from the specified 64 | /// by the and index. 65 | /// 66 | /// 67 | /// 68 | /// 69 | /// 70 | public static int ParseInt(string source, int start, int end) 71 | { 72 | if (end - start > 9) 73 | throw new NotSupportedException(); 74 | 75 | int current = 0; 76 | 77 | if (source[start] == '-') 78 | { 79 | ++start; 80 | for (int i = end - 1, power = 1; i >= start; --i, power *= 10) 81 | { 82 | current += (source[i] - '0') * power; 83 | } 84 | return -current; 85 | } 86 | else 87 | { 88 | for (int i = end - 1, power = 1; i >= start; --i, power *= 10) 89 | { 90 | current += (source[i] - '0') * power; 91 | } 92 | return current; 93 | } 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/Cache/StringHelper.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e0716f25acc14296a6bb21aba37ef92b 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/Exceptions.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0fe111e2537b486ba2e8167aa03c7b04 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/Exceptions/GraphQLSyntaxErrorException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Text; 4 | 5 | namespace SimpleGraphQL.GraphQLParser.Exceptions 6 | { 7 | public class GraphQLSyntaxErrorException : Exception 8 | { 9 | public GraphQLSyntaxErrorException(string description, ISource source, int location) 10 | : base(ComposeMessage(description, source, location)) { } 11 | 12 | private static string ComposeMessage(string description, ISource source, int loc) 13 | { 14 | var location = new Location(source, loc); 15 | 16 | return $"Syntax Error GraphQL ({location.Line}:{location.Column}) {description}" + 17 | "\n" + HighlightSourceAtLocation(source, location); 18 | } 19 | 20 | private static string HighlightSourceAtLocation(ISource source, Location location) 21 | { 22 | int line = location.Line; 23 | string prevLineNum = (line - 1).ToString(); 24 | string lineNum = line.ToString(); 25 | string nextLineNum = (line + 1).ToString(); 26 | int padLen = nextLineNum.Length; 27 | string[] lines = source.Body 28 | .Split(new string[] {"\n"}, StringSplitOptions.None) 29 | .Select(e => ReplaceWithUnicodeRepresentation(e)) 30 | .ToArray(); 31 | 32 | return 33 | (line >= 2 ? LeftPad(padLen, prevLineNum) + ": " + lines[line - 2] + "\n" : string.Empty) + 34 | LeftPad(padLen, lineNum) + ": " + lines[line - 1] + "\n" + 35 | LeftPad(1 + padLen + location.Column, string.Empty) + "^" + "\n" + 36 | (line < lines.Length ? LeftPad(padLen, nextLineNum) + ": " + lines[line] + "\n" : string.Empty); 37 | } 38 | 39 | private static string LeftPad(int length, string str) 40 | { 41 | string pad = string.Empty; 42 | 43 | for (int i = 0; i < length - str.Length; i++) 44 | pad += " "; 45 | 46 | return pad + str; 47 | } 48 | 49 | private static string ReplaceWithUnicodeRepresentation(string str) 50 | { 51 | if (!HasReplacementCharacter(str)) 52 | return str; 53 | 54 | var buffer = new StringBuilder(str.Length); 55 | 56 | foreach (char code in str) 57 | { 58 | if (IsReplacementCharacter(code)) 59 | { 60 | buffer.Append(GetUnicodeRepresentation(code)); 61 | } 62 | else 63 | { 64 | buffer.Append(code); 65 | } 66 | } 67 | 68 | return buffer.ToString(); 69 | } 70 | 71 | private static bool HasReplacementCharacter(string str) 72 | { 73 | foreach (char code in str) 74 | { 75 | if (IsReplacementCharacter(code)) 76 | return true; 77 | } 78 | 79 | return false; 80 | } 81 | 82 | private static bool IsReplacementCharacter(char code) => 83 | code < 0x0020 && code != 0x0009 && code != 0x000A && code != 0x000D; 84 | 85 | private static string GetUnicodeRepresentation(char code) 86 | { 87 | switch (code) 88 | { 89 | case '\0': 90 | return "\\u0000"; 91 | default: 92 | return "\\u" + ((int) code).ToString("D4"); 93 | } 94 | } 95 | } 96 | } -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/Exceptions/GraphQLSyntaxErrorException.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 82b844b3b4b043ec91c32f9710e83984 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/GraphQLAstVisitor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using SimpleGraphQL.GraphQLParser.AST; 4 | 5 | namespace SimpleGraphQL.GraphQLParser 6 | { 7 | public class GraphQLAstVisitor 8 | { 9 | protected IDictionary Fragments { get; private set; } 10 | 11 | public GraphQLAstVisitor() 12 | { 13 | Fragments = new Dictionary(); 14 | } 15 | 16 | public virtual GraphQLName BeginVisitAlias(GraphQLName alias) => alias; 17 | 18 | public virtual GraphQLArgument BeginVisitArgument(GraphQLArgument argument) 19 | { 20 | if (argument.Name != null) 21 | BeginVisitNode(argument.Name); 22 | 23 | if (argument.Value != null) 24 | BeginVisitNode(argument.Value); 25 | 26 | return EndVisitArgument(argument); 27 | } 28 | 29 | public virtual IEnumerable BeginVisitArguments(IEnumerable arguments) 30 | { 31 | foreach (var argument in arguments) 32 | BeginVisitNode(argument); 33 | 34 | return arguments; 35 | } 36 | 37 | public virtual GraphQLScalarValue BeginVisitBooleanValue(GraphQLScalarValue value) => value; 38 | 39 | public virtual GraphQLDirective BeginVisitDirective(GraphQLDirective directive) 40 | { 41 | if (directive.Name != null) 42 | BeginVisitNode(directive.Name); 43 | 44 | if (directive.Arguments != null) 45 | BeginVisitArguments(directive.Arguments); 46 | 47 | return directive; 48 | } 49 | 50 | public virtual IEnumerable BeginVisitDirectives(IEnumerable directives) 51 | { 52 | foreach (var directive in directives) 53 | BeginVisitNode(directive); 54 | 55 | return directives; 56 | } 57 | 58 | public virtual GraphQLScalarValue BeginVisitEnumValue(GraphQLScalarValue value) => value; 59 | 60 | public virtual GraphQLFieldSelection BeginVisitFieldSelection(GraphQLFieldSelection selection) 61 | { 62 | BeginVisitNode(selection.Name); 63 | 64 | if (selection.Alias != null) 65 | BeginVisitAlias((GraphQLName)BeginVisitNode(selection.Alias)); 66 | 67 | if (selection.Arguments != null) 68 | BeginVisitArguments(selection.Arguments); 69 | 70 | if (selection.SelectionSet != null) 71 | BeginVisitNode(selection.SelectionSet); 72 | 73 | if (selection.Directives != null) 74 | BeginVisitDirectives(selection.Directives); 75 | 76 | return EndVisitFieldSelection(selection); 77 | } 78 | 79 | public virtual GraphQLScalarValue BeginVisitFloatValue(GraphQLScalarValue value) => value; 80 | 81 | public virtual GraphQLFragmentDefinition BeginVisitFragmentDefinition(GraphQLFragmentDefinition node) 82 | { 83 | BeginVisitNode(node.TypeCondition); 84 | BeginVisitNode(node.Name); 85 | 86 | if (node.SelectionSet != null) 87 | BeginVisitNode(node.SelectionSet); 88 | 89 | return node; 90 | } 91 | 92 | public virtual GraphQLFragmentSpread BeginVisitFragmentSpread(GraphQLFragmentSpread fragmentSpread) 93 | { 94 | BeginVisitNode(fragmentSpread.Name); 95 | return fragmentSpread; 96 | } 97 | 98 | public virtual GraphQLInlineFragment BeginVisitInlineFragment(GraphQLInlineFragment inlineFragment) 99 | { 100 | if (inlineFragment.TypeCondition != null) 101 | BeginVisitNode(inlineFragment.TypeCondition); 102 | 103 | if (inlineFragment.Directives != null) 104 | BeginVisitDirectives(inlineFragment.Directives); 105 | 106 | if (inlineFragment.SelectionSet != null) 107 | BeginVisitSelectionSet(inlineFragment.SelectionSet); 108 | 109 | return inlineFragment; 110 | } 111 | 112 | public virtual GraphQLScalarValue BeginVisitIntValue(GraphQLScalarValue value) => value; 113 | 114 | public virtual GraphQLName BeginVisitName(GraphQLName name) => name; 115 | 116 | public virtual GraphQLNamedType BeginVisitNamedType(GraphQLNamedType typeCondition) => typeCondition; 117 | 118 | public virtual ASTNode BeginVisitNode(ASTNode node) 119 | { 120 | switch (node?.Kind) 121 | { 122 | case ASTNodeKind.OperationDefinition: 123 | return BeginVisitOperationDefinition((GraphQLOperationDefinition) node); 124 | case ASTNodeKind.SelectionSet: 125 | return BeginVisitSelectionSet((GraphQLSelectionSet) node); 126 | case ASTNodeKind.Field: 127 | return BeginVisitNonIntrospectionFieldSelection((GraphQLFieldSelection) node); 128 | case ASTNodeKind.Name: 129 | return BeginVisitName((GraphQLName) node); 130 | case ASTNodeKind.Argument: 131 | return BeginVisitArgument((GraphQLArgument) node); 132 | case ASTNodeKind.FragmentSpread: 133 | return BeginVisitFragmentSpread((GraphQLFragmentSpread) node); 134 | case ASTNodeKind.FragmentDefinition: 135 | return BeginVisitFragmentDefinition((GraphQLFragmentDefinition) node); 136 | case ASTNodeKind.InlineFragment: 137 | return BeginVisitInlineFragment((GraphQLInlineFragment) node); 138 | case ASTNodeKind.NamedType: 139 | return BeginVisitNamedType((GraphQLNamedType) node); 140 | case ASTNodeKind.Directive: 141 | return BeginVisitDirective((GraphQLDirective) node); 142 | case ASTNodeKind.Variable: 143 | return BeginVisitVariable((GraphQLVariable) node); 144 | case ASTNodeKind.IntValue: 145 | return BeginVisitIntValue((GraphQLScalarValue) node); 146 | case ASTNodeKind.FloatValue: 147 | return BeginVisitFloatValue((GraphQLScalarValue) node); 148 | case ASTNodeKind.StringValue: 149 | return BeginVisitStringValue((GraphQLScalarValue) node); 150 | case ASTNodeKind.BooleanValue: 151 | return BeginVisitBooleanValue((GraphQLScalarValue) node); 152 | case ASTNodeKind.EnumValue: 153 | return BeginVisitEnumValue((GraphQLScalarValue) node); 154 | case ASTNodeKind.ListValue: 155 | return BeginVisitListValue((GraphQLListValue) node); 156 | case ASTNodeKind.ObjectValue: 157 | return BeginVisitObjectValue((GraphQLObjectValue) node); 158 | case ASTNodeKind.ObjectField: 159 | return BeginVisitObjectField((GraphQLObjectField) node); 160 | case ASTNodeKind.VariableDefinition: 161 | return BeginVisitVariableDefinition((GraphQLVariableDefinition) node); 162 | default: 163 | return null; 164 | } 165 | } 166 | 167 | public virtual GraphQLOperationDefinition BeginVisitOperationDefinition(GraphQLOperationDefinition definition) 168 | { 169 | if (definition.Name != null) 170 | BeginVisitNode(definition.Name); 171 | 172 | if (definition.VariableDefinitions != null) 173 | BeginVisitVariableDefinitions(definition.VariableDefinitions); 174 | 175 | BeginVisitNode(definition.SelectionSet); 176 | 177 | return EndVisitOperationDefinition(definition); 178 | } 179 | 180 | public virtual GraphQLOperationDefinition EndVisitOperationDefinition(GraphQLOperationDefinition definition) => definition; 181 | 182 | public virtual GraphQLSelectionSet BeginVisitSelectionSet(GraphQLSelectionSet selectionSet) 183 | { 184 | if (selectionSet.Selections != null) 185 | { 186 | foreach (var selection in selectionSet.Selections) 187 | BeginVisitNode(selection); 188 | } 189 | 190 | return selectionSet; 191 | } 192 | 193 | public virtual GraphQLScalarValue BeginVisitStringValue(GraphQLScalarValue value) => value; 194 | 195 | public virtual GraphQLVariable BeginVisitVariable(GraphQLVariable variable) 196 | { 197 | if (variable.Name != null) 198 | BeginVisitNode(variable.Name); 199 | 200 | return EndVisitVariable(variable); 201 | } 202 | 203 | public virtual GraphQLVariableDefinition BeginVisitVariableDefinition(GraphQLVariableDefinition node) 204 | { 205 | BeginVisitNode(node.Type); 206 | 207 | return node; 208 | } 209 | 210 | public virtual IEnumerable BeginVisitVariableDefinitions(IEnumerable variableDefinitions) 211 | { 212 | foreach (var definition in variableDefinitions) 213 | BeginVisitNode(definition); 214 | 215 | return variableDefinitions; 216 | } 217 | 218 | public virtual GraphQLArgument EndVisitArgument(GraphQLArgument argument) => argument; 219 | 220 | public virtual GraphQLFieldSelection EndVisitFieldSelection(GraphQLFieldSelection selection) => selection; 221 | 222 | public virtual GraphQLVariable EndVisitVariable(GraphQLVariable variable) => variable; 223 | 224 | public virtual void Visit(GraphQLDocument ast) 225 | { 226 | if (ast.Definitions != null) 227 | { 228 | foreach (var definition in ast.Definitions) 229 | { 230 | if (definition.Kind == ASTNodeKind.FragmentDefinition) 231 | { 232 | var fragment = (GraphQLFragmentDefinition)definition; 233 | string name = fragment.Name?.Value; 234 | if (name == null) 235 | throw new InvalidOperationException("Fragment name cannot be null"); 236 | 237 | Fragments.Add(name, fragment); 238 | } 239 | } 240 | 241 | foreach (var definition in ast.Definitions) 242 | { 243 | BeginVisitNode(definition); 244 | } 245 | } 246 | } 247 | 248 | public virtual GraphQLObjectField BeginVisitObjectField(GraphQLObjectField node) 249 | { 250 | BeginVisitNode(node.Name); 251 | 252 | BeginVisitNode(node.Value); 253 | 254 | return node; 255 | } 256 | 257 | public virtual GraphQLObjectValue BeginVisitObjectValue(GraphQLObjectValue node) 258 | { 259 | if (node.Fields != null) 260 | { 261 | foreach (var field in node.Fields) 262 | BeginVisitNode(field); 263 | } 264 | 265 | return EndVisitObjectValue(node); 266 | } 267 | 268 | public virtual GraphQLObjectValue EndVisitObjectValue(GraphQLObjectValue node) => node; 269 | 270 | public virtual GraphQLListValue EndVisitListValue(GraphQLListValue node) => node; 271 | 272 | private ASTNode BeginVisitListValue(GraphQLListValue node) 273 | { 274 | if (node.Values != null) 275 | { 276 | foreach (var value in node.Values) 277 | BeginVisitNode(value); 278 | } 279 | 280 | return EndVisitListValue(node); 281 | } 282 | 283 | private ASTNode BeginVisitNonIntrospectionFieldSelection(GraphQLFieldSelection selection) 284 | { 285 | return BeginVisitFieldSelection(selection); 286 | } 287 | } 288 | } 289 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/GraphQLAstVisitor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9744eb45ecd34b6b8506a4c8eac02046 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/ILexer.cs: -------------------------------------------------------------------------------- 1 | namespace SimpleGraphQL.GraphQLParser 2 | { 3 | public interface ILexer 4 | { 5 | Token Lex(ISource source); 6 | 7 | Token Lex(ISource source, int start); 8 | } 9 | } -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/ILexer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 475c3148d8dc4639a8e05bb46857db0c 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/ISource.cs: -------------------------------------------------------------------------------- 1 | namespace SimpleGraphQL.GraphQLParser 2 | { 3 | public interface ISource 4 | { 5 | string Body { get; set; } 6 | 7 | string Name { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/ISource.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 58bf70d22f5a47acabdb86655ad8e4a4 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Marek Magdziak 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/LICENSE.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 674b4bb514a641b8bd2a7d4b782d10da 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/Lexer.cs: -------------------------------------------------------------------------------- 1 | using SimpleGraphQL.GraphQLParser.Cache; 2 | 3 | namespace SimpleGraphQL.GraphQLParser 4 | { 5 | public class Lexer : ILexer 6 | { 7 | public ILexemeCache Cache { get; set; } 8 | 9 | public Token Lex(ISource source) => Lex(source, 0); 10 | 11 | public Token Lex(ISource source, int start) 12 | { 13 | var context = new LexerContext(source, start, Cache); 14 | return context.GetToken(); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/Lexer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6e64ce89458149cd8f128a003a0422a5 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/LexerContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SimpleGraphQL.GraphQLParser.Cache; 3 | using SimpleGraphQL.GraphQLParser.Exceptions; 4 | 5 | namespace SimpleGraphQL.GraphQLParser 6 | { 7 | // WARNING: mutable struct, pass it by reference to those methods that will change it 8 | internal struct LexerContext 9 | { 10 | private int _currentIndex; 11 | private readonly ISource _source; 12 | private readonly ILexemeCache _cache; 13 | 14 | public LexerContext(ISource source, int index, ILexemeCache cache) 15 | { 16 | _currentIndex = index; 17 | _source = source; 18 | _cache = cache ?? NoCache.Instance; 19 | } 20 | 21 | public Token GetToken() 22 | { 23 | if (_source.Body == null) 24 | return CreateEOFToken(); 25 | 26 | _currentIndex = GetPositionAfterWhitespace(_source.Body, _currentIndex); 27 | 28 | if (_currentIndex >= _source.Body.Length) 29 | return CreateEOFToken(); 30 | 31 | char code = _source.Body[_currentIndex]; 32 | 33 | ValidateCharacterCode(code); 34 | 35 | var token = CheckForPunctuationTokens(code); 36 | if (token.Kind != TokenKind.UNKNOWN) 37 | return token; 38 | 39 | if (code == '#') 40 | return ReadComment(); 41 | 42 | if (char.IsLetter(code) || code == '_') 43 | return ReadName(); 44 | 45 | if (char.IsNumber(code) || code == '-') 46 | return ReadNumber(); 47 | 48 | if (code == '"') 49 | return ReadString(); 50 | 51 | throw new GraphQLSyntaxErrorException( 52 | $"Unexpected character {ResolveCharName(code, IfUnicodeGetString())}", _source, _currentIndex); 53 | } 54 | 55 | public bool OnlyHexInString(string test) => 56 | System.Text.RegularExpressions.Regex.IsMatch(test, @"\A\b[0-9a-fA-F]+\b\Z"); 57 | 58 | public Token ReadComment() 59 | { 60 | int start = _currentIndex; 61 | 62 | int chunkStart = ++_currentIndex; 63 | char code = GetCode(); 64 | string value = string.Empty; 65 | 66 | while (IsNotAtTheEndOfQuery() && code != 0x000A && code != 0x000D) 67 | { 68 | code = ProcessCharacter(ref value, ref chunkStart); 69 | } 70 | 71 | value += _source.Body.Substring(chunkStart, _currentIndex - chunkStart); 72 | 73 | return new Token 74 | ( 75 | TokenKind.COMMENT, 76 | value, 77 | start, 78 | _currentIndex + 1 79 | ); 80 | } 81 | 82 | public Token ReadNumber() 83 | { 84 | bool isFloat = false; 85 | int start = _currentIndex; 86 | char code = _source.Body[start]; 87 | 88 | if (code == '-') 89 | code = NextCode(); 90 | 91 | char nextCode = code == '0' 92 | ? NextCode() 93 | : ReadDigitsFromOwnSource(code); 94 | 95 | if (nextCode >= 48 && nextCode <= 57) 96 | { 97 | throw new GraphQLSyntaxErrorException( 98 | $"Invalid number, unexpected digit after {code}: \"{nextCode}\"", _source, _currentIndex); 99 | } 100 | 101 | code = nextCode; 102 | if (code == '.') 103 | { 104 | isFloat = true; 105 | code = ReadDigitsFromOwnSource(NextCode()); 106 | } 107 | 108 | if (code == 'E' || code == 'e') 109 | { 110 | isFloat = true; 111 | code = NextCode(); 112 | if (code == '+' || code == '-') 113 | { 114 | code = NextCode(); 115 | } 116 | 117 | code = ReadDigitsFromOwnSource(code); 118 | } 119 | 120 | return isFloat ? CreateFloatToken(start) : CreateIntToken(start); 121 | } 122 | 123 | public Token ReadString() 124 | { 125 | int start = _currentIndex; 126 | string value = ProcessStringChunks(); 127 | 128 | return new Token 129 | ( 130 | TokenKind.STRING, 131 | value, 132 | start, 133 | _currentIndex + 1 134 | ); 135 | } 136 | 137 | private static bool IsValidNameCharacter(char code) => code == '_' || char.IsLetterOrDigit(code); 138 | 139 | private string AppendCharactersFromLastChunk(string value, int chunkStart) 140 | { 141 | return value + _source.Body.Substring(chunkStart, _currentIndex - chunkStart - 1); 142 | } 143 | 144 | private string AppendToValueByCode(string value, char code) 145 | { 146 | switch (code) 147 | { 148 | case '"': 149 | value = "\""; 150 | break; 151 | case '/': 152 | value = "/"; 153 | break; 154 | case '\\': 155 | value = "\\"; 156 | break; 157 | case 'b': 158 | value = "\b"; 159 | break; 160 | case 'f': 161 | value = "\f"; 162 | break; 163 | case 'n': 164 | value = "\n"; 165 | break; 166 | case 'r': 167 | value = "\r"; 168 | break; 169 | case 't': 170 | value = "\t"; 171 | break; 172 | case 'u': 173 | value = GetUnicodeChar().ToString(); 174 | break; 175 | default: 176 | throw new GraphQLSyntaxErrorException($"Invalid character escape sequence: \\{code}.", _source, 177 | _currentIndex); 178 | } 179 | 180 | return value; 181 | } 182 | 183 | private int CharToHex(char code) => Convert.ToByte(code.ToString(), 16); 184 | 185 | private void CheckForInvalidCharacters(char code) 186 | { 187 | if (code < 0x0020 && code != 0x0009) 188 | { 189 | throw new GraphQLSyntaxErrorException( 190 | $"Invalid character within String: \\u{((int) code).ToString("D4")}.", _source, _currentIndex); 191 | } 192 | } 193 | 194 | private Token CheckForPunctuationTokens(char code) 195 | { 196 | switch (code) 197 | { 198 | case '!': 199 | return CreatePunctuationToken(TokenKind.BANG, 1); 200 | case '$': 201 | return CreatePunctuationToken(TokenKind.DOLLAR, 1); 202 | case '(': 203 | return CreatePunctuationToken(TokenKind.PAREN_L, 1); 204 | case ')': 205 | return CreatePunctuationToken(TokenKind.PAREN_R, 1); 206 | case '.': 207 | return CheckForSpreadOperator(); 208 | case ':': 209 | return CreatePunctuationToken(TokenKind.COLON, 1); 210 | case '=': 211 | return CreatePunctuationToken(TokenKind.EQUALS, 1); 212 | case '@': 213 | return CreatePunctuationToken(TokenKind.AT, 1); 214 | case '[': 215 | return CreatePunctuationToken(TokenKind.BRACKET_L, 1); 216 | case ']': 217 | return CreatePunctuationToken(TokenKind.BRACKET_R, 1); 218 | case '{': 219 | return CreatePunctuationToken(TokenKind.BRACE_L, 1); 220 | case '|': 221 | return CreatePunctuationToken(TokenKind.PIPE, 1); 222 | case '}': 223 | return CreatePunctuationToken(TokenKind.BRACE_R, 1); 224 | default: 225 | return CreateUnknownToken(); 226 | } 227 | } 228 | 229 | private Token CheckForSpreadOperator() 230 | { 231 | int char1 = _source.Body.Length > _currentIndex + 1 ? _source.Body[_currentIndex + 1] : 0; 232 | int char2 = _source.Body.Length > _currentIndex + 2 ? _source.Body[_currentIndex + 2] : 0; 233 | 234 | return char1 == '.' && char2 == '.' 235 | ? CreatePunctuationToken(TokenKind.SPREAD, 3) 236 | : CreateUnknownToken(); 237 | } 238 | 239 | private void CheckStringTermination(char code) 240 | { 241 | if (code != '"') 242 | { 243 | throw new GraphQLSyntaxErrorException("Unterminated string.", _source, _currentIndex); 244 | } 245 | } 246 | 247 | private Token CreateUnknownToken() 248 | { 249 | return new Token 250 | ( 251 | TokenKind.UNKNOWN, 252 | null, 253 | _currentIndex, 254 | _currentIndex 255 | ); 256 | } 257 | 258 | private Token CreateEOFToken() 259 | { 260 | return new Token 261 | ( 262 | TokenKind.EOF, 263 | null, 264 | _currentIndex, 265 | _currentIndex 266 | ); 267 | } 268 | 269 | private Token CreateFloatToken(int start) 270 | { 271 | return new Token 272 | ( 273 | TokenKind.FLOAT, 274 | _source.Body.Substring(start, _currentIndex - start), 275 | start, 276 | _currentIndex 277 | ); 278 | } 279 | 280 | private Token CreateIntToken(int start) 281 | { 282 | return new Token 283 | ( 284 | TokenKind.INT, 285 | _cache.GetInt(_source.Body, start, _currentIndex), 286 | start, 287 | _currentIndex 288 | ); 289 | } 290 | 291 | private Token CreateNameToken(int start) 292 | { 293 | return new Token 294 | ( 295 | TokenKind.NAME, 296 | _cache.GetName(_source.Body, start, _currentIndex), 297 | start, 298 | _currentIndex 299 | ); 300 | } 301 | 302 | private Token CreatePunctuationToken(TokenKind kind, int offset) 303 | { 304 | return new Token 305 | ( 306 | kind, 307 | null, 308 | _currentIndex, 309 | _currentIndex + offset 310 | ); 311 | } 312 | 313 | private char GetCode() 314 | { 315 | return IsNotAtTheEndOfQuery() 316 | ? _source.Body[_currentIndex] 317 | : (char) 0; 318 | } 319 | 320 | private int GetPositionAfterWhitespace(string body, int start) 321 | { 322 | int position = start; 323 | 324 | while (position < body.Length) 325 | { 326 | char code = body[position]; 327 | switch (code) 328 | { 329 | case '\xFEFF': // BOM 330 | case '\t': // tab 331 | case ' ': // space 332 | case '\n': // new line 333 | case '\r': // carriage return 334 | case ',': // Comma 335 | ++position; 336 | break; 337 | 338 | // case '#': 339 | // position = WaitForEndOfComment(body, position, code); 340 | // break; 341 | 342 | default: 343 | return position; 344 | } 345 | } 346 | 347 | return position; 348 | } 349 | 350 | private char GetUnicodeChar() 351 | { 352 | if (_currentIndex + 5 > _source.Body.Length) 353 | { 354 | string truncatedExpression = _source.Body.Substring(_currentIndex); 355 | throw new GraphQLSyntaxErrorException( 356 | $"Invalid character escape sequence at EOF: \\{truncatedExpression}.", _source, _currentIndex); 357 | } 358 | 359 | string expression = _source.Body.Substring(_currentIndex, 5); 360 | 361 | if (!OnlyHexInString(expression.Substring(1))) 362 | { 363 | throw new GraphQLSyntaxErrorException($"Invalid character escape sequence: \\{expression}.", _source, 364 | _currentIndex); 365 | } 366 | 367 | return (char) ( 368 | CharToHex(NextCode()) << 12 | 369 | CharToHex(NextCode()) << 8 | 370 | CharToHex(NextCode()) << 4 | 371 | CharToHex(NextCode())); 372 | } 373 | 374 | private string IfUnicodeGetString() 375 | { 376 | return _source.Body.Length > _currentIndex + 5 && 377 | OnlyHexInString(_source.Body.Substring(_currentIndex + 2, 4)) 378 | ? _source.Body.Substring(_currentIndex, 6) 379 | : null; 380 | } 381 | 382 | private bool IsNotAtTheEndOfQuery() => _currentIndex < _source.Body.Length; 383 | 384 | private char NextCode() 385 | { 386 | _currentIndex++; 387 | return IsNotAtTheEndOfQuery() 388 | ? _source.Body[_currentIndex] 389 | : (char) 0; 390 | } 391 | 392 | private char ProcessCharacter(ref string value, ref int chunkStart) 393 | { 394 | char code = GetCode(); 395 | ++_currentIndex; 396 | 397 | if (code == '\\') 398 | { 399 | value = AppendToValueByCode(AppendCharactersFromLastChunk(value, chunkStart), GetCode()); 400 | 401 | ++_currentIndex; 402 | chunkStart = _currentIndex; 403 | } 404 | 405 | return GetCode(); 406 | } 407 | 408 | private string ProcessStringChunks() 409 | { 410 | int chunkStart = ++_currentIndex; 411 | char code = GetCode(); 412 | string value = string.Empty; 413 | 414 | while (IsNotAtTheEndOfQuery() && code != 0x000A && code != 0x000D && code != '"') 415 | { 416 | CheckForInvalidCharacters(code); 417 | code = ProcessCharacter(ref value, ref chunkStart); 418 | } 419 | 420 | CheckStringTermination(code); 421 | value += _source.Body.Substring(chunkStart, _currentIndex - chunkStart); 422 | return value; 423 | } 424 | 425 | private int ReadDigits(ISource source, int start, char firstCode) 426 | { 427 | string body = source.Body; 428 | int position = start; 429 | char code = firstCode; 430 | 431 | if (!char.IsNumber(code)) 432 | { 433 | throw new GraphQLSyntaxErrorException( 434 | $"Invalid number, expected digit but got: {ResolveCharName(code)}", source, _currentIndex); 435 | } 436 | 437 | do 438 | { 439 | code = ++position < body.Length 440 | ? body[position] 441 | : (char) 0; 442 | } while (char.IsNumber(code)); 443 | 444 | return position; 445 | } 446 | 447 | private char ReadDigitsFromOwnSource(char code) 448 | { 449 | _currentIndex = ReadDigits(_source, _currentIndex, code); 450 | return GetCode(); 451 | } 452 | 453 | private Token ReadName() 454 | { 455 | int start = _currentIndex; 456 | char code; 457 | 458 | do 459 | { 460 | _currentIndex++; 461 | code = GetCode(); 462 | } while (IsNotAtTheEndOfQuery() && IsValidNameCharacter(code)); 463 | 464 | return CreateNameToken(start); 465 | } 466 | 467 | private string ResolveCharName(char code, string unicodeString = null) 468 | { 469 | if (code == '\0') 470 | return ""; 471 | 472 | return string.IsNullOrWhiteSpace(unicodeString) 473 | ? $"\"{code}\"" 474 | : $"\"{unicodeString}\""; 475 | } 476 | 477 | private void ValidateCharacterCode(int code) 478 | { 479 | if (code < 0x0020 && code != 0x0009 && code != 0x000A && code != 0x000D) 480 | { 481 | throw new GraphQLSyntaxErrorException( 482 | $"Invalid character \"\\u{code.ToString("D4")}\".", _source, _currentIndex); 483 | } 484 | } 485 | 486 | private int WaitForEndOfComment(string body, int position, char code) 487 | { 488 | while (++position < body.Length && (code = body[position]) != 0 && (code > 0x001F || code == 0x0009) && 489 | code != 0x000A && code != 0x000D) { } 490 | 491 | return position; 492 | } 493 | } 494 | } -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/LexerContext.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bf1b9e4ffe0343cd8800c42865c29a6f 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/Location.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | 3 | namespace SimpleGraphQL.GraphQLParser 4 | { 5 | public readonly struct Location 6 | { 7 | private static readonly Regex _lineRegex = new Regex("\r\n|[\n\r]", RegexOptions.ECMAScript); 8 | 9 | public Location(ISource source, int position) 10 | { 11 | Line = 1; 12 | Column = position + 1; 13 | 14 | var matches = _lineRegex.Matches(source.Body); 15 | foreach (Match match in matches) 16 | { 17 | if (match.Index >= position) 18 | break; 19 | 20 | Line++; 21 | Column = position + 1 - (match.Index + matches[0].Length); 22 | } 23 | } 24 | 25 | public int Column { get; } 26 | 27 | public int Line { get; } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/Location.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b2943772854f47e39863af1b7d8d9478 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/Parser.cs: -------------------------------------------------------------------------------- 1 | using SimpleGraphQL.GraphQLParser.AST; 2 | 3 | namespace SimpleGraphQL.GraphQLParser 4 | { 5 | public class Parser 6 | { 7 | private readonly ILexer _lexer; 8 | 9 | public Parser(ILexer lexer) 10 | { 11 | _lexer = lexer; 12 | } 13 | 14 | public GraphQLDocument Parse(ISource source) 15 | { 16 | using (var context = new ParserContext(source, _lexer)) 17 | { 18 | return context.Parse(); 19 | } 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/Parser.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a4d9392c0ba04b7ea3866db9582c1677 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/ParserContext.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: dc9a417e991646e48600330e79af65f5 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/Source.cs: -------------------------------------------------------------------------------- 1 | namespace SimpleGraphQL.GraphQLParser 2 | { 3 | public class Source : ISource 4 | { 5 | public Source(string body) : this(body, "GraphQL") 6 | { 7 | } 8 | 9 | public Source(string body, string name) 10 | { 11 | Name = name; 12 | Body = MonetizeLineBreaks(body); 13 | } 14 | 15 | public string Body { get; set; } 16 | 17 | public string Name { get; set; } 18 | 19 | private static string MonetizeLineBreaks(string input) 20 | { 21 | return (input ?? string.Empty) 22 | .Replace("\r\n", "\n") 23 | .Replace("\r", "\n"); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/Source.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f97281071fff445aabe9cb6d1f0acef9 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/Token.cs: -------------------------------------------------------------------------------- 1 | namespace SimpleGraphQL.GraphQLParser 2 | { 3 | public readonly struct Token 4 | { 5 | public Token(TokenKind kind, string value, int start, int end) 6 | { 7 | Kind = kind; 8 | Value = value; 9 | Start = start; 10 | End = end; 11 | } 12 | 13 | public int End { get; } 14 | 15 | public TokenKind Kind { get; } 16 | 17 | public int Start { get; } 18 | 19 | public string Value { get; } 20 | 21 | public static string GetTokenKindDescription(TokenKind kind) 22 | { 23 | switch (kind) 24 | { 25 | case TokenKind.EOF: 26 | return "EOF"; 27 | case TokenKind.BANG: 28 | return "!"; 29 | case TokenKind.DOLLAR: 30 | return "$"; 31 | case TokenKind.PAREN_L: 32 | return "("; 33 | case TokenKind.PAREN_R: 34 | return ")"; 35 | case TokenKind.SPREAD: 36 | return "..."; 37 | case TokenKind.COLON: 38 | return ":"; 39 | case TokenKind.EQUALS: 40 | return "="; 41 | case TokenKind.AT: 42 | return "@"; 43 | case TokenKind.BRACKET_L: 44 | return "["; 45 | case TokenKind.BRACKET_R: 46 | return "]"; 47 | case TokenKind.BRACE_L: 48 | return "{"; 49 | case TokenKind.PIPE: 50 | return "|"; 51 | case TokenKind.BRACE_R: 52 | return "}"; 53 | case TokenKind.NAME: 54 | return "Name"; 55 | case TokenKind.INT: 56 | return "Int"; 57 | case TokenKind.FLOAT: 58 | return "Float"; 59 | case TokenKind.STRING: 60 | return "String"; 61 | case TokenKind.COMMENT: 62 | return "#"; 63 | default: 64 | return string.Empty; 65 | } 66 | } 67 | 68 | public override string ToString() 69 | { 70 | return Value != null 71 | ? $"{GetTokenKindDescription(Kind)} \"{Value}\"" 72 | : GetTokenKindDescription(Kind); 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/Token.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1b269697aed44d58b461dc9a9c2043fa 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/TokenKind.cs: -------------------------------------------------------------------------------- 1 | namespace SimpleGraphQL.GraphQLParser 2 | { 3 | public enum TokenKind 4 | { 5 | EOF = 1, 6 | BANG = 2, 7 | DOLLAR = 3, 8 | PAREN_L = 4, 9 | PAREN_R = 5, 10 | SPREAD = 6, 11 | COLON = 7, 12 | EQUALS = 8, 13 | AT = 9, 14 | BRACKET_L = 10, 15 | BRACKET_R = 11, 16 | BRACE_L = 12, 17 | PIPE = 13, 18 | BRACE_R = 14, 19 | NAME = 15, 20 | INT = 16, 21 | FLOAT = 17, 22 | STRING = 18, 23 | COMMENT = 19, 24 | UNKNOWN = 20 25 | } 26 | } -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/GraphQLParser/TokenKind.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d53f0a59ea6b4767b2beba2441f6e8f8 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/Utils.cs: -------------------------------------------------------------------------------- 1 | namespace SimpleGraphQL 2 | { 3 | public static class Utils 4 | { 5 | public static bool IsNullOrEmpty(this string str) 6 | { 7 | return string.IsNullOrEmpty(str); 8 | } 9 | 10 | /// 11 | /// Checks if a string is null, empty, or contains whitespace. 12 | /// 13 | /// 14 | /// 15 | public static bool IsNullOrWhitespace(this string str) 16 | { 17 | if (!string.IsNullOrEmpty(str)) 18 | { 19 | foreach (char c in str) 20 | { 21 | if (!char.IsWhiteSpace(c)) 22 | return false; 23 | } 24 | } 25 | 26 | return true; 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /Plugins/SimpleGraphQL/Utils.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 064ef97e220b49e8b295d0bbe031115a 3 | timeCreated: 1589081431 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ⚠️ NOTICE: This project is no longer being maintained. 2 | Sincerest apologies, but I no longer have the time to maintain this fork. It may have bugs. 3 | Feel free to fork, however no pull request or bug report will be answered. 4 | 5 | If you would like to take over this project, feel free to reach out! 6 | 7 | # SimpleGraphQL For Unity 8 | 9 | SimpleGraphQL is just that -- a simple GraphQL client that is mostly code based and works with Unity. 10 | 11 | ## About 12 | 13 | This package attempts to provide a simple API that is able to interact with a GraphQL server. Nothing more, nothing 14 | less. No complicated setup. 15 | 16 | Also, the world could use some more Unity-friendly GraphQL libraries. 17 | 18 | That being said, this is intended to be a primarily code based package, so keep that in mind if you decide to use this. 19 | 20 | ## What It Does and Doesn't 21 | 22 | ### Does 23 | 24 | - Supports Queries, mutations, and subscriptions 25 | - Checking for error codes 26 | - Reads .graphql files within your project 27 | - Supports multiple queries per file (with operation selectors) 28 | - Supports custom headers 29 | - Async/Await & Coroutine w/ Callback 30 | 31 | ### Doesn't 32 | 33 | - Introspection (you are responsible for writing valid .graphql files) 34 | - There is very basic error checking, but beyond that you need to ensure that you are writing something compatible 35 | with your server (GraphiQL works great) 36 | 37 | # Requirements 38 | 39 | | Requirements | 40 | | ------------------ | 41 | | .NET 4.6 or higher | 42 | | I guess that's it | 43 | 44 | # Supported Platforms 45 | 46 | | Platforms | Queries & Mutations | Subscriptions | 47 | | --------- | ------------------- | ------------- | 48 | | Mono | ✔ | ✔ | 49 | | IL2CPP | ✔ | ✔ | 50 | | WebGL | ✔ | ❌ | 51 | 52 | This should work with all platforms (Mono/IL2CPP) except for subscriptions on WebGL. 53 | It makes use of UnityWebRequest where possible, but C# WebSockets are the main issue, so subscriptions will not properly 54 | work. If you do not need 55 | subscriptions, WebGL will work just fine. Work may be added to support WebGL in the future, but for now, there is no 56 | support. 57 | 58 | If you are having trouble with a platform, please open an issue. 59 | 60 | ## Unity Version 61 | 62 | We've tested this on Unity 2019.4 and higher (up to 2021.1). While it may work on older Unity versions, there is no 63 | strong guarantee because there have been many breaking API changes over the past couple of years, but also that some of 64 | the features being used here may have not been backported. Your mileage may vary. 65 | 66 | # Installation 67 | 68 | You can add this library to your project using the Package Manager. 69 | 70 | Go to the package manager and click on "Add package from git URL". 71 | From there, add this URL: 72 | `https://github.com/ngoninteractive/SimpleGraphQL-For-Unity.git` 73 | 74 | ![show_tutorial_image](https://i.imgur.com/bZtYyfw.gif) 75 | 76 | That's it. 77 | 78 | # Quick Start 79 | 80 | Simplest usage: 81 | 82 | ```c# 83 | var client = new GraphQLClient("https://countries.trevorblades.com/"); 84 | var request = new Request 85 | { 86 | Query = "query ContinentNameByCode($code: ID!) { continent(code: $code) { name } }", 87 | Variables = new 88 | { 89 | code = "EU" 90 | } 91 | }; 92 | var responseType = new { continent = new { name = "" } }; 93 | var response = await client.Send(() => responseType, request); 94 | Debug.Log(response.Data.continent.name); 95 | ``` 96 | 97 | SimpleGraphQL also lets you store queries in .graphql files that you must write yourself. It is up to you to make sure 98 | they are valid. Many IDEs support this function natively or through plugins. 99 | 100 | ## Configuration 101 | 102 | ### Import: Put your .graphql files somewhere in your Assets folder. 103 | 104 | ### Create a Config 105 | 106 | 1. Right Click -> Create -> SimpleGraphQL -> GraphQL Config 107 | 2. Fill in values 108 | ![img](https://i.imgur.com/rs8EIEM.png) 109 | 110 | > This inspector looks this way because of Odin Inspector. Go check it out, it is a massive time saver. 111 | 112 | ### Reference GraphQL Config 113 | 114 | ```cs 115 | public GraphQLConfig Config; 116 | ``` 117 | 118 | ### Queries & Mutations 119 | 120 | ```cs 121 | public async void QueryOrMutation() 122 | { 123 | var graphQL = new GraphQLClient(Config); 124 | 125 | // You can search by file name, operation name, or operation type 126 | // or... mix and match between all three 127 | Query query = graphQL.FindQuery("FileName", "OperationName", OperationType.Query); 128 | 129 | string results = await graphQL.Send( 130 | query.ToRequest(new Dictionary 131 | { 132 | {"variable", "value"} 133 | }), 134 | null, 135 | null, 136 | "authToken", 137 | "Bearer" 138 | ); 139 | 140 | Debug.Log(results); 141 | } 142 | ``` 143 | 144 | > NOTE: The code above is just an example, not all parameters are needed. Be sure to look at the optional parameters. 145 | 146 | ### Subscriptions 147 | 148 | ```cs 149 | public async void Subscribe() 150 | { 151 | var graphQL = new GraphQLClient(Config); 152 | Query query = graphQL.FindQuery("SubscribeFile"); 153 | 154 | graphQL.RegisterListener(OnSubscriptionUpdated); 155 | 156 | bool success = await graphQL.Subscribe( 157 | query.ToRequest(new Dictionary 158 | { 159 | {"variable", "value"} 160 | }), 161 | null, 162 | "authToken", 163 | "Bearer" 164 | ); 165 | 166 | Debug.Log(success ? "Subscribed!" : "Subscribe failed!"); 167 | } 168 | 169 | public async void Unsubscribe() 170 | { 171 | var graphQL = new GraphQLClient(Config); 172 | Query query = graphQL.FindQuery("SubscribeScoresForLevel"); 173 | 174 | await graphQL.Unsubscribe(query.ToRequest()); 175 | graphQL.UnregisterListener(OnSubscriptionUpdated); 176 | Debug.Log("Unsubscribed!"); 177 | } 178 | 179 | public void OnSubscriptionUpdated(string payload) 180 | { 181 | Debug.Log("Subscription updated: " + payload); 182 | } 183 | ``` 184 | 185 | ### Coroutines 186 | 187 | SimpleGraphQL includes a custom yield instruction for when you want to use coroutines. 188 | 189 | ```cs 190 | /// 191 | /// Create a new WaitForSend Yield Instruction. 192 | /// 193 | /// The graphQL send function. 194 | /// The callback that will be invoked after the task is complete. 195 | public WaitForSend(Func> sendFunc, Action onComplete) 196 | ``` 197 | 198 | ```cs 199 | private void Start() 200 | { 201 | StartCoroutine(_CallQueryCoroutine()); 202 | } 203 | 204 | public IEnumerator _CallQueryCoroutine() 205 | { 206 | yield return new WaitForSend( 207 | graphQL.Send( 208 | request 209 | ), 210 | OnComplete 211 | ); 212 | } 213 | 214 | public void OnComplete(string result) 215 | { 216 | Debug.Log("GraphQL Result: " + result); 217 | } 218 | ``` 219 | 220 | # Authentication and Headers 221 | 222 | > Depending on your authentication method, it is up to you to ensure that your authentication data and headers are set 223 | > correctly. 224 | 225 | ### Custom headers and auth tokens are natively supported in SimpleGraphQL. They can be passed in as parameters when calling `Subscribe` or `Send`. 226 | 227 | # Example Valid .graphql Files 228 | 229 | ### GetScoreById.graphql 230 | 231 | ```graphql 232 | # fully defined query 233 | query GetScoreById($user_id: String!, $level: String!) { 234 | leaderboards_by_pk(level: $level, user_id: $user_id) { 235 | user_id 236 | level 237 | score 238 | metadata 239 | } 240 | } 241 | ``` 242 | 243 | ### GetScoresForLevel.graphql 244 | 245 | ```graphql 246 | # anonymous query 247 | query ($level: String!) { 248 | leaderboards(where: {level: {_eq: $level}}) { 249 | user_id 250 | level 251 | score 252 | metadata 253 | } 254 | } 255 | ``` 256 | 257 | ### MoreScoreStuff.graphql 258 | 259 | ```graphql 260 | # you can have multiple queries in one file, and long as they are uniquely named 261 | 262 | mutation UpsertScore($user_id: String!, $level: String!, $score: bigint! $metadata: jsonb!) { 263 | insert_leaderboards_one(object: {user_id: $user_id, level: $level, score: $score, metadata: $metadata}, on_conflict: {constraint: leaderboards_pkey, update_columns: score, where: {score: {_lt: $score}}}) { 264 | user_id 265 | score 266 | } 267 | } 268 | 269 | query ListLevelScores($level: String!) { 270 | leaderboards(where: {level: {_eq: $level}}) { 271 | user_id 272 | level 273 | score 274 | metadata 275 | } 276 | } 277 | ``` 278 | 279 | ### Subscriptions.graphql 280 | 281 | ```graphql 282 | subscription OnScoresUpdated($level: String!) { 283 | leaderboards(where: {level: {_eq: $level}}) { 284 | user_id 285 | level 286 | score 287 | metadata 288 | } 289 | } 290 | 291 | subscription OnAnyScoresUpdated { 292 | leaderboards { 293 | user_id 294 | level 295 | score 296 | metadata 297 | } 298 | } 299 | ``` 300 | 301 | > NOTE: We recommend putting graphQL subscriptions in a separate file. Mixing queries, mutations, and subscriptions 302 | > together in one file may lead to odd/undocumented behavior on various servers. 303 | 304 | # Things to Note 305 | 306 | - During testing, we found that Unity's version of .NET occasionally has issues with HttpClient and WebSocket. If you 307 | find that you are having the same issues, please let us know. WebSocket is unavoidable for subscriptions, and Unity 308 | has no alternative like they do with UnityWebRequest. 309 | - WebSockets sometimes take extraordinarily long amounts of time to start up on the first call. This is has probably 310 | been fixed in a recent .NET version (but we don't have those fixes yet.) 311 | 312 | 314 | -------------------------------------------------------------------------------- /README.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b8380bd939002e64392c307e4a22a23d 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Runtime.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: af68861d24601f248ae1fea8245d7687 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/LastAbyss.SimpleGraphQL.Runtime.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "LastAbyss.SimpleGraphQL.Runtime", 3 | "references": [ 4 | "GUID:15e3c116196bd394da80b1072fff8aa8" 5 | ], 6 | "includePlatforms": [], 7 | "excludePlatforms": [], 8 | "allowUnsafeCode": false, 9 | "overrideReferences": false, 10 | "precompiledReferences": [], 11 | "autoReferenced": true, 12 | "defineConstraints": [], 13 | "versionDefines": [], 14 | "noEngineReferences": false 15 | } -------------------------------------------------------------------------------- /Runtime/LastAbyss.SimpleGraphQL.Runtime.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d9c4a3993822f42439e43ee7d2d1f243 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Runtime/SimpleGraphQL.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4e906f956a134245b1c7e3cc65330266 3 | timeCreated: 1589026568 -------------------------------------------------------------------------------- /Runtime/SimpleGraphQL/GraphQLClient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using JetBrains.Annotations; 6 | using Newtonsoft.Json; 7 | using UnityEngine; 8 | 9 | namespace SimpleGraphQL 10 | { 11 | /// 12 | /// This API object is meant to be reused, so keep an instance of it somewhere! 13 | /// Multiple GraphQLClients can be used with different configs based on needs. 14 | /// 15 | [PublicAPI] 16 | public class GraphQLClient 17 | { 18 | public readonly List SearchableQueries; 19 | public readonly Dictionary CustomHeaders; 20 | 21 | public string Endpoint; 22 | public string AuthScheme; 23 | 24 | // track the running subscriptions ids 25 | internal HashSet RunningSubscriptions; 26 | 27 | public GraphQLClient( 28 | string endpoint, 29 | IEnumerable queries = null, 30 | Dictionary headers = null, 31 | string authScheme = null 32 | ) 33 | { 34 | Endpoint = endpoint; 35 | AuthScheme = authScheme; 36 | SearchableQueries = queries?.ToList(); 37 | CustomHeaders = headers; 38 | RunningSubscriptions = new HashSet(); 39 | } 40 | 41 | public GraphQLClient(GraphQLConfig config) 42 | { 43 | Endpoint = config.Endpoint; 44 | SearchableQueries = config.Files.SelectMany(x => x.Queries).ToList(); 45 | CustomHeaders = config.CustomHeaders.ToDictionary(header => header.Key, header => header.Value); 46 | AuthScheme = config.AuthScheme; 47 | RunningSubscriptions = new HashSet(); 48 | } 49 | 50 | /// 51 | /// Send a query! 52 | /// 53 | /// The request you are sending. 54 | /// 55 | /// Any headers you want to pass 56 | /// The authToken 57 | /// The authScheme to be used. 58 | /// 59 | public async Task Send( 60 | Request request, 61 | JsonSerializerSettings serializerSettings = null, 62 | Dictionary headers = null, 63 | string authToken = null, 64 | string authScheme = null 65 | ) 66 | { 67 | if (CustomHeaders != null) 68 | { 69 | if (headers == null) headers = new Dictionary(); 70 | 71 | foreach (KeyValuePair header in CustomHeaders) 72 | { 73 | headers.Add(header.Key, header.Value); 74 | } 75 | } 76 | 77 | if (authScheme == null) 78 | { 79 | authScheme = AuthScheme; 80 | } 81 | 82 | string postQueryAsync = await HttpUtils.PostRequest( 83 | Endpoint, 84 | request, 85 | serializerSettings, 86 | headers, 87 | authToken, 88 | authScheme 89 | ); 90 | 91 | return postQueryAsync; 92 | } 93 | 94 | public async Task> Send( 95 | Request request, 96 | JsonSerializerSettings serializerSettings = null, 97 | Dictionary headers = null, 98 | string authToken = null, 99 | string authScheme = null 100 | ) 101 | { 102 | string json = await Send(request, serializerSettings, headers, authToken, authScheme); 103 | return JsonConvert.DeserializeObject>(json); 104 | } 105 | 106 | public async Task> Send( 107 | Func responseTypeResolver, 108 | Request request, 109 | JsonSerializerSettings serializerSettings = null, 110 | Dictionary headers = null, 111 | string authToken = null, 112 | string authScheme = null) 113 | { 114 | return await Send(request, serializerSettings, headers, authToken, authScheme); 115 | } 116 | 117 | /// 118 | /// Registers a listener for subscriptions. 119 | /// 120 | /// 121 | public void RegisterListener(Action listener) 122 | { 123 | HttpUtils.SubscriptionDataReceived += listener; 124 | } 125 | 126 | public void RegisterListener(string id, Action listener) 127 | { 128 | if (!HttpUtils.SubscriptionDataReceivedPerChannel.ContainsKey(id)) 129 | { 130 | HttpUtils.SubscriptionDataReceivedPerChannel[id] = null; 131 | } 132 | 133 | HttpUtils.SubscriptionDataReceivedPerChannel[id] += listener; 134 | } 135 | 136 | public void RegisterListener(Request request, Action listener) 137 | { 138 | RegisterListener(request.Query.ToMurmur2Hash().ToString(), listener); 139 | } 140 | 141 | /// 142 | /// Unregisters a listener for subscriptions. 143 | /// 144 | /// 145 | public void UnregisterListener(Action listener) 146 | { 147 | HttpUtils.SubscriptionDataReceived -= listener; 148 | } 149 | 150 | public void UnregisterListener(string id, Action listener) 151 | { 152 | if (HttpUtils.SubscriptionDataReceivedPerChannel.ContainsKey(id)) 153 | { 154 | HttpUtils.SubscriptionDataReceivedPerChannel[id] -= listener; 155 | } 156 | } 157 | 158 | public void UnregisterListener(Request request, Action listener) 159 | { 160 | UnregisterListener(request.Query.ToMurmur2Hash().ToString(), listener); 161 | } 162 | 163 | /// 164 | /// Subscribe to a query in GraphQL. 165 | /// 166 | /// The request you are sending. 167 | /// 168 | /// 169 | /// 170 | /// 171 | /// True if successful 172 | public async Task Subscribe( 173 | Request request, 174 | Dictionary headers = null, 175 | string authToken = null, 176 | string authScheme = null, 177 | string protocol = "graphql-ws" 178 | ) 179 | { 180 | return await Subscribe(request.Query.ToMurmur2Hash().ToString(), request, headers, authToken, authScheme, protocol); 181 | } 182 | 183 | /// 184 | /// Subscribe to a query in GraphQL. 185 | /// 186 | /// A custom id to pass. 187 | /// 188 | /// 189 | /// 190 | /// 191 | /// 192 | /// True if successful 193 | public async Task Subscribe( 194 | string id, 195 | Request request, 196 | Dictionary headers = null, 197 | string authToken = null, 198 | string authScheme = null, 199 | string protocol = "graphql-ws" 200 | ) 201 | { 202 | if (CustomHeaders != null) 203 | { 204 | if (headers == null) headers = new Dictionary(); 205 | 206 | foreach (KeyValuePair header in CustomHeaders) 207 | { 208 | headers.Add(header.Key, header.Value); 209 | } 210 | } 211 | 212 | if (authScheme == null) 213 | { 214 | authScheme = AuthScheme; 215 | } 216 | 217 | if (!HttpUtils.IsWebSocketReady()) 218 | { 219 | Debug.Log("websocket not ready: open connection"); 220 | // Prepare the socket before continuing. 221 | await HttpUtils.WebSocketConnect(Endpoint, headers, authToken, authScheme, protocol); 222 | } 223 | 224 | bool success = await HttpUtils.WebSocketSubscribe(id, request); 225 | if (success) 226 | { 227 | RunningSubscriptions.Add(id); 228 | } 229 | else 230 | { 231 | // if no other subscriptions exist, close connection again 232 | if (RunningSubscriptions.Count == 0) 233 | { 234 | Debug.Log("No running subscription remain: close connection"); 235 | await HttpUtils.WebSocketDisconnect(); 236 | } 237 | } 238 | return success; 239 | 240 | } 241 | 242 | 243 | /// 244 | /// Unsubscribe from a request. 245 | /// 246 | /// 247 | public async Task Unsubscribe(Request request) 248 | { 249 | await Unsubscribe(request.Query.ToMurmur2Hash().ToString()); 250 | } 251 | 252 | /// 253 | /// Unsubscribe from an id. 254 | /// 255 | /// 256 | public async Task Unsubscribe(string id) 257 | { 258 | if (!HttpUtils.IsWebSocketReady()) 259 | { 260 | // Socket is already apparently closed, so this wouldn't work anyways. 261 | return; 262 | } 263 | 264 | // when unsubscribing an unexisting id (or already unsubscribed) 265 | if (!RunningSubscriptions.Contains(id)) 266 | { 267 | Debug.LogError("Attempted to unsubscribe to a query without subscribing first!"); 268 | return; 269 | } 270 | 271 | // TODO: what if this fails? 272 | await HttpUtils.WebSocketUnsubscribe(id); 273 | 274 | RunningSubscriptions.Remove(id); 275 | 276 | // if no active subscriptions remain, stop the connection 277 | // this will also stop the update loop 278 | if (RunningSubscriptions.Count == 0) 279 | { 280 | Debug.Log("No running subscription remain: close connection"); 281 | await HttpUtils.WebSocketDisconnect(); 282 | Debug.Log("connection closed"); 283 | } 284 | } 285 | 286 | /// 287 | /// Finds the first query located in a file. 288 | /// 289 | /// 290 | /// 291 | public Query FindQuery(string fileName) 292 | { 293 | return SearchableQueries?.FirstOrDefault(x => x.FileName == fileName); 294 | } 295 | 296 | /// 297 | /// Finds the first query located in a file. 298 | /// 299 | /// 300 | /// 301 | public Query FindQueryByOperation(string operationName) 302 | { 303 | return SearchableQueries?.FirstOrDefault(x => x.OperationName == operationName); 304 | } 305 | 306 | /// 307 | /// Finds a query by fileName and operationName. 308 | /// 309 | /// 310 | /// 311 | /// 312 | public Query FindQuery(string fileName, string operationName) 313 | { 314 | return SearchableQueries?.FirstOrDefault(x => x.FileName == fileName && x.OperationName == operationName); 315 | } 316 | 317 | /// 318 | /// Finds a query by operationName and operationType. 319 | /// 320 | /// 321 | /// 322 | /// 323 | public Query FindQuery(string operationName, OperationType operationType) 324 | { 325 | return SearchableQueries?.FirstOrDefault(x => 326 | x.OperationName == operationName && 327 | x.OperationType == operationType 328 | ); 329 | } 330 | 331 | /// 332 | /// Finds a query by fileName, operationName, and operationType. 333 | /// 334 | /// 335 | /// 336 | /// 337 | /// 338 | public Query FindQuery(string fileName, string operationName, OperationType operationType) 339 | { 340 | return SearchableQueries?.FirstOrDefault( 341 | x => x.FileName == fileName && 342 | x.OperationName == operationName && 343 | x.OperationType == operationType 344 | ); 345 | } 346 | 347 | /// 348 | /// Finds all queries with the given operation name. 349 | /// You may need to do additional filtering to get the query you want since they will all have the same operation name. 350 | /// 351 | /// 352 | /// 353 | public List FindQueriesByOperation(string operation) 354 | { 355 | return SearchableQueries?.FindAll(x => x.OperationName == operation); 356 | } 357 | } 358 | } -------------------------------------------------------------------------------- /Runtime/SimpleGraphQL/GraphQLClient.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c1592950d8395c34b8e8468f2e887b50 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/SimpleGraphQL/GraphQLConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace SimpleGraphQL 6 | { 7 | [CreateAssetMenu(menuName = "SimpleGraphQL/GraphQL Config")] 8 | public class GraphQLConfig : ScriptableObject 9 | { 10 | /// 11 | /// This is the endpoint that we will be talking to. 12 | /// 13 | [Header("GraphQL Endpoint")] 14 | public string Endpoint; 15 | 16 | /// 17 | /// This is all the GraphQL query files that are available to SimpleGraphQL. 18 | /// 19 | /// 20 | [Header(".graphql Files")] 21 | public List Files; 22 | 23 | /// 24 | /// Set the auth scheme to be used here if you need authentication. 25 | /// You can also use CustomHeaders to pass in authentication if needed, but this is inherently less secure. 26 | /// 27 | [Header("Authorization")] 28 | public string AuthScheme = "Bearer"; 29 | 30 | /// 31 | /// You can use this to include Headers on every query. This is useful if you are debugging or need 32 | /// a special access code alongside authentication. 33 | /// 34 | [Header("Custom Headers")] 35 | public List
CustomHeaders; 36 | } 37 | 38 | [Serializable] 39 | public class Header 40 | { 41 | public string Key; 42 | public string Value; 43 | } 44 | } -------------------------------------------------------------------------------- /Runtime/SimpleGraphQL/GraphQLConfig.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d7544f1907c44b1394f70c35d12caec5 3 | timeCreated: 1589033997 -------------------------------------------------------------------------------- /Runtime/SimpleGraphQL/GraphQLFile.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnityEngine; 3 | 4 | namespace SimpleGraphQL 5 | { 6 | public class GraphQLFile : ScriptableObject 7 | { 8 | public List Queries = new List(); 9 | } 10 | } -------------------------------------------------------------------------------- /Runtime/SimpleGraphQL/GraphQLFile.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ad07d3eb3e874add979c9deb15f15e1f 3 | timeCreated: 1589088814 -------------------------------------------------------------------------------- /Runtime/SimpleGraphQL/HttpUtils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Net.WebSockets; 4 | using System.Text; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | using JetBrains.Annotations; 8 | using Newtonsoft.Json; 9 | using Newtonsoft.Json.Linq; 10 | using UnityEngine; 11 | using UnityEngine.Networking; 12 | 13 | namespace SimpleGraphQL 14 | { 15 | [PublicAPI] 16 | public static class HttpUtils 17 | { 18 | private static ClientWebSocket _webSocket; 19 | 20 | /// 21 | /// Called when the websocket receives subscription data. 22 | /// 23 | public static event Action SubscriptionDataReceived; 24 | 25 | public static Dictionary> SubscriptionDataReceivedPerChannel; 26 | 27 | [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] 28 | public static void PreInit() 29 | { 30 | _webSocket?.Dispose(); 31 | SubscriptionDataReceived = null; 32 | SubscriptionDataReceivedPerChannel = new Dictionary>(); 33 | } 34 | 35 | /// 36 | /// For when the WebSocket needs to be disposed and reset. 37 | /// 38 | public static void Dispose() 39 | { 40 | _webSocket?.Dispose(); 41 | _webSocket = null; 42 | } 43 | 44 | /// 45 | /// POST a query to the given endpoint url. 46 | /// 47 | /// The endpoint url. 48 | /// The GraphQL request 49 | /// The authentication scheme to be used. 50 | /// The actual auth token. 51 | /// 52 | /// Any headers that should be passed in 53 | /// 54 | public static async Task PostRequest( 55 | string url, 56 | Request request, 57 | JsonSerializerSettings serializerSettings = null, 58 | Dictionary headers = null, 59 | string authToken = null, 60 | string authScheme = null 61 | ) 62 | { 63 | var uri = new Uri(url); 64 | 65 | byte[] payload = request.ToBytes(serializerSettings); 66 | 67 | using (var webRequest = new UnityWebRequest(uri, "POST") 68 | { 69 | uploadHandler = new UploadHandlerRaw(payload), 70 | downloadHandler = new DownloadHandlerBuffer(), 71 | disposeCertificateHandlerOnDispose = true, 72 | disposeDownloadHandlerOnDispose = true, 73 | disposeUploadHandlerOnDispose = true 74 | }) 75 | { 76 | if (authToken != null) 77 | webRequest.SetRequestHeader("Authorization", $"{authScheme} {authToken}"); 78 | 79 | webRequest.SetRequestHeader("Content-Type", "application/json"); 80 | 81 | if (headers != null) 82 | { 83 | foreach (KeyValuePair header in headers) 84 | { 85 | webRequest.SetRequestHeader(header.Key, header.Value); 86 | } 87 | } 88 | 89 | try 90 | { 91 | webRequest.SendWebRequest(); 92 | 93 | while (!webRequest.isDone) 94 | { 95 | await Task.Yield(); 96 | } 97 | } 98 | catch (Exception e) 99 | { 100 | Debug.LogError("[SimpleGraphQL] " + e); 101 | throw new UnityWebRequestException(webRequest); 102 | } 103 | 104 | #if UNITY_2020_2_OR_NEWER 105 | if (webRequest.result != UnityWebRequest.Result.Success) 106 | { 107 | throw new UnityWebRequestException(webRequest); 108 | } 109 | #elif UNITY_2019_4 110 | if (webRequest.isNetworkError || webRequest.isHttpError) 111 | { 112 | throw new UnityWebRequestException(webRequest); 113 | } 114 | #endif 115 | 116 | return webRequest.downloadHandler.text; 117 | } 118 | } 119 | 120 | public static bool IsWebSocketReady() => 121 | _webSocket?.State == WebSocketState.Connecting || _webSocket?.State == WebSocketState.Open; 122 | 123 | /// 124 | /// Connect to the GraphQL server. Call is necessary in order to send subscription queries via WebSocket. 125 | /// 126 | /// 127 | /// 128 | /// 129 | /// 130 | /// 131 | /// 132 | public static async Task WebSocketConnect( 133 | string url, 134 | Dictionary headers = null, 135 | string authToken = null, 136 | string authScheme = null, 137 | string protocol = "graphql-ws" 138 | ) 139 | { 140 | url = url.Replace("http", "ws"); 141 | 142 | var uri = new Uri(url); 143 | _webSocket = new ClientWebSocket(); 144 | _webSocket.Options.AddSubProtocol(protocol); 145 | 146 | var payload = new Dictionary(); 147 | 148 | if (protocol == "graphql-transport-ws") 149 | { 150 | payload["content-type"] = "application/json"; 151 | } 152 | else 153 | { 154 | _webSocket.Options.SetRequestHeader("Content-Type", "application/json"); 155 | } 156 | 157 | if (authToken != null) 158 | { 159 | if (protocol == "graphql-transport-ws") 160 | { 161 | // set Authorization as payload 162 | payload["Authorization"] = $"{authScheme} {authToken}"; 163 | } 164 | else 165 | { 166 | _webSocket.Options.SetRequestHeader("Authorization", $"{authScheme} {authToken}"); 167 | } 168 | } 169 | 170 | 171 | if (headers != null) 172 | { 173 | foreach (KeyValuePair header in headers) 174 | { 175 | _webSocket.Options.SetRequestHeader(header.Key, header.Value); 176 | } 177 | } 178 | 179 | try 180 | { 181 | Debug.Log("Websocket is connecting"); 182 | await _webSocket.ConnectAsync(uri, CancellationToken.None); 183 | 184 | string json = JsonConvert.SerializeObject( 185 | new 186 | { 187 | type = "connection_init", 188 | payload = payload 189 | }, 190 | Formatting.None, 191 | new JsonSerializerSettings 192 | { 193 | NullValueHandling = NullValueHandling.Ignore 194 | } 195 | ); 196 | 197 | Debug.Log("Websocket is starting"); 198 | // Initialize the socket at the server side 199 | await _webSocket.SendAsync( 200 | new ArraySegment(Encoding.UTF8.GetBytes(json)), 201 | WebSocketMessageType.Text, 202 | true, 203 | CancellationToken.None 204 | ); 205 | 206 | Debug.Log("Websocket is updating"); 207 | // Start listening to the websocket for data. 208 | WebSocketUpdate(); 209 | } 210 | catch (Exception e) 211 | { 212 | Debug.LogError(e.Message); 213 | } 214 | } 215 | 216 | /// 217 | /// Disconnect the websocket. 218 | /// 219 | /// 220 | public static async Task WebSocketDisconnect() 221 | { 222 | if (_webSocket?.State != WebSocketState.Open) 223 | { 224 | Debug.LogError("Attempted to disconnect from a socket that was not open!"); 225 | return; 226 | } 227 | 228 | await _webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Socket closed.", CancellationToken.None); 229 | Dispose(); 230 | } 231 | 232 | /// 233 | /// Subscribe to a query. 234 | /// 235 | /// Used to identify the subscription. Must be unique per query. 236 | /// The subscription query. 237 | /// true if successful 238 | public static async Task WebSocketSubscribe(string id, Request request) 239 | { 240 | if (!IsWebSocketReady()) 241 | { 242 | Debug.LogError("Attempted to subscribe to a query without connecting to a WebSocket first!"); 243 | return false; 244 | } 245 | 246 | string json = JsonConvert.SerializeObject( 247 | new 248 | { 249 | id, 250 | type = _webSocket.SubProtocol == "graphql-transport-ws" ? "subscribe" : "start", 251 | payload = new 252 | { 253 | query = request.Query, 254 | variables = request.Variables, 255 | operationName = request.OperationName 256 | } 257 | }, 258 | Formatting.None, 259 | new JsonSerializerSettings 260 | { 261 | NullValueHandling = NullValueHandling.Ignore 262 | } 263 | ); 264 | 265 | await _webSocket.SendAsync( 266 | new ArraySegment(Encoding.UTF8.GetBytes(json)), 267 | WebSocketMessageType.Text, 268 | true, 269 | CancellationToken.None 270 | ); 271 | 272 | return true; 273 | } 274 | 275 | /// 276 | /// Unsubscribe from this query. 277 | /// 278 | /// Used to identify the subscription. Must be unique per query. 279 | /// 280 | public static async Task WebSocketUnsubscribe(string id) 281 | { 282 | if (!IsWebSocketReady()) 283 | { 284 | Debug.LogError("Attempted to unsubscribe to a query without connecting to a WebSocket first!"); 285 | return; 286 | } 287 | 288 | string type = _webSocket.SubProtocol == "graphql-transport-ws" ? "complete" : "stop"; 289 | 290 | await _webSocket.SendAsync( 291 | new ArraySegment(Encoding.UTF8.GetBytes($@"{{""type"":""{type}"",""id"":""{id}""}}")), 292 | WebSocketMessageType.Text, 293 | true, 294 | CancellationToken.None 295 | ); 296 | } 297 | 298 | private static async void WebSocketUpdate() 299 | { 300 | while (true) 301 | { 302 | // break the loop as soon as the websocket was closed 303 | if (!IsWebSocketReady()) 304 | { 305 | Debug.Log("websocket was closed, stop the loop"); 306 | break; 307 | } 308 | 309 | ArraySegment buffer = WebSocket.CreateClientBuffer(1024, 1024); 310 | 311 | if (buffer.Array == null) 312 | { 313 | throw new WebSocketException("Buffer array is null!"); 314 | } 315 | 316 | WebSocketReceiveResult wsReceiveResult; 317 | var jsonBuild = new StringBuilder(); 318 | 319 | do 320 | { 321 | wsReceiveResult = await _webSocket.ReceiveAsync(buffer, CancellationToken.None); 322 | 323 | jsonBuild.Append(Encoding.UTF8.GetString(buffer.Array, buffer.Offset, wsReceiveResult.Count)); 324 | } while (!wsReceiveResult.EndOfMessage); 325 | 326 | var jsonResult = jsonBuild.ToString(); 327 | if (jsonResult.IsNullOrEmpty()) return; 328 | 329 | JObject jsonObj; 330 | try 331 | { 332 | jsonObj = JObject.Parse(jsonResult); 333 | } 334 | catch (JsonReaderException e) 335 | { 336 | throw new ApplicationException(e.Message); 337 | } 338 | 339 | var msgType = (string)jsonObj["type"]; 340 | var id = (string)jsonObj["id"]; 341 | switch (msgType) 342 | { 343 | case "connection_error": 344 | { 345 | throw new WebSocketException("Connection error. Error: " + jsonResult); 346 | } 347 | case "connection_ack": 348 | { 349 | Debug.Log($"Websocket connection acknowledged ({id})."); 350 | continue; 351 | } 352 | case "data": 353 | case "next": 354 | { 355 | JToken jToken = jsonObj["payload"]; 356 | 357 | if (jToken != null) 358 | { 359 | SubscriptionDataReceived?.Invoke(jToken.ToString()); 360 | 361 | if (id != null) 362 | { 363 | SubscriptionDataReceivedPerChannel?[id]?.Invoke(jToken.ToString()); 364 | } 365 | } 366 | 367 | continue; 368 | } 369 | case "error": 370 | { 371 | throw new WebSocketException("Handshake error. Error: " + jsonResult); 372 | } 373 | case "complete": 374 | { 375 | Debug.Log("Server sent complete, it's done sending data."); 376 | continue; 377 | } 378 | case "ka": 379 | { 380 | // stayin' alive, stayin' alive 381 | continue; 382 | } 383 | case "subscription_fail": 384 | { 385 | throw new WebSocketException("Subscription failed. Error: " + jsonResult); 386 | } 387 | case "ping": 388 | { 389 | await _webSocket.SendAsync( 390 | new ArraySegment(Encoding.UTF8.GetBytes($@"{{""type"":""pong""}}")), 391 | WebSocketMessageType.Text, 392 | true, 393 | CancellationToken.None 394 | ); 395 | continue; 396 | } 397 | } 398 | 399 | break; 400 | } 401 | } 402 | } 403 | } -------------------------------------------------------------------------------- /Runtime/SimpleGraphQL/HttpUtils.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b1720931a7a94dd6a7826d94b72abd1b 3 | timeCreated: 1589036192 -------------------------------------------------------------------------------- /Runtime/SimpleGraphQL/MurmurHash2.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.Annotations; 2 | 3 | namespace SimpleGraphQL 4 | { 5 | // Author: jitbit 6 | // 7 | // MIT License 8 | // 9 | // Copyright (c) 2017 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining a copy 12 | // of this software and associated documentation files (the "Software"), to deal 13 | // in the Software without restriction, including without limitation the rights 14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | // copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in all 19 | // copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | // SOFTWARE. 28 | 29 | [PublicAPI] 30 | public class MurmurHash2 31 | { 32 | public static uint Hash(string data) 33 | { 34 | return Hash(System.Text.Encoding.UTF8.GetBytes(data)); 35 | } 36 | 37 | private const uint M = 0x5bd1e995; 38 | private const int R = 24; 39 | 40 | public static uint Hash(byte[] data, uint seed = 0xc58f1a7a) 41 | { 42 | int length = data.Length; 43 | 44 | if (length == 0) 45 | return 0; 46 | 47 | uint h = seed ^ (uint) length; 48 | var currentIndex = 0; 49 | 50 | while (length >= 4) 51 | { 52 | var k = (uint) (data[currentIndex++] | data[currentIndex++] << 8 | data[currentIndex++] << 16 | 53 | data[currentIndex++] << 24); 54 | k *= M; 55 | k ^= k >> R; 56 | k *= M; 57 | 58 | h *= M; 59 | h ^= k; 60 | length -= 4; 61 | } 62 | 63 | switch (length) 64 | { 65 | case 3: 66 | h ^= (ushort) (data[currentIndex++] | data[currentIndex++] << 8); 67 | h ^= (uint) (data[currentIndex] << 16); 68 | h *= M; 69 | break; 70 | case 2: 71 | h ^= (ushort) (data[currentIndex++] | data[currentIndex] << 8); 72 | h *= M; 73 | break; 74 | case 1: 75 | h ^= data[currentIndex]; 76 | h *= M; 77 | break; 78 | default: 79 | break; 80 | } 81 | 82 | h ^= h >> 13; 83 | h *= M; 84 | h ^= h >> 15; 85 | 86 | return h; 87 | } 88 | } 89 | 90 | public static class MurmurHash2Extensions 91 | { 92 | public static uint ToMurmur2Hash(this string str) 93 | { 94 | return MurmurHash2.Hash(str); 95 | } 96 | } 97 | } -------------------------------------------------------------------------------- /Runtime/SimpleGraphQL/MurmurHash2.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a46f5e9f36bf30d409648e86aad3d9c9 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/SimpleGraphQL/Query.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using JetBrains.Annotations; 3 | 4 | namespace SimpleGraphQL 5 | { 6 | [PublicAPI] 7 | [Serializable] 8 | public class Query 9 | { 10 | /// 11 | /// The filename that this query is located in. 12 | /// This is mostly used for searching and identification purposes, and is not 13 | /// necessarily needed for dynamically created queries. 14 | /// 15 | [CanBeNull] 16 | public string FileName; 17 | 18 | /// 19 | /// The operation name of this query. 20 | /// It may be null, in which case it should be the only anonymous query in this file. 21 | /// 22 | [CanBeNull] 23 | public string OperationName; 24 | 25 | /// 26 | /// The type of query this is. 27 | /// 28 | public OperationType OperationType; 29 | 30 | /// 31 | /// The actual query itself. 32 | /// 33 | public string Source; 34 | 35 | public override string ToString() 36 | { 37 | return $"{FileName}:{OperationName}:{OperationType}"; 38 | } 39 | } 40 | 41 | [PublicAPI] 42 | public static class QueryExtensions 43 | { 44 | public static Request ToRequest(this Query query, object variables = null) 45 | { 46 | return new Request 47 | { 48 | Query = query.Source, 49 | Variables = variables, 50 | OperationName = query.OperationName, 51 | }; 52 | } 53 | } 54 | 55 | [PublicAPI] 56 | [Serializable] 57 | public enum OperationType 58 | { 59 | Query, 60 | Mutation, 61 | Subscription 62 | } 63 | } -------------------------------------------------------------------------------- /Runtime/SimpleGraphQL/Query.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a6ee071b87154be595058e1a6b1d7e77 3 | timeCreated: 1589172993 -------------------------------------------------------------------------------- /Runtime/SimpleGraphQL/Request.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using JetBrains.Annotations; 4 | using Newtonsoft.Json; 5 | using Newtonsoft.Json.Serialization; 6 | 7 | namespace SimpleGraphQL 8 | { 9 | [Serializable] 10 | [JsonObject(NamingStrategyType = typeof(CamelCaseNamingStrategy))] 11 | public class Request 12 | { 13 | public string Query { get; set; } 14 | 15 | [CanBeNull] 16 | public string OperationName { get; set; } 17 | 18 | public object Variables { get; set; } 19 | 20 | public override string ToString() 21 | { 22 | return $"GraphQL Request:\n{this.ToJson(true)}"; 23 | } 24 | } 25 | 26 | [PublicAPI] 27 | public static class RequestExtensions 28 | { 29 | private static JsonSerializerSettings defaultSerializerSettings = new JsonSerializerSettings 30 | { NullValueHandling = NullValueHandling.Ignore }; 31 | 32 | public static byte[] ToBytes(this Request request, JsonSerializerSettings serializerSettings = null) 33 | { 34 | return Encoding.UTF8.GetBytes(request.ToJson(false, serializerSettings)); 35 | } 36 | 37 | public static string ToJson(this Request request, bool prettyPrint = false, 38 | JsonSerializerSettings serializerSettings = null) 39 | { 40 | if (serializerSettings == null) 41 | { 42 | serializerSettings = defaultSerializerSettings; 43 | } 44 | 45 | return JsonConvert.SerializeObject 46 | (request, 47 | prettyPrint ? Formatting.Indented : Formatting.None, 48 | serializerSettings 49 | ); 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /Runtime/SimpleGraphQL/Request.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e14e44c4ba10492ab46ce11e7db590ba 3 | timeCreated: 1623267576 -------------------------------------------------------------------------------- /Runtime/SimpleGraphQL/Response.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.Serialization; 2 | using JetBrains.Annotations; 3 | using UnityEngine.Scripting; 4 | 5 | namespace SimpleGraphQL 6 | { 7 | [PublicAPI] 8 | [Preserve] 9 | public class Response 10 | { 11 | [DataMember(Name = "data")] 12 | public T Data { get; set; } 13 | 14 | [DataMember(Name = "errors")] 15 | [CanBeNull] 16 | public Error[] Errors { get; set; } 17 | 18 | [Preserve] // Ensures it survives code-stripping 19 | public Response() 20 | { 21 | } 22 | } 23 | 24 | [PublicAPI] 25 | [Preserve] 26 | public class Error 27 | { 28 | [DataMember(Name = "message")] 29 | public string Message { get; set; } 30 | 31 | [DataMember(Name = "locations")] 32 | [CanBeNull] 33 | public Location[] Locations { get; set; } 34 | 35 | [DataMember(Name = "extensions")] 36 | [CanBeNull] 37 | public Extensions Extensions { get; set; } 38 | 39 | [DataMember(Name = "path")] 40 | [CanBeNull] 41 | public object[] Path { get; set; } // Path objects can be either integers or strings 42 | 43 | [Preserve] // Ensures it survives code-stripping 44 | public Error() 45 | { 46 | } 47 | } 48 | 49 | [PublicAPI] 50 | [Preserve] 51 | public class Extensions 52 | { 53 | [DataMember(Name = "code")] 54 | public string Code { get; set; } 55 | 56 | [Preserve] // Ensures it survives code-stripping 57 | public Extensions() 58 | { 59 | } 60 | } 61 | 62 | [PublicAPI] 63 | [Preserve] 64 | public class Location 65 | { 66 | [DataMember(Name = "line")] 67 | public int Line { get; set; } 68 | 69 | [DataMember(Name = "column")] 70 | public int Column { get; set; } 71 | 72 | [Preserve] // Ensures it survives code-stripping 73 | public Location() 74 | { 75 | } 76 | } 77 | } -------------------------------------------------------------------------------- /Runtime/SimpleGraphQL/Response.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e37fe1a274a541f889a676866851a8c2 3 | timeCreated: 1620144704 -------------------------------------------------------------------------------- /Runtime/SimpleGraphQL/UnityWebRequestException.cs: -------------------------------------------------------------------------------- 1 | // Based on: https://github.com/Cysharp/UniTask/blob/master/src/UniTask/Assets/Plugins/UniTask/Runtime/UnityWebRequestException.cs 2 | 3 | // The MIT License (MIT) 4 | // 5 | // Copyright (c) 2019 Yoshifumi Kawai / Cysharp, Inc. 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all 15 | // copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | // SOFTWARE. 24 | 25 | using System; 26 | using System.Collections.Generic; 27 | using JetBrains.Annotations; 28 | using UnityEngine.Networking; 29 | 30 | namespace SimpleGraphQL 31 | { 32 | [PublicAPI] 33 | public class UnityWebRequestException : Exception 34 | { 35 | public UnityWebRequest UnityWebRequest { get; } 36 | #if UNITY_2020_2_OR_NEWER 37 | public UnityWebRequest.Result Result { get; } 38 | #else 39 | public bool IsNetworkError { get; } 40 | public bool IsHttpError { get; } 41 | #endif 42 | public string Error { get; } 43 | public string Text { get; } 44 | public long ResponseCode { get; } 45 | public Dictionary ResponseHeaders { get; } 46 | 47 | private string _msg; 48 | 49 | public UnityWebRequestException(UnityWebRequest unityWebRequest) 50 | { 51 | UnityWebRequest = unityWebRequest; 52 | #if UNITY_2020_2_OR_NEWER 53 | Result = unityWebRequest.result; 54 | #else 55 | this.IsNetworkError = unityWebRequest.isNetworkError; 56 | this.IsHttpError = unityWebRequest.isHttpError; 57 | #endif 58 | Error = unityWebRequest.error; 59 | ResponseCode = unityWebRequest.responseCode; 60 | 61 | if (UnityWebRequest.downloadHandler != null) 62 | { 63 | if (unityWebRequest.downloadHandler is DownloadHandlerBuffer dhb) 64 | { 65 | Text = dhb.text; 66 | } 67 | } 68 | 69 | ResponseHeaders = unityWebRequest.GetResponseHeaders(); 70 | } 71 | 72 | public override string Message 73 | { 74 | get 75 | { 76 | if (_msg == null) 77 | { 78 | if (Text != null) 79 | { 80 | _msg = Error + Environment.NewLine + Text; 81 | } 82 | else 83 | { 84 | _msg = Error; 85 | } 86 | } 87 | 88 | return _msg; 89 | } 90 | } 91 | } 92 | } -------------------------------------------------------------------------------- /Runtime/SimpleGraphQL/UnityWebRequestException.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: aae9a1fa3eed469c8e7329b47b94a0b0 3 | timeCreated: 1624357139 -------------------------------------------------------------------------------- /Runtime/SimpleGraphQL/YieldInstructions.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3004a14779ca4035991a6b06f1ecb83d 3 | timeCreated: 1603831576 -------------------------------------------------------------------------------- /Runtime/SimpleGraphQL/YieldInstructions/WaitForSend.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using JetBrains.Annotations; 4 | using UnityEngine; 5 | 6 | namespace SimpleGraphQL.YieldInstructions 7 | { 8 | [PublicAPI] 9 | public class WaitForSend : CustomYieldInstruction 10 | { 11 | private bool _taskDone; 12 | 13 | public override bool keepWaiting => !_taskDone; 14 | 15 | /// 16 | /// Create a new WaitForSend Yield Instruction. 17 | /// 18 | /// The graphQL send function. 19 | /// The callback that will be invoked after the task is complete. 20 | public WaitForSend(Func> sendFunc, Action onComplete) 21 | { 22 | Task.Run(() => RunSend(sendFunc, onComplete)); 23 | } 24 | 25 | private async Task RunSend(Func> func, Action onComplete) 26 | { 27 | string result = await func.Invoke(); 28 | _taskDone = true; 29 | 30 | onComplete.Invoke(result); 31 | 32 | return result; 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /Runtime/SimpleGraphQL/YieldInstructions/WaitForSend.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0178d7e285534c9e94ed178b9e6ca414 3 | timeCreated: 1603830618 -------------------------------------------------------------------------------- /Tests.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e2875de05c81d114d98d022831ec1d66 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Tests/Runtime.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ba5c84dcab58f424cb82b6c42096a005 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Tests/Runtime/LastAbyss.SimpleGraphQL.Runtime.Tests.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "LastAbyss.SimpleGraphQL.Runtime.Tests", 3 | "rootNamespace": "SimpleGraphQL.Tests", 4 | "references": [ 5 | "UnityEngine.TestRunner", 6 | "UnityEditor.TestRunner", 7 | "LastAbyss.SimpleGraphQL.Runtime" 8 | ], 9 | "includePlatforms": [], 10 | "excludePlatforms": [], 11 | "allowUnsafeCode": false, 12 | "overrideReferences": true, 13 | "precompiledReferences": [ 14 | "nunit.framework.dll", 15 | "Newtonsoft.Json.dll" 16 | ], 17 | "autoReferenced": false, 18 | "defineConstraints": [ 19 | "UNITY_INCLUDE_TESTS" 20 | ], 21 | "versionDefines": [], 22 | "noEngineReferences": false 23 | } 24 | -------------------------------------------------------------------------------- /Tests/Runtime/LastAbyss.SimpleGraphQL.Runtime.Tests.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e86aa5191ccd2af4a975e98a6004f481 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Tests/Runtime/QueryTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Linq; 4 | using NUnit.Framework; 5 | using UnityEngine.Networking; 6 | using UnityEngine.TestTools; 7 | using Newtonsoft.Json; 8 | 9 | namespace SimpleGraphQL.Tests 10 | { 11 | public class QueryTests 12 | { 13 | // TODO: Ideally mock our own server, but for now just use a publicly available one 14 | private const string Uri = "https://countries.trevorblades.com"; 15 | 16 | [UnityTest] 17 | public IEnumerator SimpleQuery() 18 | { 19 | var client = new GraphQLClient(Uri); 20 | var request = new Request { Query = "{ continents { name } }" }; 21 | var responseType = new { continents = new[] { new { name = "" } } }; 22 | var response = client.Send(() => responseType, request); 23 | 24 | yield return response.AsCoroutine(); 25 | 26 | Assert.IsNull(response.Result.Errors); 27 | 28 | var data = response.Result.Data; 29 | Assert.IsNotNull(data); 30 | Assert.IsNotNull(data.continents); 31 | Assert.IsTrue(data.continents.Any(c => c.name == "Europe")); 32 | } 33 | 34 | [UnityTest] 35 | public IEnumerator MalformedQuery() 36 | { 37 | var client = new GraphQLClient(Uri); 38 | var query = new Request { Query = "{ continents MALFORMED name } }" }; 39 | var responseType = new { continents = new[] { new { name = "" } } }; 40 | var response = client.Send(() => responseType, query); 41 | 42 | yield return response.AsCoroutineUnchecked(); 43 | var ex = response.Expect(); 44 | 45 | Assert.AreEqual(ex.ResponseCode, 400); // Bad request 46 | 47 | Error[] errors = DeserializeResponse(() => responseType, ex.Text).Errors; 48 | 49 | Assert.IsNotNull(errors); 50 | Assert.IsNotEmpty(errors); 51 | Assert.IsNotNull(errors[0].Message); 52 | } 53 | 54 | // Could be part of the library? 55 | private Response DeserializeResponse(Func responseTypeResolver, string json) 56 | { 57 | return JsonConvert.DeserializeObject>(json); 58 | } 59 | 60 | [UnityTest] 61 | public IEnumerator QueryWithArgs() 62 | { 63 | var client = new GraphQLClient(Uri); 64 | var request = new Request 65 | { 66 | Query = "query ContinentNameByCode($code: ID!) { continent(code: $code) { name } }", 67 | Variables = new 68 | { 69 | code = "EU" 70 | } 71 | }; 72 | var responseType = new { continent = new { name = "" } }; 73 | var response = client.Send(() => responseType, request); 74 | 75 | yield return response.AsCoroutine(); 76 | 77 | Assert.IsNull(response.Result.Errors); 78 | 79 | var data = response.Result.Data; 80 | Assert.IsNotNull(data); 81 | Assert.IsNotNull(data.continent); 82 | Assert.AreEqual(data.continent.name, "Europe"); 83 | } 84 | 85 | [UnityTest] 86 | public IEnumerator NetworkError() 87 | { 88 | var client = new GraphQLClient("https://non_resolvable_host_123123123123123"); 89 | var request = new Request { Query = "{ continents { name } }" }; 90 | var responseType = new { continents = new[] { new { name = "" } } }; 91 | var response = client.Send(() => responseType, request); 92 | 93 | yield return response.AsCoroutineUnchecked(); 94 | var ex = response.Expect(); 95 | #if UNITY_2020_2_OR_NEWER 96 | Assert.AreEqual(ex.Result, UnityWebRequest.Result.ConnectionError); 97 | #else 98 | Assert.IsTrue(ex.IsNetworkError); 99 | #endif 100 | } 101 | 102 | [UnityTest] 103 | public IEnumerator Http404Error() 104 | { 105 | var client = new GraphQLClient("https://google.com/url_that_returns_404_lsdfksadjflksdafjs"); 106 | var request = new Request { Query = "{ continents { name } }" }; 107 | var responseType = new { continents = new[] { new { name = "" } } }; 108 | var response = client.Send(() => responseType, request); 109 | 110 | yield return response.AsCoroutineUnchecked(); 111 | var ex = response.Expect(); 112 | #if UNITY_2020_2_OR_NEWER 113 | Assert.AreEqual(ex.Result, UnityWebRequest.Result.ProtocolError); 114 | #else 115 | Assert.IsTrue(ex.IsHttpError); 116 | #endif 117 | Assert.AreEqual(ex.ResponseCode, 404); 118 | } 119 | } 120 | } -------------------------------------------------------------------------------- /Tests/Runtime/QueryTests.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b0df056492699dc45bdff346a0f7b587 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Tests/Runtime/UnityTestAsyncExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Threading.Tasks; 4 | using NUnit.Framework; 5 | using UnityEngine; 6 | 7 | namespace SimpleGraphQL.Tests 8 | { 9 | public static class UnityTestAsyncExtensions 10 | { 11 | public static IEnumerator AsCoroutine(this Task task) 12 | { 13 | while (!task.IsCompleted) yield return null; 14 | // Throws if the Task fails 15 | task.GetAwaiter().GetResult(); 16 | } 17 | 18 | // Doesn't check for errors 19 | public static IEnumerator AsCoroutineUnchecked(this Task task) 20 | { 21 | while (!task.IsCompleted) yield return null; 22 | } 23 | 24 | public static void ThrowExceptions(this Task task) 25 | { 26 | Debug.Assert(task.IsCompleted); 27 | task.GetAwaiter().GetResult(); 28 | } 29 | 30 | public static T Expect(this Task task) 31 | where T: Exception 32 | { 33 | try 34 | { 35 | task.ThrowExceptions(); 36 | } 37 | catch (T ex) 38 | { 39 | Assert.IsNotNull(ex); 40 | return ex; // OK! 41 | } 42 | throw new AssertionException($"Expected task to throw {typeof(T)}"); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /Tests/Runtime/UnityTestAsyncExtensions.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0989e45b66e34b05be8f976dcb41ef94 3 | timeCreated: 1620237489 -------------------------------------------------------------------------------- /Tests/Runtime/sample.graphql: -------------------------------------------------------------------------------- 1 | query GetContinents { 2 | continents { 3 | name 4 | } 5 | } -------------------------------------------------------------------------------- /Tests/Runtime/sample.graphql.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 909905e8c7fb4225a73670be96a121f1 3 | ScriptedImporter: 4 | internalIDToNameTable: [] 5 | externalObjects: {} 6 | serializedVersion: 2 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | script: {fileID: 11500000, guid: 1d33fc8355b800b49883cbcc4d3b2b9c, type: 3} 11 | -------------------------------------------------------------------------------- /link.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /link.xml.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9bbe747a148f00540828ab8521feb770 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "com.lastabyss.simplegraphql", 3 | "version": "2.1.0", 4 | "displayName": "SimpleGraphQL", 5 | "description": "A simple graphQL client that allows one to use .graphql files (or code) for queries, mutations, and subscriptions with Unity.", 6 | "unity": "2019.4", 7 | "keywords": [ 8 | "graphql", 9 | "client", 10 | "async", 11 | "await", 12 | "asynchronous", 13 | ".graphql", 14 | "files", 15 | "codebased", 16 | "library" 17 | ], 18 | "author": { 19 | "name": "Last Abyss Inc.", 20 | "email": "contact@lastabyss.com", 21 | "url": "https://lastabyss.com" 22 | }, 23 | "dependencies": { 24 | "com.unity.nuget.newtonsoft-json": "2.0.0" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /package.json.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4483865f1d1a5cd458944d107efaa9e7 3 | PackageManifestImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | --------------------------------------------------------------------------------