├── .gitattributes ├── .gitignore ├── CleanupExample.ps1 ├── ConfigureTestLocalSettings.ps1 ├── ConfigureVersion.ps1 ├── Documentation ├── Caching.md ├── Connections.md ├── MutationActions.md ├── Mutations.md ├── Nuget.md ├── Queries.md ├── Searches.md ├── Tracing.md ├── Transforms.md └── Validations.md ├── Eklee.Azure.Functions.GraphQl.Tests ├── Actions │ ├── MockModel1.cs │ ├── MockModel2.cs │ ├── MockModel3.cs │ ├── MockModel4.cs │ └── ModelTransformerProviderTests.cs ├── Connections │ ├── ConnectionEdgeHandlerTests.cs │ ├── ConnectionFieldResolverTests.cs │ ├── ExtensionsTests.cs │ └── ListConnectionEdgeQueryParameterTests.cs ├── Constants.cs ├── ContextValueTests.cs ├── DocumentDbConfigurationTests.cs ├── Eklee.Azure.Functions.GraphQl.Tests.csproj ├── Extensions.cs ├── ExtensionsTests.cs ├── JwtConfigParametersTests.cs ├── LocalConfiguration.cs ├── ModelEnumConventionTypeTests.cs ├── Models │ ├── Model1.cs │ ├── Model1Friend.cs │ ├── Model2.cs │ ├── Model2ConnectionToModel3.cs │ ├── Model3.cs │ ├── ModelWith3Connections.cs │ ├── ModelWith3ConnectionsEdge.cs │ ├── ModelWith3ConnectionsOther.cs │ └── NoneConnectionModel.cs ├── Queries │ └── SearchFilterModelQueryArgumentTests.cs ├── QueryParameterListExtensionsTests.cs ├── QueryStepExtensionsTests.cs ├── Repository │ ├── BatchModelListTests.cs │ ├── DocumentDb │ │ ├── DocumentDbRepositoryQueryTests.cs │ │ ├── DocumentDbRepositoryTests.cs │ │ └── DocumentDbRepositoryTestsBase.cs │ ├── GraphQlRepositoryExtensionsTests.cs │ ├── InMemory │ │ ├── InMemItem.cs │ │ ├── InMemoryCompareDateTimeTests.cs │ │ ├── InMemoryCompareIntTests.cs │ │ ├── InMemoryCompareStringTests.cs │ │ ├── InMemoryCompareTestBase.cs │ │ ├── InMemoryRepositoryQueryTests.cs │ │ └── InMemoryRepositoryTests.cs │ ├── Search │ │ ├── Filters │ │ │ ├── MockItem.cs │ │ │ ├── NumericSearchFilterTests.cs │ │ │ ├── SearchFilterProviderTests.cs │ │ │ └── StringSearchFilterTests.cs │ │ ├── SearchMappedModelsTests.cs │ │ ├── SearchRepositoryQueryTests.cs │ │ └── SearchRepositoryQueryTestsBase.cs │ └── TableStorage │ │ ├── TableStorageComparisonStringTests.cs │ │ ├── TableStorageRepositoryQueryTests.cs │ │ ├── TableStorageRepositoryTests.cs │ │ └── TableStorageRepositoryTestsBase.cs ├── SecurityExtensionsTests.cs ├── Validations │ └── StringLengthModelValidationTests.cs └── xunit.runner.json ├── Eklee.Azure.Functions.GraphQl.sln ├── Eklee.Azure.Functions.GraphQl ├── Actions │ ├── AutoDateTimeGenerator.cs │ ├── AutoIdGenerator.cs │ ├── IModelTransformer.cs │ ├── IModelTransformerProvider.cs │ ├── ModelTransformerProvider.cs │ ├── RequestContextValueExtractors │ │ └── IRequestContextValueExtractor.cs │ └── ValueFromRequestContextGenerator.cs ├── AssertAction.cs ├── Attributes │ ├── AutoDateTimeAttribute.cs │ ├── AutoIdAttribute.cs │ ├── ModelFieldAttribute.cs │ ├── PartitionKeyAttribute.cs │ └── RequestContextValueAttribute.cs ├── Comparisons.cs ├── Connections │ ├── ConnectionAttribute.cs │ ├── ConnectionEdge.cs │ ├── ConnectionEdgeDestinationAttribute.cs │ ├── ConnectionEdgeDestinationFilter.cs │ ├── ConnectionEdgeDestinationKeyAttribute.cs │ ├── ConnectionEdgeHandler.cs │ ├── ConnectionEdgeQueryBuilder.cs │ ├── ConnectionEdgeQueryParameter.cs │ ├── ConnectionEdgeResolver.cs │ ├── Extensions.cs │ ├── IConnectionEdgeHandler.cs │ ├── IConnectionEdgeResolver.cs │ └── InternalConnectionEdgeState.cs ├── ContextValue.cs ├── ContextValueSetRule.cs ├── Eklee.Azure.Functions.GraphQl.csproj ├── Eklee.Azure.Functions.GraphQl.nuspec ├── ExecutionErrorResponse.cs ├── ExecutionResultResponse.cs ├── ExecutionResultResponseExtension.cs ├── Extensions.cs ├── Filters │ ├── BoolFilter.cs │ ├── DateFilter.cs │ ├── FieldNameValueFilter.cs │ ├── GuidFilter.cs │ ├── IntFilter.cs │ ├── StringEqualFilter.cs │ └── StringFilter.cs ├── GraphDependencyResolver.cs ├── GraphQlDomain.cs ├── GraphQlDomainRequest.cs ├── GraphRequestContext.cs ├── IGraphQlDomain.cs ├── IGraphRequestContext.cs ├── IModelConventionInputBuilder.cs ├── IQueryArgumentsBuilder.cs ├── InputBuilderFactory.cs ├── JwtConfigParameters.cs ├── MapperQueryExecutionContext.cs ├── ModelConvention.cs ├── ModelConventionInputBuilder.cs ├── ModelConventionInputType.cs ├── ModelConventionType.cs ├── ModelEnumConventionType.cs ├── ModelMember.cs ├── ModelType.cs ├── ObjectCacheResult.cs ├── Queries │ ├── BoolQueryArgument.cs │ ├── Constants.cs │ ├── ContextValueResolver.cs │ ├── DateQueryArgument.cs │ ├── GuidQueryArgument.cs │ ├── IContextValueResolver.cs │ ├── IModelMemberQueryArgument.cs │ ├── IModelMemberQueryArgumentProvider.cs │ ├── IntQueryArgument.cs │ ├── ModelMemberQueryArgumentProvider.cs │ ├── SearchFilterModelQueryArgument.cs │ ├── SearchModelQueryArgument.cs │ └── StringQueryArgument.cs ├── QueryArgumentsBuilder.cs ├── QueryBuilder.cs ├── QueryBuilderFactory.cs ├── QueryExecutionContext.cs ├── QueryExecutor.cs ├── QueryExtensions.cs ├── QueryOutput.cs ├── QueryParameter.cs ├── QueryParameterBuilder.cs ├── QueryParameterBuilderSearchExtensions.cs ├── QueryParameterListExtensions.cs ├── QueryStep.cs ├── QueryStepBuilder.cs ├── QueryStepExtensions.cs ├── Repository │ ├── BatchModelList.cs │ ├── DocumentDb │ │ ├── BaseDocumentDbComparison.cs │ │ ├── DocumentClientProvider.cs │ │ ├── DocumentDbComparisonBool.cs │ │ ├── DocumentDbComparisonDate.cs │ │ ├── DocumentDbComparisonGuid.cs │ │ ├── DocumentDbComparisonInt.cs │ │ ├── DocumentDbComparisonString.cs │ │ ├── DocumentDbConfiguration.cs │ │ ├── DocumentDbConfigurationExtensions.cs │ │ ├── DocumentDbConstants.cs │ │ ├── DocumentDbExtensions.cs │ │ ├── DocumentDbRepository.cs │ │ ├── DocumentDbSqlParameter.cs │ │ └── IDocumentDbComparison.cs │ ├── FieldMutationResolver.cs │ ├── GraphQlRepositoryExtensions.cs │ ├── GraphQlRepositoryProvider.cs │ ├── Http │ │ ├── HttpConfiguration.cs │ │ ├── HttpConstants.cs │ │ ├── HttpRepository.cs │ │ └── HttpTypeConfiguration.cs │ ├── IFieldMutationResolver.cs │ ├── IGraphQlRepository.cs │ ├── IGraphQlRepositoryProvider.cs │ ├── IMutationActionsProvider.cs │ ├── IMutationPostAction.cs │ ├── IMutationPreAction.cs │ ├── InMemory │ │ ├── IInMemoryCompare.cs │ │ ├── IInMemoryComparerProvider.cs │ │ ├── InMemoryCompareDateTime.cs │ │ ├── InMemoryCompareInt.cs │ │ ├── InMemoryCompareString.cs │ │ ├── InMemoryComparerProvider.cs │ │ ├── InMemoryConfiguration.cs │ │ └── InMemoryRepository.cs │ ├── MutationActionItem.cs │ ├── MutationActions.cs │ ├── MutationActionsProvider.cs │ ├── Search │ │ ├── Extensions.cs │ │ ├── FieldAggregateModel.cs │ │ ├── Filters │ │ │ ├── ISearchFilter.cs │ │ │ ├── ISearchFilterProvider.cs │ │ │ ├── NumericSearchFilter.cs │ │ │ ├── SearchFilterProvider.cs │ │ │ └── StringSearchFilter.cs │ │ ├── ISearchMappedModels.cs │ │ ├── SearchAggregateModel.cs │ │ ├── SearchClientProvider.cs │ │ ├── SearchConfiguration.cs │ │ ├── SearchConstants.cs │ │ ├── SearchFilterModel.cs │ │ ├── SearchMappedModel.cs │ │ ├── SearchMappedModels.cs │ │ ├── SearchModel.cs │ │ ├── SearchRepository.cs │ │ ├── SearchResult.cs │ │ ├── SearchResultExtensions.cs │ │ └── SearchResultModel.cs │ └── TableStorage │ │ ├── ITableStorageComparison.cs │ │ ├── TableStorageClientProvider.cs │ │ ├── TableStorageComparisonBase.cs │ │ ├── TableStorageComparisonBool.cs │ │ ├── TableStorageComparisonDate.cs │ │ ├── TableStorageComparisonGuid.cs │ │ ├── TableStorageComparisonInt.cs │ │ ├── TableStorageComparisonString.cs │ │ ├── TableStorageConfiguration.cs │ │ ├── TableStorageConstants.cs │ │ └── TableStorageRepository.cs ├── SearchQueryBuilder.cs ├── SecurityExtensions.cs └── Validations │ ├── DataAnnotationsValidation.cs │ ├── IModelValidation.cs │ └── StringLengthModelValidation.cs ├── Examples └── Eklee.Azure.Functions.GraphQl.Example │ ├── .gitignore │ ├── Actions │ └── ValueFromRequestHeader.cs │ ├── BooksGraphFunction.cs │ ├── BusinessLayer │ ├── BookAuthorsOutputExtensions.cs │ ├── BookPrice.cs │ ├── BookReviewQueryExtensions.cs │ ├── BooksMutation.cs │ ├── BooksQuery.cs │ ├── BooksQueryExtensions.cs │ ├── BooksSchema.cs │ ├── PagingBooksMutation.cs │ ├── PagingBooksQuery.cs │ ├── PagingBooksSchema.cs │ └── PublisherQueryExtensions.cs │ ├── Eklee.Azure.Functions.GraphQl.Example.csproj │ ├── HttpMocks │ ├── IHttpMockRepository.cs │ ├── Publisher.cs │ └── PublisherMockRepository.cs │ ├── Models │ ├── Author.cs │ ├── Book.cs │ ├── BookAuthors.cs │ ├── BookAuthorsOutput.cs │ ├── BookId.cs │ ├── BookReview.cs │ ├── BookReviewOutput.cs │ ├── BookSearch.cs │ ├── EachModel10.cs │ ├── EachModel11.cs │ ├── Model1.cs │ ├── Model10.cs │ ├── Model11.cs │ ├── Model12.cs │ ├── Model13Child.cs │ ├── Model13Edge.cs │ ├── Model13Parent.cs │ ├── Model14.cs │ ├── Model15.cs │ ├── Model16.cs │ ├── Model17.cs │ ├── Model18.cs │ ├── Model19.cs │ ├── Model2.cs │ ├── Model3.cs │ ├── Model3V2.cs │ ├── Model4.cs │ ├── Model5.cs │ ├── Model5Friend.cs │ ├── Model6.cs │ ├── Model6Friend.cs │ ├── Model7.cs │ ├── Model7ToModel8.cs │ ├── Model8.cs │ ├── Model9.cs │ ├── Reviewer.cs │ ├── Status.cs │ ├── TestPermissionModel1.cs │ ├── TestPermissionModel2.cs │ └── TestPermissionModel3.cs │ ├── MyModule.cs │ ├── MyModule2.cs │ ├── MyPagingBooksModule.cs │ ├── MyPublisherHttpFunction.cs │ ├── Operations │ ├── IOperations.cs │ ├── Operations.cs │ ├── OperationsHttpFunction.cs │ └── OperationsModule.cs │ ├── PagingBooksGraphFunction.cs │ ├── TestDocumentDb │ ├── Events │ │ ├── BarMutationPostAction.cs │ │ ├── BarMutationPreAction.cs │ │ ├── FooBarBase.cs │ │ ├── FooMutationPostAction.cs │ │ └── FooMutationPreAction.cs │ ├── Query │ │ ├── GetModel7FromConnectionEdgeExtensions.cs │ │ └── GetModel7WithModel8FieldAndConnectionFieldDescriptionExtensions.cs │ ├── TestDocumentDbGraphFunction.cs │ ├── TestDocumentDbModule.cs │ ├── TestDocumentDbMutation.cs │ ├── TestDocumentDbQuery.cs │ └── TestDocumentDbSchema.cs │ ├── TestDocumentDbWithPermissions │ ├── TestDocumentDbWithPermissionsFunction.cs │ ├── TestDocumentDbWithPermissionsModule.cs │ ├── TestDocumentDbWithPermissionsMutation.cs │ ├── TestDocumentDbWithPermissionsQuery.cs │ └── TestDocumentDbWithPermissionsSchema.cs │ ├── TestInMemory │ ├── TestInMemoryGraphFunction.cs │ ├── TestInMemoryModule.cs │ ├── TestInMemoryMutation.cs │ ├── TestInMemoryQuery.cs │ └── TestInMemorySchema.cs │ ├── TestSearch │ ├── Models │ │ ├── MySearch1.cs │ │ ├── MySearch2.cs │ │ ├── MySearch3.cs │ │ ├── MySearchResult.cs │ │ └── MySearchResult2.cs │ ├── TestSearchGraphFunction.cs │ ├── TestSearchModule.cs │ ├── TestSearchMutation.cs │ ├── TestSearchQuery.cs │ └── TestSearchSchema.cs │ ├── TestSearch2 │ ├── Models │ │ ├── MySearch4.cs │ │ ├── MySearch4Result.cs │ │ ├── MySearch5.cs │ │ ├── MySearch6.cs │ │ ├── MySearch7.cs │ │ └── MySearch8.cs │ ├── TestSearchGraphFunction2.cs │ ├── TestSearchModule2.cs │ ├── TestSearchMutation2.cs │ ├── TestSearchQuery2.cs │ └── TestSearchSchema2.cs │ ├── TestStorage │ ├── TestStorageFunctionModule.cs │ ├── TestStorageGraphQLFunction.cs │ ├── TestStorageMutationObjectGraphType.cs │ ├── TestStorageQueryObjectGraphType.cs │ └── TestStorageSchemaConfig.cs │ ├── Validations │ └── MyValidation.cs │ └── host.json ├── LICENSE ├── PrepNugetPack.ps1 ├── README.md ├── Reset.ps1 ├── ResetDocumentDb.ps1 ├── ResetSearch.ps1 ├── ResetTableStorage.ps1 ├── Templates └── app.json ├── TestExample.ps1 ├── Tests ├── Deployment │ └── template.json └── Eklee.Azure.Functions.GraphQl.postman_collection.json ├── azure-pipelines.yml ├── cicd.ps1 └── version.txt /CleanupExample.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | [Parameter(Mandatory = $True)][string]$Name) 3 | 4 | $StackName = ($Name + $env:Build_BuildNumber).Replace(".", "") 5 | 6 | $resources = az resource list --tag stackName=$StackName | ConvertFrom-Json 7 | 8 | $funcId = ($resources | Where-Object { $_.type -eq "Microsoft.Web/sites" }).id 9 | 10 | az resource delete --ids $funcId 11 | 12 | $resources | Where-Object { $_.type -ne "Microsoft.Web/sites" } | ForEach-Object { az resource delete --ids $_.id } -------------------------------------------------------------------------------- /ConfigureVersion.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | [Parameter(Mandatory = $True)][string]$BuildId) 3 | 4 | # Note: We are following: https://semver.org/ 5 | # Given a version number MAJOR.MINOR.PATCH, increment the: 6 | 7 | # MAJOR version when you make incompatible API changes, 8 | # MINOR version when you add functionality in a backwards-compatible manner OR bugfixes 9 | 10 | $versions = (Get-Content version.txt).Split(".") 11 | $major = [int]$versions[0] 12 | $minor = [int]$versions[1] 13 | $patch = [int]($BuildId.Split(".")[1]) 14 | 15 | $version = "$major.$minor.$patch" 16 | 17 | Write-Host "##vso[task.setvariable variable=buildConfig;isOutput=true]Release" 18 | Write-Host "##vso[task.setvariable variable=version;isOutput=true]$version" -------------------------------------------------------------------------------- /Documentation/Caching.md: -------------------------------------------------------------------------------- 1 | [Main page](../README.md) 2 | 3 | # Introduction 4 | 5 | To setup caching, in your Module setup, use the extension method UseDistributedCache. Note that MemoryDistributedCache is just an example. In a production senario, you may choose something like Azure Redis. 6 | 7 | ``` 8 | builder.UseDistributedCache(); 9 | ``` -------------------------------------------------------------------------------- /Documentation/Nuget.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | Eklee-Azure-Functions-GraphQl is a serverless GraphQL implementation built on top of [graphql-dotnet](https://github.com/graphql-dotnet/graphql-dotnet), Azure Functions and several Azure specific services. 3 | 4 | It includes resolvers for: 5 | 6 | * Azure Cosmos DB 7 | * Azure Search 8 | * Azure Table Storage 9 | 10 | Currently, query and mutation are supported. 11 | 12 | ## Usage 13 | Documentation for using Eklee-Azure-Functions-GraphQl can be found on the following links: 14 | 15 | * [Eklee-Azure-Functions-GraphQl](https://github.com/seekdavidlee/Eklee-Azure-Functions-GraphQl/) 16 | * [Eklee-Azure-Functions-GraphQl-Examples](https://github.com/seekdavidlee/Eklee-Azure-Functions-GraphQl-Examples) 17 | * [Eklee-Exams-Api](https://github.com/seekdavidlee/Eklee-Exams-Api) -------------------------------------------------------------------------------- /Documentation/Tracing.md: -------------------------------------------------------------------------------- 1 | [Main page](../README.md) 2 | 3 | # Introduction 4 | 5 | Tracing enables you to track internal stats about your GraphQL execution. To enable support for tracing, please add set EnableMetrics configuration to true under GraphQl. 6 | 7 | ``` 8 | { 9 | ... 10 | "GraphQl": { 11 | "EnableMetrics": "true" 12 | } 13 | } 14 | ``` 15 | 16 | For more information about Tracing, visit https://graphql-dotnet.github.io/docs/getting-started/metrics. -------------------------------------------------------------------------------- /Documentation/Validations.md: -------------------------------------------------------------------------------- 1 | [Main page](../README.md) 2 | 3 | # Validation introduction 4 | Model validation can be leverage by performing two steps. Create your Model and add a supported attribute from System.ComponentModel.DataAnnotations. Next, add the following in your AutoFac Module. 5 | 6 | ``` 7 | builder.UseDataAnnotationsValidation(); 8 | ``` 9 | 10 | ## Currently supported attribute 11 | 12 | * StringLengthAttribute 13 | 14 | ## Custom Model Validation 15 | 16 | You can also validate your Model via a custom validator. You will need to implement the IModelValidation interface. An example below. 17 | 18 | ``` 19 | public class MyValidation : IModelValidation 20 | { 21 | public bool CanHandle(Type type) 22 | { 23 | return type == typeof(Model4); 24 | } 25 | 26 | public bool TryAssertMemberValueIsValid(Member member, object value, out string errorCode, out string message) 27 | { 28 | if (member.Name == "DateField") 29 | { 30 | DateTime result; 31 | if (DateTime.TryParse(value.ToString(), out result)) 32 | { 33 | if (result == DateTime.MinValue) 34 | { 35 | errorCode = "DateTimeError"; 36 | message = "DateTime cannot be Min Value."; 37 | return false; 38 | } 39 | } 40 | else 41 | { 42 | errorCode = "DateTimeError"; 43 | message = "DateTime is invalid."; 44 | return false; 45 | } 46 | } 47 | 48 | errorCode = null; 49 | message = null; 50 | return true; 51 | } 52 | } 53 | ``` 54 | 55 | Lastly, register your custom validator in your AutoFac Module. 56 | 57 | ``` 58 | builder.RegisterType().As(); 59 | ``` -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl.Tests/Actions/MockModel1.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl.Tests.Actions 4 | { 5 | public class MockModel1 6 | { 7 | public string Id { get; set; } 8 | 9 | public List Model2List { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl.Tests/Actions/MockModel2.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.GraphQl.Connections; 2 | using System.Collections.Generic; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Tests.Actions 5 | { 6 | public class MockModel2 7 | { 8 | public string Id { get; set; } 9 | 10 | public List Model3List { get; set; } 11 | 12 | [ConnectionEdgeDestination] 13 | public MockModel4 SomeMock { get; set; } 14 | } 15 | } -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl.Tests/Actions/MockModel3.cs: -------------------------------------------------------------------------------- 1 | namespace Eklee.Azure.Functions.GraphQl.Tests.Actions 2 | { 3 | public class MockModel3 4 | { 5 | public string Id { get; set; } 6 | 7 | public string Value { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl.Tests/Actions/MockModel4.cs: -------------------------------------------------------------------------------- 1 | namespace Eklee.Azure.Functions.GraphQl.Tests.Actions 2 | { 3 | public class MockModel4 4 | { 5 | public string Id { get; set; } 6 | 7 | public string Value { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl.Tests/Connections/ListConnectionEdgeQueryParameterTests.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.GraphQl.Connections; 2 | using Eklee.Azure.Functions.GraphQl.Tests.Models; 3 | using Shouldly; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using Xunit; 7 | 8 | namespace Eklee.Azure.Functions.GraphQl.Tests.Connections 9 | { 10 | [Trait(Constants.Category, Constants.UnitTests)] 11 | public class ListConnectionEdgeQueryParameterTests 12 | { 13 | private readonly ConnectionEdgeResolver _connectionFieldResolver = 14 | new ConnectionEdgeResolver(); 15 | 16 | [Fact] 17 | public void CanList() 18 | { 19 | var models = new List 20 | { 21 | new Model1 { Id = "f1" }, 22 | new Model1 { Id = "f2" }, 23 | new Model1 { Id = "f3" }, 24 | new Model1 { Id = "f4" } 25 | }; 26 | 27 | var list = _connectionFieldResolver.ListConnectionEdgeQueryParameter(models); 28 | list.Count.ShouldBe(4); 29 | 30 | list.SingleOrDefault(item => item.SourceId == "f1").ShouldNotBeNull(); 31 | list.SingleOrDefault(item => item.SourceId == "f2").ShouldNotBeNull(); 32 | list.SingleOrDefault(item => item.SourceId == "f3").ShouldNotBeNull(); 33 | list.SingleOrDefault(item => item.SourceId == "f4").ShouldNotBeNull(); 34 | 35 | list.ForEach(item => 36 | { 37 | item.SourceFieldName.ShouldNotBeNullOrEmpty(); 38 | item.SourceType.ShouldNotBeNullOrEmpty(); 39 | }); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl.Tests/Constants.cs: -------------------------------------------------------------------------------- 1 | namespace Eklee.Azure.Functions.GraphQl.Tests 2 | { 3 | public static class Constants 4 | { 5 | public const string Category = "Category"; 6 | public const string UnitTests = "Unit"; 7 | public const string IntegrationTests = "Integration"; 8 | public const string DocumentDbTests = "DocumentDb Tests"; 9 | public const string TableStorageTests = "TableStorage Tests"; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl.Tests/ContextValueTests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Shouldly; 3 | using Xunit; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl.Tests 6 | { 7 | [Trait(Constants.Category, Constants.UnitTests)] 8 | public class ContextValueTests 9 | { 10 | private readonly ContextValue _contextValue = new ContextValue(); 11 | 12 | [Fact] 13 | public void SingleValueNotSetToBeFalse() 14 | { 15 | _contextValue.Values = new List(); 16 | _contextValue.IsSingleValue().ShouldBeFalse(); 17 | } 18 | 19 | [Fact] 20 | public void SingleValueSetToBeTrue() 21 | { 22 | _contextValue.Values = new List { "a" }; 23 | _contextValue.IsSingleValue().ShouldBeTrue(); 24 | } 25 | 26 | [Fact] 27 | public void AbleToGetFirstValue() 28 | { 29 | _contextValue.Values = new List { "a" }; 30 | _contextValue.GetFirstValue().ShouldBe("a"); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl.Tests/Eklee.Azure.Functions.GraphQl.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.1 5 | false 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | all 16 | runtime; build; native; contentfiles; analyzers 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | Always 27 | 28 | 29 | PreserveNewest 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl.Tests/Extensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Logging; 2 | using System; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Tests 5 | { 6 | public static class Extensions 7 | { 8 | public static DateTime ToUtc(this DateTime date) 9 | { 10 | return new DateTime(date.Year, date.Month, date.Day, 0, 0, 0, 0, DateTimeKind.Utc); 11 | } 12 | 13 | public static void Log(this string message) 14 | { 15 | Console.WriteLine($"[{DateTime.Now}] {message}"); 16 | } 17 | 18 | public static ILogger GetLogger() 19 | { 20 | using var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole()); 21 | var logger = loggerFactory.CreateLogger(); 22 | return logger; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl.Tests/JwtConfigParametersTests.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Configuration; 2 | using NSubstitute; 3 | using Shouldly; 4 | using Xunit; 5 | 6 | namespace Eklee.Azure.Functions.GraphQl.Tests 7 | { 8 | [Trait(Constants.Category, Constants.UnitTests)] 9 | public class JwtConfigParametersTests 10 | { 11 | [Fact] 12 | public void AudienceIsSet() 13 | { 14 | var config = Substitute.For(); 15 | 16 | config["Security:Audience"].Returns("abc"); 17 | 18 | var jwtConfig = new JwtConfigParameters(config); 19 | 20 | jwtConfig.Audience.ShouldBe("abc"); 21 | } 22 | 23 | [Fact] 24 | public void NoIssuerIsSet() 25 | { 26 | var config = Substitute.For(); 27 | 28 | var jwtConfig = new JwtConfigParameters(config); 29 | 30 | jwtConfig.Issuers.Length.ShouldBe(0); 31 | } 32 | 33 | [Fact] 34 | public void SingleIssuerIsSet() 35 | { 36 | var config = Substitute.For(); 37 | 38 | config["Security:Issuers"].Returns("abc"); 39 | 40 | var jwtConfig = new JwtConfigParameters(config); 41 | 42 | jwtConfig.Issuers.Length.ShouldBe(1); 43 | jwtConfig.Issuers[0].ShouldBe("abc"); 44 | } 45 | 46 | [Fact] 47 | public void MultipleIssuersAreSet() 48 | { 49 | var config = Substitute.For(); 50 | 51 | config["Security:Issuers"].Returns("abc def ghi"); 52 | 53 | var jwtConfig = new JwtConfigParameters(config); 54 | 55 | jwtConfig.Issuers.Length.ShouldBe(3); 56 | jwtConfig.Issuers[0].ShouldBe("abc"); 57 | jwtConfig.Issuers[1].ShouldBe("def"); 58 | jwtConfig.Issuers[2].ShouldBe("ghi"); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl.Tests/LocalConfiguration.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using Microsoft.Extensions.Configuration; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Tests 5 | { 6 | public static class LocalConfiguration 7 | { 8 | public static IConfiguration Get() 9 | { 10 | string currentDir = Directory.GetCurrentDirectory(); 11 | $"LocalConfiguration: {currentDir}".Log(); 12 | 13 | var builder = new ConfigurationBuilder(); 14 | builder.SetBasePath(currentDir); 15 | builder.AddJsonFile("local.settings.json"); 16 | return builder.Build(); 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl.Tests/Models/Model1.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.GraphQl.Connections; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Tests.Models 5 | { 6 | public class Model1 7 | { 8 | [Key] 9 | public string Id { get; set; } 10 | 11 | public string Field1 { get; set; } 12 | 13 | public int Field2 { get; set; } 14 | 15 | [Connection] 16 | public Model1Friend BestFriend { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl.Tests/Models/Model1Friend.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.GraphQl.Connections; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl.Tests.Models 4 | { 5 | public class Model1Friend 6 | { 7 | [ConnectionEdgeDestinationKey] 8 | public string Id { get; set; } 9 | 10 | public string Field1 { get; set; } 11 | 12 | public int Field2 { get; set; } 13 | 14 | [ConnectionEdgeDestination] 15 | public Model1 Model1 { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl.Tests/Models/Model2.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.GraphQl.Connections; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Tests.Models 5 | { 6 | public class Model2 7 | { 8 | [Key] 9 | public string Id { get; set; } 10 | 11 | public string Field1 { get; set; } 12 | 13 | public int Field2 { get; set; } 14 | 15 | [Connection] 16 | public Model2ConnectionToModel3 Edge { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl.Tests/Models/Model2ConnectionToModel3.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.GraphQl.Connections; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl.Tests.Models 4 | { 5 | public class Model2ConnectionToModel3 6 | { 7 | [ConnectionEdgeDestinationKey] 8 | public string Id { get; set; } 9 | 10 | public string Field1 { get; set; } 11 | 12 | [ConnectionEdgeDestination] 13 | public Model3 Model3 { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl.Tests/Models/Model3.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl.Tests.Models 4 | { 5 | public class Model3 6 | { 7 | [Key] 8 | public string Id { get; set; } 9 | 10 | public string Field1 { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl.Tests/Models/ModelWith3Connections.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.GraphQl.Connections; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Tests.Models 5 | { 6 | public class ModelWith3Connections 7 | { 8 | [Key] 9 | public string Id { get; set; } 10 | 11 | public string Field1 { get; set; } 12 | 13 | [Connection] 14 | public ModelWith3ConnectionsEdge Edge1 { get; set; } 15 | 16 | [Connection] 17 | public ModelWith3ConnectionsEdge Edge2 { get; set; } 18 | 19 | [Connection] 20 | public ModelWith3ConnectionsEdge Edge3 { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl.Tests/Models/ModelWith3ConnectionsEdge.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.GraphQl.Connections; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl.Tests.Models 4 | { 5 | public class ModelWith3ConnectionsEdge 6 | { 7 | [ConnectionEdgeDestinationKey] 8 | public string Id { get; set; } 9 | 10 | public string Field1 { get; set; } 11 | 12 | [ConnectionEdgeDestination] 13 | public ModelWith3ConnectionsOther Other { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl.Tests/Models/ModelWith3ConnectionsOther.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl.Tests.Models 4 | { 5 | public class ModelWith3ConnectionsOther 6 | { 7 | [Key] 8 | public string Id { get; set; } 9 | 10 | public string Field1 { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl.Tests/Models/NoneConnectionModel.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl.Tests.Models 4 | { 5 | public class NoneConnectionModel 6 | { 7 | [Key] 8 | public string Id { get; set; } 9 | 10 | public string Field1 { get; set; } 11 | 12 | public int Field2 { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl.Tests/Queries/SearchFilterModelQueryArgumentTests.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.GraphQl.Queries; 2 | using Eklee.Azure.Functions.GraphQl.Repository.Search; 3 | using FastMember; 4 | using Shouldly; 5 | using System; 6 | using System.Linq; 7 | using Xunit; 8 | 9 | namespace Eklee.Azure.Functions.GraphQl.Tests.Queries 10 | { 11 | [Trait(Constants.Category, Constants.UnitTests)] 12 | public class SearchFilterModelQueryArgumentTests 13 | { 14 | [Fact] 15 | public void CanHandleSearchModelFilters() 16 | { 17 | Type t = typeof(SearchModel); 18 | TypeAccessor ta = TypeAccessor.Create(t); 19 | var member = ta.GetMembers().ToList().Single(x => x.Name == "Filters"); 20 | var filtersMemberModel = new ModelMember(null, null, member, false); 21 | 22 | var qa = new SearchFilterModelQueryArgument(); 23 | qa.CanHandle(filtersMemberModel).ShouldBeTrue(); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl.Tests/QueryParameterListExtensionsTests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Shouldly; 3 | using Xunit; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl.Tests 6 | { 7 | public class QueryFoo 8 | { 9 | public string Id { get; set; } 10 | } 11 | 12 | public class QueryParameterListExtensionsTests 13 | { 14 | [Fact] 15 | public void CacheKeyShouldBeGeneratedUsingValuesFromList() 16 | { 17 | var steps = new List 18 | { 19 | new QueryStep 20 | { 21 | QueryParameters = new List 22 | { 23 | new QueryParameter 24 | { 25 | ContextValue = new ContextValue 26 | { 27 | Comparison = Comparisons.Equal, 28 | Values = new List{ "ABB90","CCE5"} 29 | } 30 | } 31 | } 32 | } 33 | }; 34 | 35 | var cacheKey = steps.GetCacheKey(); 36 | cacheKey.ShouldContain("ABB90"); 37 | cacheKey.ShouldContain("CCE5"); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl.Tests/Repository/GraphQlRepositoryExtensionsTests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using Eklee.Azure.Functions.GraphQl.Repository; 4 | using NSubstitute; 5 | using Xunit; 6 | 7 | namespace Eklee.Azure.Functions.GraphQl.Tests.Repository 8 | { 9 | public class BatchAddItem 10 | { 11 | public string Id { get; set; } 12 | public string Name { get; set; } 13 | } 14 | 15 | [Trait(Constants.Category, Constants.UnitTests)] 16 | public class GraphQlRepositoryExtensionsTests 17 | { 18 | [Fact] 19 | public async Task CanBatchAdd() 20 | { 21 | List list = new List 22 | { 23 | new BatchAddItem {Id = "1", Name = "Foo 1"}, 24 | new BatchAddItem {Id = "2", Name = "Foo 2"}, 25 | new BatchAddItem {Id = "3", Name = "Foo 3"} 26 | }; 27 | 28 | var mock = Substitute.For(); 29 | await mock.BatchAddAsync(typeof(BatchAddItem), list, null); 30 | 31 | Received.InOrder(async () => 32 | { 33 | await mock.BatchAddAsync(Arg.Is>(x => x.Count == 3), null); 34 | }); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl.Tests/Repository/InMemory/InMemItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl.Tests.Repository.InMemory 4 | { 5 | public class InMemItem 6 | { 7 | public int IntValue { get; set; } 8 | public string StrValue { get; set; } 9 | 10 | public DateTime DateTimeValue { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl.Tests/Repository/InMemory/InMemoryCompareTestBase.cs: -------------------------------------------------------------------------------- 1 | using FastMember; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl.Tests.Repository.InMemory 6 | { 7 | public abstract class InMemoryCompareTestBase 8 | { 9 | private ModelMember GetModelMember(string name) 10 | { 11 | var type = typeof(InMemItem); 12 | var ta = TypeAccessor.Create(type); 13 | return new ModelMember(type, ta, ta.GetMembers().Single(x => x.Name == name), false); 14 | } 15 | 16 | protected QueryParameter GetQueryParameter(string name, object value, Comparisons comparisons) 17 | { 18 | return new QueryParameter 19 | { 20 | ContextValue = new ContextValue 21 | { 22 | Comparison = comparisons, 23 | Values = new List { value } 24 | }, 25 | MemberModel = GetModelMember(name) 26 | }; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl.Tests/Repository/Search/Filters/MockItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl.Tests.Repository.Search.Filters 4 | { 5 | public class MockItem 6 | { 7 | public int IntValue { get; set; } 8 | public string StringValue { get; set; } 9 | public DateTime DateValue { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl.Tests/Repository/Search/Filters/StringSearchFilterTests.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.GraphQl.Repository.Search; 2 | using Eklee.Azure.Functions.GraphQl.Repository.Search.Filters; 3 | using FastMember; 4 | using Shouldly; 5 | using System.Linq; 6 | using Xunit; 7 | 8 | namespace Eklee.Azure.Functions.GraphQl.Tests.Repository.Search.Filters 9 | { 10 | [Trait(Constants.Category, Constants.UnitTests)] 11 | public class StringSearchFilterTests 12 | { 13 | private readonly MemberSet _members; 14 | public StringSearchFilterTests() 15 | { 16 | _members = TypeAccessor.Create(typeof(MockItem)).GetMembers(); 17 | } 18 | 19 | [Fact] 20 | public void CanHandleString() 21 | { 22 | var filter = new StringSearchFilter(); 23 | filter.CanHandle(Comparisons.Equal, _members.Single(m => m.Name == "StringValue")).ShouldBeTrue(); 24 | } 25 | 26 | [Fact] 27 | public void CannotHandleInt() 28 | { 29 | var filter = new StringSearchFilter(); 30 | filter.CanHandle(Comparisons.Equal, _members.Single(m => m.Name == "IntValue")).ShouldBeFalse(); 31 | } 32 | 33 | [Fact] 34 | public void CanGenerateEquals() 35 | { 36 | var filter = new StringSearchFilter(); 37 | filter.GetFilter(new SearchFilterModel 38 | { 39 | FieldName = "StringValue", 40 | Comprison = Comparisons.Equal, 41 | Value = "One" 42 | }, _members.Single(m => m.Name == "StringValue")).ShouldNotBeNullOrEmpty(); 43 | } 44 | 45 | [Fact] 46 | public void CanGenerateNotEquals() 47 | { 48 | var filter = new StringSearchFilter(); 49 | filter.GetFilter(new SearchFilterModel 50 | { 51 | FieldName = "StringValue", 52 | Comprison = Comparisons.NotEqual, 53 | Value = "One" 54 | }, _members.Single(m => m.Name == "StringValue")).ShouldNotBeNullOrEmpty(); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl.Tests/Repository/TableStorage/TableStorageRepositoryTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Linq.Expressions; 4 | using System.Threading.Tasks; 5 | using Shouldly; 6 | using Xunit; 7 | 8 | namespace Eklee.Azure.Functions.GraphQl.Tests.Repository.TableStorage 9 | { 10 | [Collection(Constants.TableStorageTests)] 11 | [Trait(Constants.Category, Constants.IntegrationTests)] 12 | public class TableStorageRepositoryTests : TableStorageRepositoryTestsBase 13 | { 14 | [Fact] 15 | public async Task CanHandleEntityTypeWithStringBasedPartition() 16 | { 17 | Expression> expression = x => x.MyStringCategory; 18 | var configurations = GetBaseConfigurations((MemberExpression)expression.Body); 19 | 20 | TableStorageRepository.Configure(typeof(DocumentDbFoo1), configurations); 21 | 22 | const string id = "3"; 23 | 24 | await TableStorageRepository.AddAsync(new DocumentDbFoo1 25 | { 26 | Id = id, 27 | Name = "Foo 1", 28 | MyStringCategory = "cat 1" 29 | }, null); 30 | 31 | await TableStorageRepository.UpdateAsync(new DocumentDbFoo1 32 | { 33 | Id = id, 34 | Name = "Foo 1 v2", 35 | MyStringCategory = "cat 1" 36 | }, null); 37 | 38 | try 39 | { 40 | var item = (await GetByIdAsync(id)).Single(); 41 | 42 | item.Name.ShouldBe("Foo 1 v2"); 43 | } 44 | finally 45 | { 46 | await TableStorageRepository.DeleteAllAsync(null); 47 | } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl.Tests/xunit.runner.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://xunit.net/schema/current/xunit.runner.schema.json", 3 | "parallelizeTestCollections": false 4 | } -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Actions/AutoDateTimeGenerator.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.GraphQl.Attributes; 2 | using Eklee.Azure.Functions.GraphQl.Repository; 3 | using FastMember; 4 | using System; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | 8 | namespace Eklee.Azure.Functions.GraphQl.Actions 9 | { 10 | public class AutoDateTimeGenerator : IModelTransformer 11 | { 12 | public int ExecutionOrder => 0; 13 | 14 | public bool CanHandle(MutationActions action) 15 | { 16 | return action != MutationActions.DeleteAll && 17 | action != MutationActions.Delete; 18 | } 19 | 20 | public Task TransformAsync(object item, TypeAccessor typeAccessor, IGraphRequestContext context) 21 | { 22 | var dateTimeMembers = typeAccessor.GetMembers().Where(x => x.GetAttribute(typeof(AutoDateTimeAttribute), true) != null).ToList(); 23 | 24 | dateTimeMembers.ForEach(member => 25 | { 26 | bool isDateTime = true; ; 27 | bool process = typeAccessor[item, member.Name] is DateTime value && 28 | (value == null || value == DateTime.MinValue); 29 | 30 | if (!process) 31 | { 32 | isDateTime = false; 33 | process = typeAccessor[item, member.Name] is DateTimeOffset value1 && 34 | (value1 == null || value1 == DateTimeOffset.MinValue); 35 | } 36 | 37 | if (process) 38 | { 39 | var att = (AutoDateTimeAttribute)member.GetAttribute(typeof(AutoDateTimeAttribute), true); 40 | 41 | switch (att.AutoDateTimeTypes) 42 | { 43 | case AutoDateTimeTypes.UtcNow: 44 | typeAccessor[item, member.Name] = isDateTime ? DateTime.UtcNow : DateTimeOffset.UtcNow; 45 | 46 | break; 47 | 48 | case AutoDateTimeTypes.UtcToday: 49 | typeAccessor[item, member.Name] = isDateTime ? DateTime.UtcNow.Date : DateTimeOffset.UtcNow.Date; 50 | 51 | break; 52 | } 53 | } 54 | }); 55 | 56 | return Task.CompletedTask; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Actions/AutoIdGenerator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Threading.Tasks; 4 | using Eklee.Azure.Functions.GraphQl.Attributes; 5 | using Eklee.Azure.Functions.GraphQl.Repository; 6 | using FastMember; 7 | 8 | namespace Eklee.Azure.Functions.GraphQl.Actions 9 | { 10 | public class AutoIdGenerator : IModelTransformer 11 | { 12 | public const string Marker = "@"; 13 | 14 | public int ExecutionOrder => 0; 15 | 16 | public bool CanHandle(MutationActions action) 17 | { 18 | return action != MutationActions.DeleteAll && 19 | action != MutationActions.Delete && 20 | action != MutationActions.Update; 21 | } 22 | 23 | public Task TransformAsync(object item, TypeAccessor typeAccessor, IGraphRequestContext context) 24 | { 25 | var autoIdMembers = typeAccessor.GetMembers().Where(x => x.GetAttribute(typeof(AutoIdAttribute), true) != null).ToList(); 26 | if (autoIdMembers.Count > 0) 27 | { 28 | autoIdMembers.ForEach(member => 29 | { 30 | var value = typeAccessor[item, member.Name]; 31 | if (value is string key && key == Marker) 32 | { 33 | typeAccessor[item, member.Name] = Guid.NewGuid().ToString("N"); 34 | 35 | } 36 | }); 37 | } 38 | 39 | return Task.CompletedTask; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Actions/IModelTransformer.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.GraphQl.Repository; 2 | using FastMember; 3 | using System.Collections.Generic; 4 | using System.Threading.Tasks; 5 | 6 | namespace Eklee.Azure.Functions.GraphQl.Actions 7 | { 8 | public class ModelTransformArguments 9 | { 10 | public List Models { get; set; } 11 | public MutationActions Action { get; set; } 12 | public IGraphRequestContext RequestContext { get; set; } 13 | } 14 | 15 | public interface IModelTransformer 16 | { 17 | int ExecutionOrder { get; } 18 | 19 | bool CanHandle(MutationActions action); 20 | 21 | Task TransformAsync(object item, TypeAccessor typeAccessor, IGraphRequestContext context); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Actions/IModelTransformerProvider.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl.Actions 4 | { 5 | public interface IModelTransformerProvider 6 | { 7 | Task TransformAsync(ModelTransformArguments arguments); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Actions/RequestContextValueExtractors/IRequestContextValueExtractor.cs: -------------------------------------------------------------------------------- 1 | using FastMember; 2 | using System.Threading.Tasks; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Actions.RequestContextValueExtractors 5 | { 6 | public interface IRequestContextValueExtractor 7 | { 8 | Task GetValueAsync(IGraphRequestContext graphRequestContext, Member member); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/AssertAction.cs: -------------------------------------------------------------------------------- 1 | namespace Eklee.Azure.Functions.GraphQl 2 | { 3 | /// 4 | /// Related actions that is supported. 5 | /// 6 | public enum AssertAction 7 | { 8 | BatchCreateOrUpdate, 9 | BatchCreate, 10 | Create, 11 | CreateOrUpdate, 12 | Update, 13 | Delete, 14 | DeleteAll 15 | } 16 | } -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Attributes/AutoDateTimeAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl.Attributes 4 | { 5 | public enum AutoDateTimeTypes 6 | { 7 | UtcToday, 8 | UtcNow 9 | } 10 | 11 | public class AutoDateTimeAttribute : Attribute 12 | { 13 | public AutoDateTimeAttribute(AutoDateTimeTypes autoDateTimeTypes) 14 | { 15 | AutoDateTimeTypes = autoDateTimeTypes; 16 | } 17 | 18 | public AutoDateTimeTypes AutoDateTimeTypes { get; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Attributes/AutoIdAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl.Attributes 4 | { 5 | public class AutoIdAttribute : Attribute 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Attributes/ModelFieldAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl.Attributes 4 | { 5 | public class ModelFieldAttribute : Attribute 6 | { 7 | public bool IsRequired { get; } 8 | public bool UseNullWhenOptional { get; } 9 | 10 | public ModelFieldAttribute(bool isRequired, bool useNullWhenOptional = false) 11 | { 12 | IsRequired = isRequired; 13 | UseNullWhenOptional = useNullWhenOptional; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Attributes/PartitionKeyAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl.Attributes 4 | { 5 | public class PartitionKeyAttribute : Attribute 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Attributes/RequestContextValueAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl.Attributes 4 | { 5 | public class RequestContextValueAttribute : Attribute 6 | { 7 | public RequestContextValueAttribute(Type type) 8 | { 9 | Type = type; 10 | } 11 | 12 | public Type Type { get; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Comparisons.cs: -------------------------------------------------------------------------------- 1 | namespace Eklee.Azure.Functions.GraphQl 2 | { 3 | public enum Comparisons 4 | { 5 | Equal, 6 | StringStartsWith, 7 | StringEndsWith, 8 | StringContains, 9 | NotEqual, 10 | GreaterThan, 11 | GreaterEqualThan, 12 | LessThan, 13 | LessEqualThan 14 | } 15 | } -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Connections/ConnectionAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl.Connections 4 | { 5 | public class ConnectionAttribute : Attribute 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Connections/ConnectionEdge.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.ComponentModel.DataAnnotations; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl.Connections 6 | { 7 | public class ConnectionEdge 8 | { 9 | [Key] 10 | [Description("Id of ConnectionEdge.")] 11 | public string Id { get; set; } 12 | 13 | [Description("The source entity's field name.")] 14 | public string SourceFieldName { get; set; } 15 | 16 | [Description("The source entity's type.")] 17 | public string SourceType { get; set; } 18 | 19 | [Description("The source entity's Id.")] 20 | public string SourceId { get; set; } 21 | 22 | [Description("The destination entity's Id.")] 23 | public string DestinationId { get; set; } 24 | 25 | [Description("The destination field name.")] 26 | [Obsolete("This is no longer required. It remains for backwards compatibility.")] 27 | public string DestinationFieldName { get; set; } 28 | 29 | [Description("The stored object as JSON.")] 30 | public string MetaValue { get; set; } 31 | 32 | [Description("The stored object's type.")] 33 | public string MetaType { get; set; } 34 | 35 | [Description("The stored object's field name.")] 36 | public string MetaFieldName { get; set; } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Connections/ConnectionEdgeDestinationAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl.Connections 4 | { 5 | public class ConnectionEdgeDestinationAttribute : Attribute 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Connections/ConnectionEdgeDestinationFilter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Connections 5 | { 6 | public class ConnectionEdgeDestinationFilter 7 | { 8 | public string Type { get; set; } 9 | 10 | public ModelMember ModelMember { get; set; } 11 | 12 | public Func> Mapper { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Connections/ConnectionEdgeDestinationKeyAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl.Connections 4 | { 5 | public class ConnectionEdgeDestinationKeyAttribute : Attribute 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Connections/ConnectionEdgeQueryParameter.cs: -------------------------------------------------------------------------------- 1 | namespace Eklee.Azure.Functions.GraphQl.Connections 2 | { 3 | public class ConnectionEdgeQueryParameter 4 | { 5 | public string SourceId { get; set; } 6 | 7 | public string SourceFieldName { get; set; } 8 | 9 | public string SourceType { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Connections/IConnectionEdgeHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Connections 5 | { 6 | public interface IConnectionEdgeHandler 7 | { 8 | Task DeleteAllEdgeConnectionsOfType(IGraphRequestContext graphRequestContext); 9 | Task RemoveEdgeConnections(object item, IGraphRequestContext graphRequestContext); 10 | Task QueryAsync(List results, QueryStep queryStep, 11 | IGraphRequestContext graphRequestContext, 12 | QueryExecutionContext queryExecutionContext, 13 | List connectionEdgeDestinationFilters); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Connections/IConnectionEdgeResolver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Connections 5 | { 6 | public interface IConnectionEdgeResolver 7 | { 8 | List HandleConnectionEdges(List items, Action entityAction); 9 | List ListConnectionEdgeQueryParameter(IEnumerable items); 10 | List HandleConnectionEdges(TSource item, Action childAction); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Connections/InternalConnectionEdgeState.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Connections 5 | { 6 | public class InternalConnectionEdgeState 7 | { 8 | private readonly List _list = new List(); 9 | 10 | private readonly Action _entityAction; 11 | 12 | public InternalConnectionEdgeState(Action entityAction) 13 | { 14 | _entityAction = entityAction; 15 | } 16 | 17 | public void InvokeAction(object item, string id, string type) 18 | { 19 | string key = $"{type}{id}"; 20 | 21 | if (_list.IndexOf(key) == -1) 22 | { 23 | _list.Add(key); 24 | _entityAction?.Invoke(item); 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/ContextValue.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl 5 | { 6 | public class SelectValue 7 | { 8 | public string FieldName { get; set; } 9 | 10 | public List SelectValues { get; set; } 11 | } 12 | 13 | public class ContextValue 14 | { 15 | public List Values { get; set; } 16 | 17 | public object GetFirstValue() 18 | { 19 | return Values.First(); 20 | } 21 | 22 | public bool IsSingleValue() 23 | { 24 | return Values.Count == 1; 25 | } 26 | 27 | public bool IsMultipleValues() 28 | { 29 | return Values.Count > 1; 30 | } 31 | 32 | public Comparisons? Comparison { get; set; } 33 | 34 | public List SelectValues { get; set; } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/ContextValueSetRule.cs: -------------------------------------------------------------------------------- 1 | namespace Eklee.Azure.Functions.GraphQl 2 | { 3 | /// 4 | /// ContextValueSetRule class. 5 | /// 6 | /// This class is used to provide support for behavioral settings for how we configure ContextValue. 7 | public class ContextValueSetRule 8 | { 9 | /// 10 | /// The current behavior is to attempt to set the sub fields of the GraphQL query into the ContextValue's Values properties so we can attempt to leverage it in ConnectionEdge for selecting into deeper query results. Setting this behavior to true disables that. This setting is used internally. 11 | /// 12 | public bool DisableSetSelectValues { get; set; } 13 | 14 | /// 15 | /// The current behavior is to choose the first query parameter to populate context value with. This forces us to choose the specific query parameter when it is not the first parameter. 16 | /// 17 | public bool PopulateWithQueryValues { get; set; } 18 | 19 | /// 20 | /// Force an empty context value to be created. 21 | /// 22 | public bool ForceCreateContextValueIfNull { get; set; } 23 | } 24 | } -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Eklee.Azure.Functions.GraphQl.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.1 5 | 0.0.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Eklee.Azure.Functions.GraphQl.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Eklee.Azure.Functions.GraphQl 5 | 0.0.0.0 6 | Eklee.Azure.Functions.GraphQl 7 | Eng Keong David Lee 8 | Eng Keong David Lee 9 | LICENSE.txt 10 | https://github.com/seekdavidlee/Eklee-Azure-Functions-GraphQl 11 | false 12 | Implement one or more Serverless GraphQL API(s) using Azure Functions, Azure Cosmos DB, Azure Search, Azure Table Storage etc. 13 | Fixed additional issues related to nullable types, support null for doing a query in optional field. 14 | GraphQL, Azure, Functions, Caching, .NET, Graph, CosmosDB, DocumentDB, Search, Table, Paging 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/ExecutionErrorResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl 4 | { 5 | public class ExecutionErrorResponse 6 | { 7 | public string Code { get; set; } 8 | public string Message { get; set; } 9 | public Exception InnerException { get; set; } 10 | } 11 | } -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/ExecutionResultResponse.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl 4 | { 5 | public class ExecutionResultResponse 6 | { 7 | public object Data { get; set; } 8 | 9 | public List Errors { get; set; } 10 | 11 | public Dictionary Extensions { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/ExecutionResultResponseExtension.cs: -------------------------------------------------------------------------------- 1 | using GraphQL; 2 | using GraphQL.Validation; 3 | using System.Linq; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl 6 | { 7 | public static class ExecutionResultResponseExtension 8 | { 9 | public static ExecutionResultResponse ToExecutionResultResponse(this ExecutionResult executionResult) 10 | { 11 | var response = new ExecutionResultResponse(); 12 | response.Data = executionResult.Data; 13 | 14 | if (executionResult.Errors != null) 15 | { 16 | response.Errors = executionResult.Errors.Select(x => 17 | { 18 | string code = ""; 19 | if (x is ValidationError e) 20 | { 21 | code = e.Number; 22 | } 23 | return new ExecutionErrorResponse { Code = code, Message = x.Message, InnerException = x.InnerException }; 24 | }).ToList(); 25 | } 26 | 27 | response.Extensions = executionResult.Extensions; 28 | return response; 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Filters/BoolFilter.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using Eklee.Azure.Functions.GraphQl.Attributes; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Filters 5 | { 6 | public class BoolFilter 7 | { 8 | [ModelField(false)] 9 | [Description("Equal.")] 10 | public bool Equal { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Filters/DateFilter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using Eklee.Azure.Functions.GraphQl.Attributes; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl.Filters 6 | { 7 | public class DateFilter 8 | { 9 | [ModelField(false)] 10 | [Description("Equal.")] 11 | public DateTime Equal { get; set; } 12 | 13 | [ModelField(false)] 14 | [Description("Not equal.")] 15 | public DateTime NotEqual { get; set; } 16 | 17 | [ModelField(false)] 18 | [Description("Greater than.")] 19 | public DateTime GreaterThan { get; set; } 20 | 21 | [ModelField(false)] 22 | [Description("Greater equal than.")] 23 | public DateTime GreaterEqualThan { get; set; } 24 | 25 | [ModelField(false)] 26 | [Description("Less than.")] 27 | public DateTime LessThan { get; set; } 28 | 29 | [ModelField(false)] 30 | [Description("Less equal than.")] 31 | public DateTime LessEqualThan { get; set; } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Filters/FieldNameValueFilter.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using Eklee.Azure.Functions.GraphQl.Attributes; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Filters 5 | { 6 | public class FieldNameValueFilter 7 | { 8 | [ModelField(false)] 9 | [Description("Field name.")] 10 | public string FieldName { get; set; } 11 | 12 | [ModelField(false)] 13 | [Description("Field value.")] 14 | public string FieldValue { get; set; } 15 | 16 | [ModelField(false)] 17 | [Description("Comparisons.")] 18 | public Comparisons Comparison { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Filters/GuidFilter.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using Eklee.Azure.Functions.GraphQl.Attributes; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Filters 5 | { 6 | public class GuidFilter 7 | { 8 | [ModelField(false)] 9 | [Description("Equal.")] 10 | public string Equal { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Filters/IntFilter.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using Eklee.Azure.Functions.GraphQl.Attributes; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Filters 5 | { 6 | public class IntFilter 7 | { 8 | [ModelField(false)] 9 | [Description("Equal.")] 10 | public int Equal { get; set; } 11 | 12 | [ModelField(false)] 13 | [Description("Not equal.")] 14 | public int NotEqual { get; set; } 15 | 16 | [ModelField(false)] 17 | [Description("Greater than.")] 18 | public int GreaterThan { get; set; } 19 | 20 | [ModelField(false)] 21 | [Description("Greater equal than.")] 22 | public int GreaterEqualThan { get; set; } 23 | 24 | [ModelField(false)] 25 | [Description("Less than.")] 26 | public int LessThan { get; set; } 27 | 28 | [ModelField(false)] 29 | [Description("Less equal than.")] 30 | public int LessEqualThan { get; set; } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Filters/StringEqualFilter.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using Eklee.Azure.Functions.GraphQl.Attributes; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Filters 5 | { 6 | public class StringEqualFilter 7 | { 8 | [ModelField(false)] 9 | [Description("String equal.")] 10 | public string Equal { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Filters/StringFilter.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using Eklee.Azure.Functions.GraphQl.Attributes; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Filters 5 | { 6 | public class StringFilter 7 | { 8 | [ModelField(false)] 9 | [Description("String equal.")] 10 | public string Equal { get; set; } 11 | 12 | [ModelField(false)] 13 | [Description("String starts with.")] 14 | public string StartsWith { get; set; } 15 | 16 | [ModelField(false)] 17 | [Description("String ends with.")] 18 | public string EndsWith { get; set; } 19 | 20 | [ModelField(false)] 21 | [Description("String contains.")] 22 | public string Contains { get; set; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/GraphDependencyResolver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Autofac; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl 5 | { 6 | public class GraphDependencyResolver : IServiceProvider 7 | { 8 | private readonly IComponentContext _componentContext; 9 | 10 | public GraphDependencyResolver(IComponentContext componentContext) 11 | { 12 | _componentContext = componentContext; 13 | } 14 | 15 | public object GetService(Type serviceType) 16 | { 17 | return _componentContext.Resolve(serviceType); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/GraphQlDomainRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Eklee.Azure.Functions.GraphQl 2 | { 3 | public class GraphQlDomainRequest 4 | { 5 | public string OperationName { get; set; } 6 | 7 | public string Query { get; set; } 8 | 9 | public object Variables { get; set; } 10 | 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/GraphRequestContext.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.Http; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl 4 | { 5 | public class GraphRequestContext : IGraphRequestContext 6 | { 7 | public IHttpRequestContext HttpRequest { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/IGraphQlDomain.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl 4 | { 5 | public interface IGraphQlDomain 6 | { 7 | Task ExecuteAsync(GraphQlDomainRequest graphQlDomainRequest); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/IGraphRequestContext.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.Http; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl 4 | { 5 | public interface IGraphRequestContext 6 | { 7 | IHttpRequestContext HttpRequest { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/IModelConventionInputBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Eklee.Azure.Functions.GraphQl.Repository.DocumentDb; 3 | using Eklee.Azure.Functions.GraphQl.Repository.Http; 4 | using Eklee.Azure.Functions.GraphQl.Repository.InMemory; 5 | 6 | namespace Eklee.Azure.Functions.GraphQl 7 | { 8 | public interface IModelConventionInputBuilder where TSource : class 9 | { 10 | InMemoryConfiguration ConfigureInMemory(); 11 | HttpConfiguration ConfigureHttp(); 12 | DocumentDbConfiguration ConfigureDocumentDb(); 13 | 14 | ModelConventionInputBuilder Delete( 15 | Func mapDelete, 16 | Func transform); 17 | 18 | ModelConventionInputBuilder DeleteAll(Func getOutput); 19 | 20 | void Build(); 21 | } 22 | } -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/IQueryArgumentsBuilder.cs: -------------------------------------------------------------------------------- 1 | using GraphQL.Types; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl 4 | { 5 | public interface IQueryArgumentsBuilder 6 | { 7 | QueryArguments BuildNonNull(string sourceName); 8 | QueryArguments BuildList(string sourceName); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/InputBuilderFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Eklee.Azure.Functions.GraphQl.Repository; 3 | using Eklee.Azure.Functions.GraphQl.Repository.Search; 4 | using GraphQL.Types; 5 | using Microsoft.Extensions.Logging; 6 | 7 | namespace Eklee.Azure.Functions.GraphQl 8 | { 9 | public class InputBuilderFactory 10 | { 11 | private readonly IGraphQlRepositoryProvider _graphQlRepositoryProvider; 12 | private readonly ILogger _logger; 13 | private readonly ISearchMappedModels _searchMappedModels; 14 | private readonly IQueryArgumentsBuilder _queryArgumentsBuilder; 15 | private readonly IFieldMutationResolver _fieldMutationResolver; 16 | 17 | public InputBuilderFactory( 18 | IGraphQlRepositoryProvider graphQlRepositoryProvider, 19 | ILogger logger, 20 | ISearchMappedModels searchMappedModels, 21 | IQueryArgumentsBuilder queryArgumentsBuilder, 22 | IFieldMutationResolver fieldMutationResolver) 23 | { 24 | _graphQlRepositoryProvider = graphQlRepositoryProvider; 25 | _logger = logger; 26 | _searchMappedModels = searchMappedModels; 27 | _queryArgumentsBuilder = queryArgumentsBuilder; 28 | _fieldMutationResolver = fieldMutationResolver; 29 | } 30 | 31 | public ModelConventionInputBuilder Create(ObjectGraphType objectGraphType) where TSource : class 32 | { 33 | try 34 | { 35 | _logger.LogInformation($"Creating model meta data for {typeof(TSource)}."); 36 | 37 | return new ModelConventionInputBuilder( 38 | objectGraphType, 39 | _graphQlRepositoryProvider, 40 | _searchMappedModels, 41 | _queryArgumentsBuilder, 42 | _fieldMutationResolver); 43 | } 44 | catch (Exception e) 45 | { 46 | _logger.LogError(e, $"An error has occured while creating model meta data for {typeof(TSource)}."); 47 | throw; 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/JwtConfigParameters.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.Http; 2 | using Microsoft.Extensions.Configuration; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl 5 | { 6 | public class JwtConfigParameters : IJwtTokenValidatorParameters 7 | { 8 | public JwtConfigParameters(IConfiguration configuration) 9 | { 10 | Audience = configuration["Security:Audience"]; 11 | 12 | var issuers = configuration["Security:Issuers"]; 13 | 14 | if (!string.IsNullOrEmpty(issuers)) 15 | { 16 | Issuers = issuers.Split(' '); 17 | } 18 | else 19 | { 20 | Issuers = new string[] { }; 21 | } 22 | } 23 | 24 | public string Audience { get; } 25 | public string[] Issuers { get; } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/MapperQueryExecutionContext.cs: -------------------------------------------------------------------------------- 1 | namespace Eklee.Azure.Functions.GraphQl 2 | { 3 | public class MapperQueryExecutionContext 4 | { 5 | public MapperQueryExecutionContext(QueryExecutionContext context, QueryStep queryStep) 6 | { 7 | Context = context; 8 | QueryStep = queryStep; 9 | } 10 | 11 | public QueryExecutionContext Context { get; } 12 | public QueryStep QueryStep { get; } 13 | } 14 | } -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/ModelConventionInputType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using GraphQL.Types; 3 | using Microsoft.Extensions.Logging; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl 6 | { 7 | public class ModelConventionInputType : InputObjectGraphType 8 | { 9 | public ModelConventionInputType(ILogger logger) 10 | { 11 | try 12 | { 13 | logger.LogInformation($"Creating input fields meta data for {typeof(TSourceType).FullName}"); 14 | this.AddFields(); 15 | } 16 | catch (Exception e) 17 | { 18 | logger.LogError(e, $"An error has occured while creating input fields meta data for {typeof(TSourceType).FullName}."); 19 | throw; 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/ModelConventionType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using GraphQL.Types; 3 | using Microsoft.Extensions.Logging; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl 6 | { 7 | public class ModelConventionType : ObjectGraphType 8 | { 9 | public ModelConventionType(ILogger logger) 10 | { 11 | try 12 | { 13 | logger.LogInformation($"Creating fields meta data for {typeof(TSourceType).FullName}"); 14 | this.AddFields(); 15 | } 16 | catch (Exception e) 17 | { 18 | logger.LogError(e, $"An error has occured while creating fields meta data for {typeof(TSourceType).FullName}."); 19 | throw; 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/ModelEnumConventionType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Reflection; 6 | using FastMember; 7 | using GraphQL.Types; 8 | 9 | namespace Eklee.Azure.Functions.GraphQl 10 | { 11 | public class ModelEnumConventionType : EnumerationGraphType 12 | { 13 | public ModelEnumConventionType() 14 | { 15 | var type = typeof(T); 16 | Name = type.Name.ToLower(); 17 | 18 | if (type.GetCustomAttribute(typeof(DescriptionAttribute), false) is DescriptionAttribute desc) 19 | { 20 | Description = desc.Description; 21 | } 22 | 23 | foreach (int val in Enum.GetValues(type)) 24 | { 25 | var memInfo = type.GetMember(type.GetEnumName(val))[0]; 26 | var descriptionAttribute = memInfo 27 | .GetCustomAttributes(typeof(DescriptionAttribute), false) 28 | .FirstOrDefault() as DescriptionAttribute; 29 | 30 | AddValue(memInfo.Name.ToLower(), 31 | descriptionAttribute != null ? descriptionAttribute.Description : "", val); 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/ModelMember.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using FastMember; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl 5 | { 6 | public class ModelMember 7 | { 8 | public ModelMember(Type sourceType, TypeAccessor typeAccessor, Member member, bool isOptional) 9 | { 10 | TypeAccessor = typeAccessor; 11 | Member = member; 12 | IsOptional = isOptional; 13 | SourceType = sourceType; 14 | } 15 | 16 | public bool IsOptional { get; } 17 | 18 | public TypeAccessor TypeAccessor { get; } 19 | 20 | public Member Member { get; } 21 | 22 | public string Name => Member.Name.ToLower(); 23 | 24 | public string Description => Member.GetDescription(); 25 | 26 | public bool IsString => Member.Type == typeof(string); 27 | public bool IsInt => Member.Type == typeof(int); 28 | public bool IsDate => Member.Type == typeof(DateTime) || Member.Type == typeof(DateTimeOffset); 29 | public bool IsBool => Member.Type == typeof(bool); 30 | public bool IsGuid => Member.Type == typeof(Guid); 31 | 32 | public Type SourceType { get; } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/ModelType.cs: -------------------------------------------------------------------------------- 1 | using FastMember; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | 6 | namespace Eklee.Azure.Functions.GraphQl 7 | { 8 | public class ModelType 9 | { 10 | private readonly TypeAccessor _typeAccessor; 11 | private readonly List _members; 12 | public string Name { get; } 13 | 14 | public ModelType() 15 | { 16 | var type = typeof(TSourceType); 17 | _typeAccessor = TypeAccessor.Create(type); 18 | _members = _typeAccessor.GetMembers().ToList(); 19 | Name = type.Name; 20 | } 21 | 22 | public void ForEach(Action memberAction) 23 | { 24 | _members.ForEach(memberAction); 25 | } 26 | 27 | public TypeAccessor GetTypeAccessor() 28 | { 29 | return _typeAccessor; 30 | } 31 | 32 | public Member GetMember(string name) 33 | { 34 | return _members.Single(x => x.Name.ToLower() == name.ToLower()); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/ObjectCacheResult.cs: -------------------------------------------------------------------------------- 1 | namespace Eklee.Azure.Functions.GraphQl 2 | { 3 | public class ObjectCacheResult 4 | { 5 | public ObjectCacheResult(T value, bool isFromCache) 6 | { 7 | Value = value; 8 | IsFromCache = isFromCache; 9 | 10 | } 11 | public bool IsFromCache { get; } 12 | public T Value { get; } 13 | } 14 | } -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Queries/BoolQueryArgument.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Eklee.Azure.Functions.GraphQl.Filters; 3 | using GraphQL.Builders; 4 | using GraphQL.Types; 5 | 6 | namespace Eklee.Azure.Functions.GraphQl.Queries 7 | { 8 | public class BoolQueryArgument : IModelMemberQueryArgument 9 | { 10 | public bool CanHandle(ModelMember modelMember) 11 | { 12 | return modelMember.IsBool; 13 | } 14 | 15 | private QueryArgument GetArgument(ModelMember modelMember) 16 | { 17 | return modelMember.IsOptional ? 18 | (QueryArgument)new QueryArgument> 19 | { 20 | Name = modelMember.Name, 21 | Description = modelMember.Description 22 | } : 23 | new QueryArgument>> 24 | { 25 | Name = modelMember.Name, 26 | Description = modelMember.Description 27 | }; 28 | } 29 | 30 | private ConnectionBuilder GetConnectionBuilderArgument(ModelMember modelMember, ConnectionBuilder connectionBuilder) 31 | { 32 | return modelMember.IsOptional ? 33 | connectionBuilder.Argument>(modelMember.Name, modelMember.Description) : 34 | connectionBuilder.Argument>>(modelMember.Name, modelMember.Description); 35 | } 36 | 37 | public IEnumerable GetArguments(ModelMember modelMember) 38 | { 39 | return new List { GetArgument(modelMember) }; 40 | } 41 | 42 | public IEnumerable> GetConnectionBuilderArguments( 43 | ModelMember modelMember, 44 | ConnectionBuilder connectionBuilder) 45 | { 46 | return new List> { GetConnectionBuilderArgument(modelMember, connectionBuilder) }; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Queries/Constants.cs: -------------------------------------------------------------------------------- 1 | namespace Eklee.Azure.Functions.GraphQl.Queries 2 | { 3 | public static class Constants 4 | { 5 | public const string FieldName = "fieldName"; 6 | public const string FieldValue = "fieldValue"; 7 | 8 | public const string LessEqualThan = "lessEqualThan"; 9 | public const string LessThan = "lessThan"; 10 | public const string GreaterEqualThan = "greaterEqualThan"; 11 | public const string GreaterThan = "greaterThan"; 12 | public const string NotEqual = "notEqual"; 13 | public const string EndsWith = "endsWith"; 14 | public const string StartsWith = "startsWith"; 15 | public const string Contains = "contains"; 16 | public const string Equal = "equal"; 17 | 18 | public const string Comparison = "comparison"; 19 | 20 | public const string ODataEqual = "eq"; 21 | public const string ODataNotEqual = "ne"; 22 | public const string ODataGreaterThan = "gt"; 23 | public const string ODataLessThan = "lt"; 24 | public const string ODataGreaterEqualThan = "ge"; 25 | public const string ODataLessEqualThan = "le"; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Queries/DateQueryArgument.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.GraphQl.Filters; 2 | using GraphQL.Builders; 3 | using GraphQL.Types; 4 | using System.Collections.Generic; 5 | 6 | namespace Eklee.Azure.Functions.GraphQl.Queries 7 | { 8 | public class DateQueryArgument : IModelMemberQueryArgument 9 | { 10 | public bool CanHandle(ModelMember modelMember) 11 | { 12 | return modelMember.IsDate; 13 | } 14 | 15 | private QueryArgument GetArgument(ModelMember modelMember) 16 | { 17 | return modelMember.IsOptional ? 18 | (QueryArgument)new QueryArgument> 19 | { 20 | Name = modelMember.Name, 21 | Description = modelMember.Description 22 | } : new QueryArgument>> 23 | { 24 | Name = modelMember.Name, 25 | Description = modelMember.Description 26 | }; 27 | } 28 | 29 | private ConnectionBuilder GetConnectionBuilderArgument(ModelMember modelMember, ConnectionBuilder connectionBuilder) 30 | { 31 | return modelMember.IsOptional ? 32 | connectionBuilder.Argument>(modelMember.Name, modelMember.Description) : 33 | connectionBuilder.Argument>>(modelMember.Name, modelMember.Description); 34 | } 35 | 36 | public IEnumerable GetArguments(ModelMember modelMember) 37 | { 38 | return new List { GetArgument(modelMember) }; 39 | } 40 | 41 | public IEnumerable> GetConnectionBuilderArguments( 42 | ModelMember modelMember, 43 | ConnectionBuilder connectionBuilder) 44 | { 45 | return new List> { GetConnectionBuilderArgument(modelMember, connectionBuilder) }; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Queries/GuidQueryArgument.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.GraphQl.Filters; 2 | using GraphQL.Builders; 3 | using GraphQL.Types; 4 | using System.Collections.Generic; 5 | 6 | namespace Eklee.Azure.Functions.GraphQl.Queries 7 | { 8 | public class GuidQueryArgument : IModelMemberQueryArgument 9 | { 10 | public bool CanHandle(ModelMember modelMember) 11 | { 12 | return modelMember.IsGuid; 13 | } 14 | 15 | private QueryArgument GetArgument(ModelMember modelMember) 16 | { 17 | return modelMember.IsOptional ? 18 | (QueryArgument)new QueryArgument> 19 | { 20 | Name = modelMember.Name, 21 | Description = modelMember.Description 22 | } : 23 | new QueryArgument>> 24 | { 25 | Name = modelMember.Name, 26 | Description = modelMember.Description 27 | }; 28 | } 29 | 30 | private ConnectionBuilder GetConnectionBuilderArgument(ModelMember modelMember, ConnectionBuilder connectionBuilder) 31 | { 32 | return modelMember.IsOptional ? 33 | connectionBuilder.Argument>(modelMember.Name, modelMember.Description) : 34 | connectionBuilder.Argument>>(modelMember.Name, modelMember.Description); 35 | } 36 | 37 | public IEnumerable GetArguments(ModelMember modelMember) 38 | { 39 | return new List { GetArgument(modelMember) }; 40 | } 41 | 42 | public IEnumerable> GetConnectionBuilderArguments( 43 | ModelMember modelMember, 44 | ConnectionBuilder connectionBuilder) 45 | { 46 | return new List> { GetConnectionBuilderArgument(modelMember, connectionBuilder) }; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Queries/IContextValueResolver.cs: -------------------------------------------------------------------------------- 1 | using GraphQL; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl.Queries 4 | { 5 | public interface IContextValueResolver 6 | { 7 | ContextValue GetContextValue(IResolveFieldContext context, ModelMember modelMember, ContextValueSetRule rule); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Queries/IModelMemberQueryArgument.cs: -------------------------------------------------------------------------------- 1 | using GraphQL.Builders; 2 | using GraphQL.Types; 3 | using System.Collections.Generic; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl.Queries 6 | { 7 | public interface IModelMemberQueryArgument 8 | { 9 | bool CanHandle(ModelMember modelMember); 10 | 11 | IEnumerable GetArguments(ModelMember modelMember); 12 | 13 | IEnumerable> GetConnectionBuilderArguments( 14 | ModelMember modelMember, 15 | ConnectionBuilder connectionBuilder); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Queries/IModelMemberQueryArgumentProvider.cs: -------------------------------------------------------------------------------- 1 | using GraphQL.Builders; 2 | using GraphQL.Types; 3 | using System.Collections.Generic; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl.Queries 6 | { 7 | public interface IModelMemberQueryArgumentProvider 8 | { 9 | QueryArguments GetQueryArguments(IEnumerable modelMembers); 10 | 11 | void PopulateConnectionBuilder( 12 | ConnectionBuilder connectionBuilder, 13 | IEnumerable modelMembers); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Queries/IntQueryArgument.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Eklee.Azure.Functions.GraphQl.Filters; 3 | using GraphQL.Builders; 4 | using GraphQL.Types; 5 | 6 | namespace Eklee.Azure.Functions.GraphQl.Queries 7 | { 8 | public class IntQueryArgument : IModelMemberQueryArgument 9 | { 10 | public bool CanHandle(ModelMember modelMember) 11 | { 12 | return modelMember.IsInt; 13 | } 14 | 15 | private QueryArgument GetArgument(ModelMember modelMember) 16 | { 17 | return modelMember.IsOptional ? 18 | (QueryArgument)new QueryArgument> 19 | { 20 | Name = modelMember.Name, 21 | Description = modelMember.Description 22 | } : 23 | new QueryArgument>> 24 | { 25 | Name = modelMember.Name, 26 | Description = modelMember.Description 27 | }; 28 | } 29 | 30 | public IEnumerable GetArguments(ModelMember modelMember) 31 | { 32 | return new List { GetArgument(modelMember) }; 33 | } 34 | 35 | public ConnectionBuilder GetConnectionBuilderArgument(ModelMember modelMember, ConnectionBuilder connectionBuilder) 36 | { 37 | return modelMember.IsOptional ? 38 | connectionBuilder.Argument>(modelMember.Name, modelMember.Description) : 39 | connectionBuilder.Argument>>(modelMember.Name, modelMember.Description); 40 | } 41 | 42 | public IEnumerable> GetConnectionBuilderArguments( 43 | ModelMember modelMember, 44 | ConnectionBuilder connectionBuilder) 45 | { 46 | return new List> { GetConnectionBuilderArgument(modelMember, connectionBuilder) }; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Queries/ModelMemberQueryArgumentProvider.cs: -------------------------------------------------------------------------------- 1 | using GraphQL.Builders; 2 | using GraphQL.Types; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | 7 | namespace Eklee.Azure.Functions.GraphQl.Queries 8 | { 9 | public class ModelMemberQueryArgumentProvider : IModelMemberQueryArgumentProvider 10 | { 11 | private readonly List _modelMemberQueryArguments; 12 | 13 | public ModelMemberQueryArgumentProvider(IEnumerable modelMemberQueryArguments) 14 | { 15 | _modelMemberQueryArguments = modelMemberQueryArguments.ToList(); 16 | } 17 | 18 | public QueryArguments GetQueryArguments(IEnumerable modelMembers) 19 | { 20 | var list = new List(); 21 | 22 | modelMembers.ToList().ForEach(m => 23 | { 24 | var handler = _modelMemberQueryArguments.SingleOrDefault(qa => qa.CanHandle(m)); 25 | 26 | if (handler == null) 27 | throw new NotImplementedException($"QueryArgument type is not yet implemented for {m.Name}"); 28 | 29 | list.AddRange(handler.GetArguments(m)); 30 | }); 31 | 32 | return new QueryArguments(list); 33 | } 34 | 35 | public void PopulateConnectionBuilder( 36 | ConnectionBuilder connectionBuilder, 37 | IEnumerable modelMembers) 38 | { 39 | modelMembers.ToList().ForEach(m => 40 | { 41 | var handler = _modelMemberQueryArguments.SingleOrDefault(qa => qa.CanHandle(m)); 42 | 43 | if (handler == null) 44 | throw new NotImplementedException($"QueryArgument type is not yet implemented for {m.Name}"); 45 | 46 | handler.GetConnectionBuilderArguments(m, connectionBuilder) 47 | .ToList() 48 | .ForEach(arg => connectionBuilder = arg); 49 | }); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Queries/SearchFilterModelQueryArgument.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.GraphQl.Filters; 2 | using Eklee.Azure.Functions.GraphQl.Repository.Search; 3 | using GraphQL.Builders; 4 | using GraphQL.Types; 5 | using System.Collections.Generic; 6 | 7 | namespace Eklee.Azure.Functions.GraphQl.Queries 8 | { 9 | public class SearchFilterModelQueryArgument : IModelMemberQueryArgument 10 | { 11 | public bool CanHandle(ModelMember modelMember) 12 | { 13 | return modelMember.Member.Type == typeof(List); 14 | } 15 | 16 | public IEnumerable GetArguments(ModelMember modelMember) 17 | { 18 | return new List 19 | { 20 | new QueryArgument>> 21 | { 22 | Name = modelMember.Name, 23 | Description = modelMember.Description 24 | } 25 | }; 26 | } 27 | 28 | public IEnumerable> GetConnectionBuilderArguments(ModelMember modelMember, ConnectionBuilder connectionBuilder) 29 | { 30 | throw new System.NotImplementedException(); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/QueryArgumentsBuilder.cs: -------------------------------------------------------------------------------- 1 | using GraphQL.Types; 2 | using System.Collections.Generic; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl 5 | { 6 | public class QueryArgumentsBuilder : IQueryArgumentsBuilder 7 | { 8 | public QueryArgumentsBuilder() 9 | { 10 | 11 | } 12 | 13 | public QueryArguments BuildNonNull(string sourceName) 14 | { 15 | var args = new List(); 16 | args.Add(new QueryArgument>> { Name = sourceName }); 17 | return new QueryArguments(args); 18 | } 19 | 20 | public QueryArguments BuildList(string sourceName) 21 | { 22 | var args = new List(); 23 | args.Add(new QueryArgument>> { Name = sourceName }); 24 | return new QueryArguments(args); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/QueryExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using Eklee.Azure.Functions.GraphQl.Repository.Search; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl 6 | { 7 | public static class QueryExtensions 8 | { 9 | public static List GetTypeList(this List searchResultModels) where T : class 10 | { 11 | return searchResultModels.Select(x => x.Value as T).Where(x => x != null).ToList(); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/QueryOutput.cs: -------------------------------------------------------------------------------- 1 | namespace Eklee.Azure.Functions.GraphQl 2 | { 3 | public enum QueryOutput { Unknown, Single, List } 4 | } -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/QueryParameter.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl 6 | { 7 | /// 8 | /// The QueryParameter class is used to define the parameter to query against any type of supported repository. 9 | /// 10 | public class QueryParameter 11 | { 12 | /// 13 | /// MemberModel keeps information about the particular property we are dealing with as we are querying. 14 | /// 15 | [JsonIgnore] 16 | public ModelMember MemberModel { get; set; } 17 | 18 | /// 19 | /// This is where we set the query value coming from GraphQL input. 20 | /// 21 | public ContextValue ContextValue { get; set; } 22 | 23 | /// 24 | /// This property is used to provide support for behavioral settings for how we configure ContextValue. 25 | /// 26 | public ContextValueSetRule Rule { get; set; } 27 | 28 | /// 29 | /// If set, this allows us to set ContextValue using this mapper func. 30 | /// 31 | [JsonIgnore] 32 | public Func> Mapper { get; set; } 33 | } 34 | 35 | /// 36 | /// This is derived from IGraphRequestContext. 37 | /// 38 | public class RequestContextParameter 39 | { 40 | /// 41 | /// Comparison. 42 | /// 43 | public Comparisons Comparison { get; set; } 44 | 45 | /// 46 | /// Value to compare with. 47 | /// 48 | public object Value { get; set; } 49 | } 50 | } -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/QueryParameterListExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Eklee.Azure.Functions.GraphQl 7 | { 8 | public static class QueryParameterListExtensions 9 | { 10 | public static string GetCacheKey(this List steps) 11 | { 12 | var all = new StringBuilder(typeof(TSource).FullName); 13 | steps.ForEach(list => 14 | { 15 | all.Append(string.Join("_", 16 | list.QueryParameters.Where( 17 | x => x.ContextValue?.Values != null && x.ContextValue.Comparison.HasValue).Select( 18 | x => $"{x.ContextValue.Comparison.Value}{ GetValue(x.ContextValue.Values)}"))); 19 | }); 20 | return all.ToString(); 21 | } 22 | 23 | private static string GetValue(List list) 24 | { 25 | return string.Join("_", list.Select(x => x.ToString())); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/QueryStep.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl 6 | { 7 | public class QueryStep 8 | { 9 | public QueryStep() 10 | { 11 | QueryParameters = new List(); 12 | } 13 | 14 | public DateTime? Started { get; set; } 15 | 16 | public bool SkipConnectionEdgeCheck { get; set; } 17 | 18 | public Type OverrideRepositoryWithType { get; set; } 19 | 20 | [JsonIgnore] 21 | public Action ContextAction { get; set; } 22 | 23 | [JsonIgnore] 24 | public Func> StepMapper { get; set; } 25 | 26 | public List QueryParameters { get; set; } 27 | public DateTime? Ended { get; set; } 28 | 29 | [JsonIgnore] 30 | public Dictionary Items { get; set; } 31 | 32 | public List InMemoryFilterQueryParameters { get; set; } 33 | } 34 | } -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/QueryStepExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl 4 | { 5 | public static class QueryStepExtensions 6 | { 7 | /// 8 | /// Specifically used the clone query steps. 9 | /// 10 | /// queryStep. 11 | /// QueryStep 12 | /// Anytime we need to create a clone copy of query steps, this is used because deep knowldge of which property where JsonIgnoreAttribute is only known here. 13 | public static QueryStep CloneQueryStep(this QueryStep queryStep) 14 | { 15 | var clone = queryStep.Clone(); 16 | clone.SkipConnectionEdgeCheck = queryStep.SkipConnectionEdgeCheck; 17 | clone.OverrideRepositoryWithType = queryStep.OverrideRepositoryWithType; 18 | clone.ContextAction = queryStep.ContextAction; 19 | clone.StepMapper = queryStep.StepMapper; 20 | clone.InMemoryFilterQueryParameters = queryStep.InMemoryFilterQueryParameters; 21 | 22 | if (queryStep.Items != null && queryStep.Items.Count > 0) 23 | { 24 | clone.Items = new Dictionary(); 25 | foreach (var key in queryStep.Items.Keys) 26 | { 27 | clone.Items.Add(key, queryStep.Items[key]); 28 | } 29 | } 30 | 31 | // Copy Member Models which are ignored via JsonIgnore. 32 | for (var i = 0; i < queryStep.QueryParameters.Count; i++) 33 | { 34 | var qp = queryStep.QueryParameters[i]; 35 | var cqp = clone.QueryParameters[i]; 36 | 37 | cqp.MemberModel = qp.MemberModel; 38 | 39 | if (qp.Mapper != null) 40 | { 41 | cqp.Mapper = qp.Mapper; 42 | } 43 | } 44 | 45 | return clone; 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/BatchModelList.cs: -------------------------------------------------------------------------------- 1 | using FastMember; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | 6 | namespace Eklee.Azure.Functions.GraphQl.Repository 7 | { 8 | public class BatchModelList 9 | { 10 | private readonly Dictionary _list = new Dictionary(); 11 | private readonly TypeAccessor _typeAccessor; 12 | 13 | /// 14 | /// Constructor for BatchModelList. 15 | /// 16 | /// Type. 17 | public BatchModelList(Type type) 18 | { 19 | _typeAccessor = TypeAccessor.Create(type); 20 | } 21 | 22 | /// 23 | /// Adds a model to the internal list which will check for duplicates. 24 | /// 25 | /// 26 | public void Add(object model) 27 | { 28 | var key = _typeAccessor.GetModelKey(model); 29 | 30 | if (!_list.ContainsKey(key)) 31 | { 32 | _list.Add(key, model); 33 | } 34 | } 35 | 36 | /// 37 | /// Gets a list of non-duplicated models. 38 | /// 39 | public List Items 40 | { 41 | get 42 | { 43 | return _list.Values.ToList(); 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/DocumentDb/DocumentDbComparisonBool.cs: -------------------------------------------------------------------------------- 1 | namespace Eklee.Azure.Functions.GraphQl.Repository.DocumentDb 2 | { 3 | public class DocumentDbComparisonBool : BaseDocumentDbComparison 4 | { 5 | protected override string GetComprisonString(Comparisons comparison, string[] names) 6 | { 7 | if (names.Length == 1 && comparison == Comparisons.Equal) 8 | { 9 | return $" {GetPropertyName()} = {names[0]}"; 10 | } 11 | 12 | return null; 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/DocumentDb/DocumentDbComparisonDate.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl.Repository.DocumentDb 4 | { 5 | public class DocumentDbComparisonDate : BaseDocumentDbComparison 6 | { 7 | protected override bool AssertContextValue(DateTime value) 8 | { 9 | return value != DateTime.MinValue; 10 | } 11 | 12 | protected override string GetComprisonString(Comparisons comparison, string[] names) 13 | { 14 | if (names.Length == 1) 15 | { 16 | var name = names[0]; 17 | 18 | if (comparison == Comparisons.Equal) 19 | return $" {GetPropertyName()} = {name}"; 20 | 21 | if (comparison == Comparisons.NotEqual) 22 | return $" {GetPropertyName()} != {name}"; 23 | 24 | if (comparison == Comparisons.GreaterThan) 25 | return $" {GetPropertyName()} > {name}"; 26 | 27 | if (comparison == Comparisons.GreaterEqualThan) 28 | return $" {GetPropertyName()} >= {name}"; 29 | 30 | if (comparison == Comparisons.LessThan) 31 | return $" {GetPropertyName()} < {name}"; 32 | 33 | if (comparison == Comparisons.LessEqualThan) 34 | return $" {GetPropertyName()} <= {name}"; 35 | } 36 | 37 | return null; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/DocumentDb/DocumentDbComparisonGuid.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl.Repository.DocumentDb 4 | { 5 | public class DocumentDbComparisonGuid : BaseDocumentDbComparison 6 | { 7 | protected override string GetComprisonString(Comparisons comparison, string[] names) 8 | { 9 | if (comparison == Comparisons.Equal) 10 | { 11 | if (names.Length == 1) 12 | { 13 | return $" {GetPropertyName()} = {names[0]}"; 14 | } 15 | 16 | if (names.Length > 1) 17 | { 18 | return $" {GetPropertyName()} in ({string.Join(",", names)})"; 19 | } 20 | } 21 | return null; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/DocumentDb/DocumentDbComparisonInt.cs: -------------------------------------------------------------------------------- 1 | namespace Eklee.Azure.Functions.GraphQl.Repository.DocumentDb 2 | { 3 | public class DocumentDbComparisonInt : BaseDocumentDbComparison 4 | { 5 | protected override bool AssertContextValue(int value) 6 | { 7 | return value != 0; 8 | } 9 | 10 | protected override string GetComprisonString(Comparisons comparison, string[] names) 11 | { 12 | if (comparison == Comparisons.Equal) 13 | { 14 | if (names.Length == 1) 15 | { 16 | return $" {GetPropertyName()} = {names[0]}"; 17 | } 18 | 19 | if (names.Length > 1) 20 | { 21 | return $" {GetPropertyName()} in ({string.Join(",", names)})"; 22 | } 23 | } 24 | 25 | if (names.Length == 1) 26 | { 27 | var name = names[0]; 28 | 29 | if (comparison == Comparisons.NotEqual) 30 | return $" {GetPropertyName()} != {name}"; 31 | 32 | if (comparison == Comparisons.GreaterThan) 33 | return $" {GetPropertyName()} > {name}"; 34 | 35 | if (comparison == Comparisons.GreaterEqualThan) 36 | return $" {GetPropertyName()} >= {name}"; 37 | 38 | if (comparison == Comparisons.LessThan) 39 | return $" {GetPropertyName()} < {name}"; 40 | 41 | if (comparison == Comparisons.LessEqualThan) 42 | return $" {GetPropertyName()} <= {name}"; 43 | } 44 | 45 | return null; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/DocumentDb/DocumentDbComparisonString.cs: -------------------------------------------------------------------------------- 1 | namespace Eklee.Azure.Functions.GraphQl.Repository.DocumentDb 2 | { 3 | public class DocumentDbComparisonString : BaseDocumentDbComparison 4 | { 5 | protected override bool AssertContextValue(string value) 6 | { 7 | return !string.IsNullOrEmpty(value); 8 | } 9 | 10 | protected override string GetComprisonString(Comparisons comparison, string[] names) 11 | { 12 | if (comparison == Comparisons.Equal) 13 | { 14 | if (names.Length == 1) 15 | { 16 | return $" {GetPropertyName()} = {names[0]}"; 17 | } 18 | 19 | if (names.Length > 1) 20 | { 21 | return $" {GetPropertyName()} in ({string.Join(",", names)})"; 22 | } 23 | } 24 | 25 | if (names.Length == 1) 26 | { 27 | var name = names[0]; 28 | 29 | switch (comparison) 30 | { 31 | case Comparisons.StringContains: 32 | return $" CONTAINS({GetPropertyName()}, {name})"; 33 | 34 | case Comparisons.StringStartsWith: 35 | return $" STARTSWITH({GetPropertyName()}, {name})"; 36 | 37 | case Comparisons.StringEndsWith: 38 | return $" ENDSWITH({GetPropertyName()}, {name})"; 39 | 40 | default: 41 | return null; 42 | } 43 | } 44 | 45 | return null; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/DocumentDb/DocumentDbConfigurationExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Repository.DocumentDb 5 | { 6 | public static class DocumentDbConfigurationExtensions 7 | { 8 | public static void Add(this Dictionary configurations, string name, object value) 9 | { 10 | configurations[$"{typeof(TSource).Name}{name}"] = value; 11 | } 12 | 13 | public static T GetValue(this Dictionary configurations, string key, Type sourceType) 14 | { 15 | return (T)configurations[GetKey(key, sourceType)]; 16 | } 17 | 18 | public static bool ContainsKey(this Dictionary configurations, string key) 19 | { 20 | return configurations.ContainsKey(GetKey(key, typeof(TSource))); 21 | } 22 | 23 | 24 | public static string GetStringValue(this Dictionary configurations, string key, Type sourceType) 25 | { 26 | string configKey = GetKey(key, sourceType); 27 | return configurations.ContainsKey(configKey) ? (string)configurations[configKey] : null; 28 | } 29 | 30 | public static string GetKey(string key, Type sourceType) 31 | { 32 | return $"{sourceType.Name}{key}"; 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/DocumentDb/DocumentDbConstants.cs: -------------------------------------------------------------------------------- 1 | namespace Eklee.Azure.Functions.GraphQl.Repository.DocumentDb 2 | { 3 | public static class DocumentDbConstants 4 | { 5 | public const string Url = "Url"; 6 | public const string Key = "Key"; 7 | public const string Database = "Database"; 8 | public const string RequestUnit = "RequestUnit"; 9 | public const string PartitionMemberExpression = "PartitionMemberExpression"; 10 | public const string RequestContextSelector = "RequestContextSelector"; 11 | } 12 | } -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/DocumentDb/DocumentDbExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | using Microsoft.Azure.Documents; 4 | using Microsoft.Azure.Documents.Client; 5 | 6 | namespace Eklee.Azure.Functions.GraphQl.Repository.DocumentDb 7 | { 8 | public static class DocumentDbExtensions 9 | { 10 | private const int MaximumCreateDatabaseRetryCount = 3; 11 | 12 | public static async Task CreateDatabaseIfNotExistsWithRetryAsync( 13 | this DocumentClient documentClient, string databaseId, int requestUnit) 14 | { 15 | int tryCounter = 0; 16 | while (true) 17 | { 18 | try 19 | { 20 | await documentClient.CreateDatabaseIfNotExistsAsync( 21 | new Database { Id = databaseId }, 22 | new RequestOptions { OfferThroughput = requestUnit }); 23 | 24 | break; 25 | } 26 | catch (DocumentClientException e) 27 | { 28 | if (tryCounter < MaximumCreateDatabaseRetryCount && e.Message.Contains("Unknown server error")) 29 | { 30 | tryCounter++; 31 | Thread.Sleep(tryCounter * 500); 32 | } 33 | else 34 | { 35 | throw; 36 | } 37 | } 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/DocumentDb/DocumentDbSqlParameter.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Azure.Documents; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl.Repository.DocumentDb 4 | { 5 | public class DocumentDbSqlParameter 6 | { 7 | public SqlParameter[] SqlParameters { get; set; } 8 | public string Comparison { get; set; } 9 | } 10 | } -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/DocumentDb/IDocumentDbComparison.cs: -------------------------------------------------------------------------------- 1 | namespace Eklee.Azure.Functions.GraphQl.Repository.DocumentDb 2 | { 3 | public interface IDocumentDbComparison 4 | { 5 | bool CanHandle(QueryParameter queryParameter); 6 | DocumentDbSqlParameter Generate(); 7 | } 8 | } -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/Http/HttpConstants.cs: -------------------------------------------------------------------------------- 1 | namespace Eklee.Azure.Functions.GraphQl.Repository.Http 2 | { 3 | public static class HttpConstants 4 | { 5 | public const string BaseUrl = "BaseUrl"; 6 | } 7 | } -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/Http/HttpTypeConfiguration.cs: -------------------------------------------------------------------------------- 1 | namespace Eklee.Azure.Functions.GraphQl.Repository.Http 2 | { 3 | public class HttpTypeConfiguration 4 | { 5 | public string BaseUrl { get; set; } 6 | } 7 | } -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/IGraphQlRepository.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl.Repository 6 | { 7 | public interface IGraphQlRepository 8 | { 9 | void Configure(Type sourceType, Dictionary configurations); 10 | Task BatchAddAsync(IEnumerable items, IGraphRequestContext graphRequestContext) where T : class; 11 | Task BatchAddOrUpdateAsync(IEnumerable items, IGraphRequestContext graphRequestContext) where T : class; 12 | Task AddAsync(T item, IGraphRequestContext graphRequestContext) where T : class; 13 | Task AddOrUpdateAsync(T item, IGraphRequestContext graphRequestContext) where T : class; 14 | Task UpdateAsync(T item, IGraphRequestContext graphRequestContext) where T : class; 15 | Task DeleteAsync(T item, IGraphRequestContext graphRequestContext) where T : class; 16 | Task> QueryAsync(string queryName, IEnumerable queryParameters, Dictionary stepBagItems, IGraphRequestContext graphRequestContext) where T : class; 17 | Task DeleteAllAsync(IGraphRequestContext graphRequestContext) where T : class; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/IGraphQlRepositoryProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl.Repository 6 | { 7 | public interface IGraphQlRepositoryProvider 8 | { 9 | IGraphQlRepository Use() where TRepository : IGraphQlRepository; 10 | Task> QueryAsync(string queryName, QueryStep queryStep, IGraphRequestContext graphRequestContext); 11 | IGraphQlRepository GetRepository(); 12 | IGraphQlRepository GetRepository(Type type); 13 | bool IsRepositoryExist(); 14 | bool IsRepositoryExist(Type type); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/IMutationActionsProvider.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl.Repository 4 | { 5 | public interface IMutationActionsProvider 6 | { 7 | Task HandlePreActions(MutationActionItem mutationActionItem); 8 | 9 | Task HandlePostActions(MutationActionItem mutationActionItem); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/IMutationPostAction.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl.Repository 4 | { 5 | public interface IMutationPostAction 6 | { 7 | Task TryHandlePostItem(MutationActionItem mutationActionItem); 8 | 9 | int ExecutionOrder { get; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/IMutationPreAction.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl.Repository 4 | { 5 | public interface IMutationPreAction 6 | { 7 | Task TryHandlePreItem(MutationActionItem mutationActionItem); 8 | 9 | int ExecutionOrder { get; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/InMemory/IInMemoryCompare.cs: -------------------------------------------------------------------------------- 1 | namespace Eklee.Azure.Functions.GraphQl.Repository.InMemory 2 | { 3 | public interface IInMemoryCompare 4 | { 5 | bool CanHandle(object obj, QueryParameter queryParameter); 6 | bool MeetsCondition(object obj, QueryParameter queryParameter); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/InMemory/IInMemoryComparerProvider.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl.Repository.InMemory 4 | { 5 | public interface IInMemoryComparerProvider 6 | { 7 | List Query(IEnumerable queryParameters, List list); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/InMemory/InMemoryCompareDateTime.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Repository.InMemory 5 | { 6 | public class InMemoryCompareDateTime : IInMemoryCompare 7 | { 8 | public bool CanHandle(object obj, QueryParameter queryParameter) 9 | { 10 | var x = queryParameter.MemberModel.TypeAccessor[obj, queryParameter.MemberModel.Member.Name]; 11 | return x is DateTime && queryParameter.ContextValue.Comparison.HasValue && 12 | queryParameter.ContextValue.GetFirstValue() is DateTime; 13 | } 14 | 15 | public bool MeetsCondition(object obj, QueryParameter queryParameter) 16 | { 17 | DateTime xDateTime = (DateTime)queryParameter.MemberModel.TypeAccessor[obj, queryParameter.MemberModel.Member.Name]; 18 | DateTime ctxValueDateTime = (DateTime)queryParameter.ContextValue.GetFirstValue(); 19 | 20 | switch (queryParameter.ContextValue.Comparison) 21 | { 22 | case Comparisons.Equal: 23 | if (queryParameter.ContextValue.IsSingleValue()) 24 | return xDateTime == ctxValueDateTime; 25 | else 26 | { 27 | return queryParameter.ContextValue.Values.Any(v => (DateTime)v == xDateTime); 28 | } 29 | 30 | case Comparisons.NotEqual: 31 | return xDateTime != ctxValueDateTime; 32 | 33 | case Comparisons.GreaterThan: 34 | return xDateTime > ctxValueDateTime; 35 | 36 | case Comparisons.GreaterEqualThan: 37 | return xDateTime >= ctxValueDateTime; 38 | 39 | case Comparisons.LessThan: 40 | return xDateTime < ctxValueDateTime; 41 | 42 | case Comparisons.LessEqualThan: 43 | return xDateTime <= ctxValueDateTime; 44 | 45 | default: 46 | throw new NotImplementedException($"DateTime comparison {queryParameter.ContextValue.Comparison} is not implemented by InMemoryCompareDateTime."); 47 | } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/InMemory/InMemoryCompareInt.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Repository.InMemory 5 | { 6 | public class InMemoryCompareInt : IInMemoryCompare 7 | { 8 | public bool CanHandle(object obj, QueryParameter queryParameter) 9 | { 10 | var x = queryParameter.MemberModel.TypeAccessor[obj, queryParameter.MemberModel.Member.Name]; 11 | return x is int && queryParameter.ContextValue.Comparison.HasValue && 12 | queryParameter.ContextValue.GetFirstValue() is int; 13 | } 14 | 15 | public bool MeetsCondition(object obj, QueryParameter queryParameter) 16 | { 17 | int xInt = (int)queryParameter.MemberModel.TypeAccessor[obj, queryParameter.MemberModel.Member.Name]; 18 | int ctxValueInt = (int)queryParameter.ContextValue.GetFirstValue(); 19 | 20 | switch (queryParameter.ContextValue.Comparison) 21 | { 22 | case Comparisons.Equal: 23 | if (queryParameter.ContextValue.IsSingleValue()) 24 | return xInt == ctxValueInt; 25 | else 26 | { 27 | return queryParameter.ContextValue.Values.Any(v => (int)v == xInt); 28 | } 29 | 30 | case Comparisons.NotEqual: 31 | return xInt != ctxValueInt; 32 | 33 | case Comparisons.GreaterThan: 34 | return xInt > ctxValueInt; 35 | 36 | case Comparisons.GreaterEqualThan: 37 | return xInt >= ctxValueInt; 38 | 39 | case Comparisons.LessThan: 40 | return xInt < ctxValueInt; 41 | 42 | case Comparisons.LessEqualThan: 43 | return xInt <= ctxValueInt; 44 | 45 | default: 46 | throw new NotImplementedException($"Int comparison {queryParameter.ContextValue.Comparison} is not implemented by InMemoryCompareInt."); 47 | } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/InMemory/InMemoryCompareString.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Repository.InMemory 5 | { 6 | public class InMemoryCompareString : IInMemoryCompare 7 | { 8 | public bool CanHandle(object obj, QueryParameter queryParameter) 9 | { 10 | var x = queryParameter.MemberModel.TypeAccessor[obj, queryParameter.MemberModel.Member.Name]; 11 | return x is string && queryParameter.ContextValue.Comparison.HasValue && 12 | queryParameter.ContextValue.GetFirstValue() is string; 13 | } 14 | 15 | public bool MeetsCondition(object obj, QueryParameter queryParameter) 16 | { 17 | string xStr = (string)queryParameter.MemberModel.TypeAccessor[obj, queryParameter.MemberModel.Member.Name]; 18 | string ctxValueStr = (string)queryParameter.ContextValue.GetFirstValue(); 19 | 20 | switch (queryParameter.ContextValue.Comparison) 21 | { 22 | case Comparisons.Equal: 23 | if (queryParameter.ContextValue.IsSingleValue()) 24 | return xStr == ctxValueStr; 25 | else 26 | { 27 | return queryParameter.ContextValue.Values.Any(v => (string)v == xStr); 28 | } 29 | 30 | case Comparisons.StringContains: 31 | return xStr.Contains(ctxValueStr); 32 | 33 | case Comparisons.StringStartsWith: 34 | return xStr.StartsWith(ctxValueStr); 35 | 36 | case Comparisons.StringEndsWith: 37 | return xStr.EndsWith(ctxValueStr); 38 | 39 | case Comparisons.NotEqual: 40 | return !xStr.Equals(ctxValueStr); 41 | 42 | default: 43 | throw new NotImplementedException($"String comparison {queryParameter.ContextValue.Comparison} is not implemented by InMemoryCompareString."); 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/InMemory/InMemoryComparerProvider.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Repository.InMemory 5 | { 6 | public class InMemoryComparerProvider : IInMemoryComparerProvider 7 | { 8 | private readonly IEnumerable _inMemoryCompares; 9 | 10 | public InMemoryComparerProvider(IEnumerable inMemoryCompares) 11 | { 12 | _inMemoryCompares = inMemoryCompares; 13 | } 14 | 15 | public List Query(IEnumerable queryParameters, List list) 16 | { 17 | var parameters = queryParameters.ToList(); 18 | return list.Where(x => parameters.Count(queryParameter => 19 | { 20 | var comparer = _inMemoryCompares.SingleOrDefault(c => c.CanHandle(x, queryParameter)); 21 | return comparer != null && comparer.MeetsCondition(x, queryParameter); 22 | }) == parameters.Count).ToList(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/InMemory/InMemoryConfiguration.cs: -------------------------------------------------------------------------------- 1 | namespace Eklee.Azure.Functions.GraphQl.Repository.InMemory 2 | { 3 | public class InMemoryConfiguration where TSource : class 4 | { 5 | private readonly ModelConventionInputBuilder _modelConventionInputBuilder; 6 | 7 | public InMemoryConfiguration(ModelConventionInputBuilder modelConventionInputBuilder) 8 | { 9 | _modelConventionInputBuilder = modelConventionInputBuilder; 10 | } 11 | 12 | public ModelConventionInputBuilder BuildInMemory() 13 | { 14 | return _modelConventionInputBuilder; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/MutationActionItem.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl.Repository 4 | { 5 | public class MutationActionItem 6 | { 7 | public TSource Item { get; set; } 8 | public IGraphRequestContext RequestContext { get; set; } 9 | public MutationActions Action { get; set; } 10 | public IGraphQlRepositoryProvider RepositoryProvider { get; set; } 11 | public object ObjectItem { get; set; } 12 | public List Items { get; set; } 13 | public List ObjectItems { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/MutationActions.cs: -------------------------------------------------------------------------------- 1 | namespace Eklee.Azure.Functions.GraphQl.Repository 2 | { 3 | public enum MutationActions 4 | { 5 | BatchCreateOrUpdate, 6 | BatchCreate, 7 | Create, 8 | CreateOrUpdate, 9 | Update, 10 | Delete, 11 | DeleteAll 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/MutationActionsProvider.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Threading.Tasks; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl.Repository 6 | { 7 | public class MutationActionsProvider : IMutationActionsProvider 8 | { 9 | private readonly List _mutationPostActions; 10 | private readonly List _mutationPreActions; 11 | 12 | public MutationActionsProvider( 13 | IEnumerable mutationPostActions, 14 | IEnumerable mutationPreActions) 15 | { 16 | _mutationPostActions = mutationPostActions.OrderBy(x => x.ExecutionOrder).ToList(); 17 | _mutationPreActions = mutationPreActions.OrderBy(x => x.ExecutionOrder).ToList(); 18 | } 19 | 20 | public async Task HandlePostActions(MutationActionItem mutationActionItem) 21 | { 22 | foreach (var action in _mutationPostActions) 23 | { 24 | await action.TryHandlePostItem(mutationActionItem); 25 | } 26 | } 27 | 28 | public async Task HandlePreActions(MutationActionItem mutationActionItem) 29 | { 30 | foreach (var action in _mutationPreActions) 31 | { 32 | await action.TryHandlePreItem(mutationActionItem); 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/Search/Extensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl.Repository.Search 4 | { 5 | public static class Extensions 6 | { 7 | public static Uri GetSearchServiceUri(this string serviceName) 8 | { 9 | return new Uri($"https://{serviceName}.search.windows.net/"); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/Search/FieldAggregateModel.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl.Repository.Search 4 | { 5 | public class FieldAggregateModel 6 | { 7 | [Description("Aggregate value.")] 8 | public string Value { get; set; } 9 | 10 | [Description("Aggregate count.")] 11 | public int Count { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/Search/Filters/ISearchFilter.cs: -------------------------------------------------------------------------------- 1 | using FastMember; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl.Repository.Search.Filters 4 | { 5 | public interface ISearchFilter 6 | { 7 | bool CanHandle(Comparisons comparison, Member member); 8 | string GetFilter(SearchFilterModel searchFilterModel, Member member); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/Search/Filters/ISearchFilterProvider.cs: -------------------------------------------------------------------------------- 1 | using FastMember; 2 | using System.Collections.Generic; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Repository.Search.Filters 5 | { 6 | public interface ISearchFilterProvider 7 | { 8 | string GenerateStringFilter(IEnumerable queryParameters, MemberSet members); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/Search/Filters/SearchFilterProvider.cs: -------------------------------------------------------------------------------- 1 | using FastMember; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | 7 | namespace Eklee.Azure.Functions.GraphQl.Repository.Search.Filters 8 | { 9 | public class SearchFilterProvider : ISearchFilterProvider 10 | { 11 | private readonly IEnumerable _searchFilters; 12 | 13 | public SearchFilterProvider(IEnumerable searchFilters) 14 | { 15 | _searchFilters = searchFilters; 16 | } 17 | 18 | public string GenerateStringFilter(IEnumerable queryParameters, MemberSet members) 19 | { 20 | var filterQp = queryParameters.SingleOrDefault(x => x.MemberModel.Name == "filters"); 21 | if (filterQp != null && filterQp.ContextValue != null && 22 | filterQp.ContextValue.Values != null) 23 | { 24 | var sb = new StringBuilder(); 25 | filterQp.ContextValue.Values.ForEach(value => 26 | { 27 | var searchFilterModel = (SearchFilterModel)value; 28 | 29 | var member = members.SingleOrDefault(x => x.Name.ToLower() == searchFilterModel.FieldName.ToLower()); 30 | 31 | if (member == null) 32 | { 33 | throw new ArgumentException($"{searchFilterModel.FieldName} is not valid."); 34 | } 35 | 36 | var filter = _searchFilters.SingleOrDefault(x => x.CanHandle(searchFilterModel.Comprison, member)); 37 | 38 | if (filter != null) 39 | { 40 | sb.Append($"{filter.GetFilter(searchFilterModel, member)} and "); 41 | } 42 | }); 43 | 44 | return sb.ToString().TrimEnd("and ".ToCharArray()); 45 | } 46 | 47 | return null; 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/Search/Filters/StringSearchFilter.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.GraphQl.Queries; 2 | using FastMember; 3 | using System; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl.Repository.Search.Filters 6 | { 7 | public class StringSearchFilter : ISearchFilter 8 | { 9 | public bool CanHandle(Comparisons comparison, Member member) 10 | { 11 | return member.Type == typeof(string); 12 | } 13 | 14 | public string GetFilter(SearchFilterModel searchFilterModel, Member member) 15 | { 16 | return $"{member.Name} {GetComparison(searchFilterModel)} '{searchFilterModel.Value}'"; 17 | } 18 | 19 | private string GetComparison(SearchFilterModel searchFilterModel) 20 | { 21 | switch (searchFilterModel.Comprison) 22 | { 23 | case Comparisons.Equal: 24 | return Constants.ODataEqual; 25 | 26 | case Comparisons.NotEqual: 27 | return Constants.ODataNotEqual; 28 | 29 | default: 30 | throw new NotImplementedException($"Comparison {searchFilterModel.Comprison} is not implemented or is invalid."); 31 | } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/Search/ISearchMappedModels.cs: -------------------------------------------------------------------------------- 1 | namespace Eklee.Azure.Functions.GraphQl.Repository.Search 2 | { 3 | public interface ISearchMappedModels 4 | { 5 | void Map(); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/Search/SearchAggregateModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Repository.Search 5 | { 6 | public class SearchAggregateModel 7 | { 8 | [Description("Name of the field.")] 9 | public string FieldName { get; set; } 10 | 11 | [Description("List of aggregates.")] 12 | public List FieldAggregates { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/Search/SearchConfiguration.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Eklee.Azure.Functions.GraphQl.Repository.DocumentDb; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl.Repository.Search 6 | { 7 | public class SearchConfiguration where TSource : class 8 | { 9 | private readonly IModelConventionInputBuilder _modelConventionInputBuilder; 10 | private readonly IGraphQlRepository _graphQlRepository; 11 | private readonly Dictionary _configurations = new Dictionary(); 12 | 13 | public SearchConfiguration( 14 | IModelConventionInputBuilder modelConventionInputBuilder, 15 | IGraphQlRepository graphQlRepository) 16 | { 17 | _modelConventionInputBuilder = modelConventionInputBuilder; 18 | _graphQlRepository = graphQlRepository; 19 | } 20 | 21 | public SearchConfiguration AddGraphRequestContextSelector(Func selector) 22 | { 23 | _configurations.Add(SearchConstants.RequestContextSelector, selector); 24 | return this; 25 | } 26 | 27 | public SearchConfiguration AddServiceName(string serviceName) 28 | { 29 | _configurations.Add(SearchConstants.ServiceName, serviceName); 30 | return this; 31 | } 32 | 33 | public SearchConfiguration AddApiKey(string apiKey) 34 | { 35 | _configurations.Add(SearchConstants.ApiKey, apiKey); 36 | return this; 37 | } 38 | 39 | public SearchConfiguration AddPrefix(string prefix) 40 | { 41 | _configurations.Add(SearchConstants.Prefix, prefix); 42 | return this; 43 | } 44 | 45 | public IModelConventionInputBuilder BuildSearch() 46 | { 47 | _graphQlRepository.Configure(typeof(TSource), _configurations); 48 | 49 | return _modelConventionInputBuilder; 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/Search/SearchConstants.cs: -------------------------------------------------------------------------------- 1 | namespace Eklee.Azure.Functions.GraphQl.Repository.Search 2 | { 3 | public static class SearchConstants 4 | { 5 | public const string ServiceName = "ServiceName"; 6 | public const string ApiKey = "ApiKey"; 7 | public const string QueryTypes = "QueryTypes"; 8 | public const string QueryName = "QueryName"; 9 | public const string Prefix = "Prefix"; 10 | public const string RequestContextSelector = "RequestContextSelector"; 11 | public const string EnableAggregate = "EnableAggregate"; 12 | } 13 | } -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/Search/SearchFilterModel.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl.Repository.Search 4 | { 5 | public class SearchFilterModel 6 | { 7 | [Description("Name of the field.")] 8 | public string FieldName { get; set; } 9 | 10 | [Description("Field filter value.")] 11 | public string Value { get; set; } 12 | 13 | [Description("Field filter comprison.")] 14 | public Comparisons Comprison { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/Search/SearchMappedModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl.Repository.Search 4 | { 5 | public class SearchMappedModel 6 | { 7 | public Type SearchModelType { get; set; } 8 | public Type ModelType { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/Search/SearchModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Repository.Search 5 | { 6 | public class SearchModel 7 | { 8 | [Description("Search text.")] 9 | public string SearchText { get; set; } 10 | 11 | [Description("List of filters.")] 12 | public List Filters { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/Search/SearchResult.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl.Repository.Search 4 | { 5 | public class SearchResult 6 | { 7 | public List Values { get; set; } 8 | 9 | public List Aggregates { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/Search/SearchResultModel.cs: -------------------------------------------------------------------------------- 1 | namespace Eklee.Azure.Functions.GraphQl.Repository.Search 2 | { 3 | public class SearchResultModel 4 | { 5 | public object Value { get; set; } 6 | 7 | public double Score { get; set; } 8 | 9 | public T Get() 10 | { 11 | return (T)Value; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/TableStorage/ITableStorageComparison.cs: -------------------------------------------------------------------------------- 1 | namespace Eklee.Azure.Functions.GraphQl.Repository.TableStorage 2 | { 3 | public interface ITableStorageComparison 4 | { 5 | bool CanHandle(QueryParameter queryParameter); 6 | string Generate(); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/TableStorage/TableStorageComparisonBase.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Azure.Cosmos.Table; 2 | using System.Linq; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Repository.TableStorage 5 | { 6 | public abstract class TableStorageComparisonBase : ITableStorageComparison 7 | { 8 | protected T Value; 9 | protected T[] Values; 10 | protected QueryParameter QueryParameter; 11 | 12 | protected abstract string GenerateFilterConditionFor(Comparisons comparison, T value); 13 | protected abstract bool AssertCanHandleContextValue(object o); 14 | 15 | public bool CanHandle(QueryParameter queryParameter) 16 | { 17 | QueryParameter = queryParameter; 18 | Value = default(T); 19 | 20 | var value = QueryParameter.ContextValue.GetFirstValue(); 21 | if (AssertCanHandleContextValue(value)) 22 | { 23 | if (QueryParameter.ContextValue.IsSingleValue()) 24 | Value = (T)value; 25 | else 26 | Values = QueryParameter.ContextValue.Values.Select(x => (T)x).ToArray(); 27 | 28 | return true; 29 | } 30 | 31 | return false; 32 | } 33 | 34 | public string Generate() 35 | { 36 | if (!QueryParameter.ContextValue.Comparison.HasValue) return null; 37 | 38 | Comparisons comparison = QueryParameter.ContextValue.Comparison.Value; 39 | if (QueryParameter.ContextValue.IsSingleValue()) 40 | return GenerateFilterConditionFor(comparison, Value); 41 | 42 | string filters = null; 43 | Values.ToList().ForEach(value => 44 | { 45 | var current = GenerateFilterConditionFor(comparison, value); 46 | 47 | if (current == null) return; 48 | 49 | if (filters == null) 50 | { 51 | filters = current; 52 | } 53 | else 54 | { 55 | filters = TableQuery.CombineFilters(filters, TableOperators.Or, current); 56 | } 57 | }); 58 | 59 | return filters; 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/TableStorage/TableStorageComparisonBool.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Azure.Cosmos.Table; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl.Repository.TableStorage 4 | { 5 | public class TableStorageComparisonBool : ITableStorageComparison 6 | { 7 | private QueryParameter _queryParameter; 8 | 9 | private bool? _value; 10 | 11 | public bool CanHandle(QueryParameter queryParameter) 12 | { 13 | _queryParameter = queryParameter; 14 | _value = null; 15 | 16 | if (queryParameter.ContextValue.IsSingleValue() && 17 | queryParameter.ContextValue.GetFirstValue() is bool value) 18 | { 19 | _value = value; 20 | return true; 21 | } 22 | 23 | return false; 24 | } 25 | 26 | public string Generate() 27 | { 28 | if (_queryParameter.ContextValue.Comparison == Comparisons.Equal) 29 | // ReSharper disable once PossibleInvalidOperationException 30 | return TableQuery.GenerateFilterConditionForBool(_queryParameter.MemberModel.Member.Name, QueryComparisons.Equal, _value.Value); 31 | 32 | return null; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/TableStorage/TableStorageComparisonGuid.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.Azure.Cosmos.Table; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Repository.TableStorage 5 | { 6 | public class TableStorageComparisonGuid : TableStorageComparisonBase 7 | { 8 | protected override string GenerateFilterConditionFor(Comparisons comparison, Guid value) 9 | { 10 | if (QueryParameter.ContextValue.Comparison == Comparisons.Equal) 11 | // ReSharper disable once PossibleInvalidOperationException 12 | return TableQuery.GenerateFilterConditionForGuid(QueryParameter.MemberModel.Member.Name, QueryComparisons.Equal, value); 13 | 14 | return null; 15 | } 16 | 17 | protected override bool AssertCanHandleContextValue(object o) 18 | { 19 | return o is Guid; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/TableStorage/TableStorageComparisonString.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Azure.Cosmos.Table; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl.Repository.TableStorage 4 | { 5 | public class TableStorageComparisonString : TableStorageComparisonBase 6 | { 7 | protected override string GenerateFilterConditionFor(Comparisons comparison, string value) 8 | { 9 | if (comparison == Comparisons.Equal) 10 | { 11 | return TableQuery.GenerateFilterCondition(QueryParameter.MemberModel.Member.Name, 12 | QueryComparisons.Equal, value); 13 | } 14 | 15 | return null; 16 | } 17 | 18 | protected override bool AssertCanHandleContextValue(object o) 19 | { 20 | return o is string value && !string.IsNullOrEmpty(value); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Repository/TableStorage/TableStorageConstants.cs: -------------------------------------------------------------------------------- 1 | namespace Eklee.Azure.Functions.GraphQl.Repository.TableStorage 2 | { 3 | public class TableStorageConstants 4 | { 5 | public const string Prefix = "Prefix"; 6 | public const string ConnectionString = "ConnectionString"; 7 | public const string PartitionMemberExpression = "PartitionMemberExpression"; 8 | public const string RequestContextSelector = "RequestContextSelector"; 9 | } 10 | } -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/SecurityExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl 5 | { 6 | public static class SecurityExtensions 7 | { 8 | private const string AzureAdSts = "https://sts.windows.net/"; 9 | 10 | public static string GetTenantIdFromIssuer(this string issuer) 11 | { 12 | var index = issuer.IndexOf(AzureAdSts, StringComparison.Ordinal); 13 | return issuer.Substring(index > -1 ? AzureAdSts.Length : 0).TrimEnd('/').Replace("-", ""); 14 | } 15 | 16 | public static bool ContainsIssuer(this IGraphRequestContext graphRequestContext, string issuer) 17 | { 18 | return graphRequestContext.HttpRequest != null && 19 | graphRequestContext.HttpRequest.Security.ClaimsPrincipal != null && 20 | graphRequestContext.HttpRequest.Security.ClaimsPrincipal.Claims.Any( 21 | x => x.Type == "iss" && x.Value == issuer); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Validations/IModelValidation.cs: -------------------------------------------------------------------------------- 1 | using FastMember; 2 | using System; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Validations 5 | { 6 | public interface IModelValidation 7 | { 8 | bool CanHandle(Type type); 9 | bool TryAssertMemberValueIsValid(Member member, object value, out string errorCode, out string message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Eklee.Azure.Functions.GraphQl/Validations/StringLengthModelValidation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | using FastMember; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl.Validations 6 | { 7 | public class StringLengthModelValidation : IModelValidation 8 | { 9 | public bool CanHandle(Type type) 10 | { 11 | // Handle all types. 12 | return true; 13 | } 14 | 15 | public bool TryAssertMemberValueIsValid(Member member, object value, out string errorCode, out string message) 16 | { 17 | StringLengthAttribute stringLength = member.GetAttribute(typeof(StringLengthAttribute), false) as StringLengthAttribute; 18 | 19 | if (stringLength != null && !IsValid(stringLength, value, out message)) 20 | { 21 | errorCode = "InvalidStringLength"; 22 | return false; 23 | } 24 | errorCode = null; 25 | message = null; 26 | 27 | return true; 28 | } 29 | 30 | private bool IsValid(StringLengthAttribute stringLength, object value, out string message) 31 | { 32 | if (value is string valueString) 33 | { 34 | if (string.IsNullOrEmpty(valueString) && stringLength.MinimumLength > 0) 35 | { 36 | message = $"String value must be more than {stringLength.MinimumLength} in length."; 37 | return false; 38 | } 39 | 40 | if (valueString.Length < stringLength.MinimumLength) 41 | { 42 | message = $"String value must be more than {stringLength.MinimumLength} in length."; 43 | return false; 44 | } 45 | 46 | if (valueString.Length > stringLength.MaximumLength) 47 | { 48 | message = $"String value must be less than {stringLength.MaximumLength} in length."; 49 | return false; 50 | } 51 | } 52 | 53 | message = ""; 54 | return true; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Actions/ValueFromRequestHeader.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.GraphQl.Actions.RequestContextValueExtractors; 2 | using FastMember; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace Eklee.Azure.Functions.GraphQl.Example.Actions 7 | { 8 | public class ValueFromRequestHeader : IRequestContextValueExtractor 9 | { 10 | public Task GetValueAsync(IGraphRequestContext graphRequestContext, Member member) 11 | { 12 | var headerVal = graphRequestContext.HttpRequest.Request.Headers["SomeThingFromHeader"]; 13 | return Task.FromResult((object)headerVal.First()); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/BooksGraphFunction.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Eklee.Azure.Functions.Http; 3 | using Microsoft.AspNetCore.Mvc; 4 | using Microsoft.Azure.WebJobs; 5 | using Microsoft.AspNetCore.Http; 6 | using Microsoft.Extensions.Logging; 7 | using Microsoft.Azure.WebJobs.Extensions.Http; 8 | 9 | namespace Eklee.Azure.Functions.GraphQl.Example 10 | { 11 | public static class BooksGraphFunction 12 | { 13 | [ExecutionContextDependencyInjection(typeof(MyModule))] 14 | [FunctionName("graph")] 15 | public static async Task Run( 16 | [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = "books/graph")] HttpRequest req, 17 | ILogger log, 18 | ExecutionContext executionContext) 19 | { 20 | return await executionContext.ProcessGraphQlRequest(req); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/BusinessLayer/BookPrice.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.ComponentModel.DataAnnotations; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl.Example.BusinessLayer 6 | { 7 | public class BookPriceId 8 | { 9 | [Key] 10 | [Description("Id of book price.")] 11 | public Guid Id { get; set; } 12 | } 13 | 14 | public class BookPrice 15 | { 16 | [Key] 17 | [Description("Id of book price.")] 18 | public Guid Id { get; set; } 19 | 20 | [Description("Description.")] 21 | public string Description { get; set; } 22 | 23 | [Description("Description.")] 24 | public string Type { get; set; } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/BusinessLayer/BooksQuery.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.GraphQl.Example.Models; 2 | using GraphQL.Types; 3 | using Microsoft.Extensions.Logging; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl.Example.BusinessLayer 6 | { 7 | public class BooksQuery : ObjectGraphType 8 | { 9 | public BooksQuery(QueryBuilderFactory queryBuilderFactory, ILogger logger) 10 | { 11 | logger.LogInformation("Creating queries."); 12 | 13 | Name = "query"; 14 | 15 | this.AddBooksQueries(queryBuilderFactory); 16 | 17 | this.AddPublisherQueries(queryBuilderFactory); 18 | 19 | this.AddBookReviewQueries(queryBuilderFactory); 20 | 21 | queryBuilderFactory.Create(this, "getAuthorByHomeCity") 22 | .WithParameterBuilder() 23 | .WithProperty(x => x.HomeCity) 24 | .BuildQuery() 25 | .BuildWithListResult(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/BusinessLayer/BooksSchema.cs: -------------------------------------------------------------------------------- 1 | using GraphQL.Types; 2 | using System; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Example.BusinessLayer 5 | { 6 | public class BooksSchema : Schema 7 | { 8 | public BooksSchema(IServiceProvider resolver, BooksQuery booksQuery, BooksMutation booksMutation) : base(resolver) 9 | { 10 | Query = booksQuery; 11 | Mutation = booksMutation; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/BusinessLayer/PagingBooksMutation.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.GraphQl.Example.Models; 2 | using GraphQL.Types; 3 | using Microsoft.Extensions.Configuration; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl.Example.BusinessLayer 6 | { 7 | public class PagingBooksMutation : ObjectGraphType 8 | { 9 | public PagingBooksMutation(InputBuilderFactory inputBuilderFactory, IConfiguration configuration) 10 | { 11 | Name = "mutations"; 12 | 13 | inputBuilderFactory.Create(this).ConfigureInMemory().BuildInMemory().Build(); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/BusinessLayer/PagingBooksQuery.cs: -------------------------------------------------------------------------------- 1 | using GraphQL.Types; 2 | using Microsoft.Extensions.Logging; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Example.BusinessLayer 5 | { 6 | public class PagingBooksQuery : ObjectGraphType 7 | { 8 | public PagingBooksQuery(QueryBuilderFactory queryBuilderFactory, ILogger logger) 9 | { 10 | logger.LogInformation("Creating queries."); 11 | 12 | Name = "query"; 13 | 14 | this.AddBookAuthorsOutputQueries(queryBuilderFactory); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/BusinessLayer/PagingBooksSchema.cs: -------------------------------------------------------------------------------- 1 | using GraphQL.Types; 2 | using System; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Example.BusinessLayer 5 | { 6 | public class PagingBooksSchema : Schema 7 | { 8 | public PagingBooksSchema(IServiceProvider resolver, PagingBooksQuery booksQuery, PagingBooksMutation booksMutation) : base(resolver) 9 | { 10 | Query = booksQuery; 11 | Mutation = booksMutation; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/BusinessLayer/PublisherQueryExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Eklee.Azure.Functions.GraphQl.Example.HttpMocks; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Example.BusinessLayer 5 | { 6 | public static class PublisherQueryExtensions 7 | { 8 | public const string GetPublisherByIdQuery = "getPublisherById"; 9 | public static void AddPublisherQueries(this BooksQuery booksQuery, QueryBuilderFactory queryBuilderFactory) 10 | { 11 | queryBuilderFactory.Create(booksQuery, GetPublisherByIdQuery) 12 | .WithCache(TimeSpan.FromSeconds(10)) 13 | .WithParameterBuilder() 14 | .WithProperty(x => x.Id) 15 | .BuildQuery() 16 | .BuildWithSingleResult(); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Eklee.Azure.Functions.GraphQl.Example.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | netstandard2.1 4 | v3 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | PreserveNewest 17 | 18 | 19 | Always 20 | Never 21 | 22 | 23 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/HttpMocks/IHttpMockRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl.Example.HttpMocks 4 | { 5 | public interface IHttpMockRepository 6 | { 7 | void Add(T item); 8 | T Update(T item); 9 | void Delete(string id); 10 | IQueryable Search(); 11 | void ClearAll(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/HttpMocks/Publisher.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Example.HttpMocks 5 | { 6 | public class Publisher 7 | { 8 | [Key] 9 | [Description("Publisher Id.")] 10 | public string Id { get; set; } 11 | 12 | [Description("Name of publisher.")] 13 | public string Name { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/HttpMocks/PublisherMockRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Example.HttpMocks 5 | { 6 | public class PublisherMockRepository : IHttpMockRepository 7 | { 8 | private readonly Dictionary _publishers = new Dictionary(); 9 | 10 | public void Add(Publisher item) 11 | { 12 | _publishers.Add(item.Id, item); 13 | } 14 | 15 | public Publisher Update(Publisher item) 16 | { 17 | var p = _publishers[item.Id] = item; 18 | 19 | return p; 20 | } 21 | 22 | public void Delete(string id) 23 | { 24 | _publishers.Remove(id); 25 | } 26 | 27 | public IQueryable Search() 28 | { 29 | return _publishers.Values.AsQueryable(); 30 | } 31 | 32 | public void ClearAll() 33 | { 34 | _publishers.Clear(); 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Models/Author.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Example.Models 5 | { 6 | [Description("Author for the book.")] 7 | public class Author 8 | { 9 | [Key] 10 | [Description("id of author")] 11 | public string Id { get; set; } 12 | 13 | [Description("Name of the author.")] 14 | public string Name { get; set; } 15 | 16 | [Description("Home city of the author.")] 17 | public string HomeCity { get; set; } 18 | } 19 | } -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Models/Book.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Example.Models 5 | { 6 | [Description("Book written by a Author found in our system.")] 7 | public class Book 8 | { 9 | [Key] 10 | [Description("id of book")] 11 | public string Id { get; set; } 12 | 13 | [Description("Name of the book.")] 14 | public string Name { get; set; } 15 | 16 | [Description("category of book")] 17 | public string Category { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Models/BookAuthors.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel; 3 | using System.ComponentModel.DataAnnotations; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl.Example.Models 6 | { 7 | [Description("Represents the relationship between a book and its authors.")] 8 | public class BookAuthors 9 | { 10 | [Key] 11 | [Description("Id of the book-authors")] 12 | public string Id { get; set; } 13 | 14 | [Description("Id of the book.")] 15 | public string BookId { get; set; } 16 | 17 | [Description("Author Id list.")] 18 | public List AuthorIdList { get; set; } 19 | 20 | [Description("The type of royalty from book publishers.")] 21 | public string RoyaltyType { get; set; } 22 | } 23 | } -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Models/BookAuthorsOutput.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Example.Models 5 | { 6 | public class BookAuthorsOutput : BookAuthors 7 | { 8 | [Description("Book written by these authors.")] 9 | public Book Book { get; set; } 10 | 11 | [Description("Authors who wrote the book")] 12 | public List Authors { get; set; } 13 | } 14 | } -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Models/BookId.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Example.Models 5 | { 6 | public class BookId 7 | { 8 | [Description("Id of book.")] 9 | [Key] 10 | public string Id { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Models/BookReview.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.ComponentModel.DataAnnotations; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl.Example.Models 6 | { 7 | public class BookReview 8 | { 9 | [Key] 10 | [Description("Id of book review.")] 11 | public string Id { get; set; } 12 | 13 | [Description("Id of Reviewer")] 14 | public string ReviewerId { get; set; } 15 | 16 | [Description("Id of book")] 17 | public string BookId { get; set; } 18 | 19 | [Description("Commentary by reviewer")] 20 | public string Comments { get; set; } 21 | 22 | [Description("1-5 starts rating")] 23 | public int Stars { get; set; } 24 | 25 | [Description("Determines whether book review is currently active or disabled.")] 26 | public bool Active { get; set; } 27 | 28 | [Description("Determine when book review is written.")] 29 | public DateTime WrittenOn { get; set; } 30 | } 31 | 32 | public class BookReviewId 33 | { 34 | [Description("Id of book review.")] 35 | [Key] 36 | public string Id { get; set; } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Models/BookReviewOutput.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl.Example.Models 4 | { 5 | public class BookReviewOutput : BookReview 6 | { 7 | [Description("Book that is reviewed.")] 8 | public Book Book { get; set; } 9 | 10 | [Description("Person who reviewed the book.")] 11 | public Reviewer Reviewer { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Models/BookSearch.cs: -------------------------------------------------------------------------------- 1 | namespace Eklee.Azure.Functions.GraphQl.Example.Models 2 | { 3 | public class BookSearch : Book 4 | { 5 | 6 | } 7 | } -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Models/EachModel10.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.GraphQl.Connections; 2 | using System.ComponentModel; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Example.Models 5 | { 6 | public class EachModel10 7 | { 8 | [ConnectionEdgeDestinationKey] 9 | [Description("Id of destination")] 10 | public string Id { get; set; } 11 | 12 | [Description("Field")] 13 | public string FieldDescription { get; set; } 14 | 15 | [ConnectionEdgeDestination] 16 | [Description("TheModel8")] 17 | public Model10 Model10 { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Models/EachModel11.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.GraphQl.Connections; 2 | using System.ComponentModel; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Example.Models 5 | { 6 | public class EachModel11 7 | { 8 | [ConnectionEdgeDestinationKey] 9 | [Description("Id of destination")] 10 | public string Id { get; set; } 11 | 12 | [Description("Field")] 13 | public string FieldDescription { get; set; } 14 | 15 | [ConnectionEdgeDestination] 16 | [Description("TheModel11")] 17 | public Model11 Model11 { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Models/Model1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.ComponentModel.DataAnnotations; 4 | using Eklee.Azure.Functions.GraphQl.Attributes; 5 | 6 | namespace Eklee.Azure.Functions.GraphQl.Example.Models 7 | { 8 | [Description("Types of Model1s")] 9 | public enum Model1Types 10 | { 11 | [Description("Model 1 Type 1")] 12 | M1Type1, 13 | 14 | [Description("Model 1 Type 2")] 15 | M1Type2 16 | } 17 | 18 | [Description("Model 1 class for testing Search.")] 19 | public class Model1 20 | { 21 | [Key] 22 | [Description("Id")] 23 | public string Id { get; set; } 24 | 25 | [Description("IntField")] 26 | public int IntField { get; set; } 27 | 28 | [Description("DoubleField")] 29 | public double DoubleField { get; set; } 30 | 31 | [Description("DateField")] 32 | public DateTime DateField { get; set; } 33 | 34 | [Description("Field")] 35 | public string Field { get; set; } 36 | 37 | [ModelField(true)] 38 | [Description("Types")] 39 | public Model1Types Type { get; set; } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Models/Model10.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.GraphQl.Connections; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.ComponentModel.DataAnnotations; 5 | 6 | namespace Eklee.Azure.Functions.GraphQl.Example.Models 7 | { 8 | public class Model10 9 | { 10 | [Key] 11 | [Description("Id")] 12 | public string Id { get; set; } 13 | 14 | [Description("Field")] 15 | public string Field { get; set; } 16 | 17 | [Connection] 18 | [Description("Model11")] 19 | public List EachModel11List { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Models/Model11.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Example.Models 5 | { 6 | public class Model11 7 | { 8 | [Key] 9 | [Description("Id")] 10 | public string Id { get; set; } 11 | 12 | [Description("Field")] 13 | public string Field { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Models/Model12.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.GraphQl.Attributes; 2 | using Eklee.Azure.Functions.GraphQl.Example.Actions; 3 | using System; 4 | using System.ComponentModel; 5 | using System.ComponentModel.DataAnnotations; 6 | 7 | namespace Eklee.Azure.Functions.GraphQl.Example.Models 8 | { 9 | public class Model12 10 | { 11 | [AutoId] 12 | [Key] 13 | [Description("Id")] 14 | public string Id { get; set; } 15 | 16 | [ModelField(false)] 17 | [Description("Field")] 18 | public string Field { get; set; } 19 | 20 | [AutoDateTime(AutoDateTimeTypes.UtcNow)] 21 | [ModelField(false)] 22 | [Description("FieldDateTimeNow")] 23 | public DateTimeOffset FieldDateTimeNow { get; set; } 24 | 25 | [AutoDateTime(AutoDateTimeTypes.UtcToday)] 26 | [ModelField(false)] 27 | [Description("FieldDateTimeToday")] 28 | public DateTime FieldDateTimeToday { get; set; } 29 | 30 | [ModelField(true)] 31 | [Description("FieldDateTime")] 32 | public DateTime FieldDateTime { get; set; } 33 | 34 | [RequestContextValue(typeof(ValueFromRequestHeader))] 35 | [ModelField(false)] 36 | [Description("FieldFromHeader")] 37 | public string FieldFromHeader { get; set; } 38 | 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Models/Model13Child.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.GraphQl.Attributes; 2 | using System.ComponentModel; 3 | using System.ComponentModel.DataAnnotations; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl.Example.Models 6 | { 7 | public class Model13Child 8 | { 9 | [Key] 10 | [Description("Id of destination")] 11 | public string ChildId { get; set; } 12 | 13 | [Description("Field")] 14 | public string Field { get; set; } 15 | 16 | [PartitionKey] 17 | [Description("AccountId")] 18 | public string AccountId { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Models/Model13Edge.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.GraphQl.Connections; 2 | using System.ComponentModel; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Example.Models 5 | { 6 | public class Model13Edge 7 | { 8 | [ConnectionEdgeDestinationKey] 9 | [Description("Id of destination")] 10 | public string Id { get; set; } 11 | 12 | [Description("Field")] 13 | public string Field { get; set; } 14 | 15 | [ConnectionEdgeDestination] 16 | [Description("Child")] 17 | public Model13Child Child { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Models/Model13Parent.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.GraphQl.Connections; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.ComponentModel.DataAnnotations; 5 | 6 | namespace Eklee.Azure.Functions.GraphQl.Example.Models 7 | { 8 | public class Model13Parent 9 | { 10 | [Key] 11 | [Description("Some Key")] 12 | public string SomeKey { get; set; } 13 | 14 | [Description("Some Descr")] 15 | public string Descr { get; set; } 16 | 17 | [Description("Account Id")] 18 | public string AccountId { get; set; } 19 | 20 | [Connection] 21 | [Description("Connection")] 22 | public List Edges { get; set; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Models/Model14.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Example.Models 5 | { 6 | public class Model14 7 | { 8 | [Key] 9 | [Description("Some Key")] 10 | public string SomeKey { get; set; } 11 | 12 | [Description("Some Descr")] 13 | public string Descr { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Models/Model15.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.ComponentModel.DataAnnotations; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl.Example.Models 6 | { 7 | public class Model15 8 | { 9 | [Key] 10 | [Description("Id")] 11 | public string Id { get; set; } 12 | 13 | [Description("Field")] 14 | public string Field { get; set; } 15 | 16 | [Description("DateTimeOffsetField ")] 17 | public DateTimeOffset DateTimeOffsetField { get; set; } 18 | 19 | [Description("DateTimeOffsetField 2")] 20 | public DateTimeOffset? DateTimeOffsetField2 { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Models/Model16.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.ComponentModel.DataAnnotations; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl.Example.Models 6 | { 7 | public class Model16 8 | { 9 | [Key] 10 | [Description("Id")] 11 | public string Id { get; set; } 12 | 13 | [Description("Field")] 14 | public string Field { get; set; } 15 | 16 | [Description("DateTime ")] 17 | public DateTime DateTime { get; set; } 18 | 19 | [Description("DateTime 2")] 20 | public DateTime? DateTime2 { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Models/Model17.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Example.Models 5 | { 6 | public class Model17 7 | { 8 | [Key] 9 | [Description("Id")] 10 | public string Id { get; set; } 11 | 12 | [Description("Field")] 13 | public string Field { get; set; } 14 | 15 | [Description("Number")] 16 | public int Value { get; set; } 17 | 18 | [Description("Number 2")] 19 | public int? Value2 { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Models/Model18.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Example.Models 5 | { 6 | public class Model18 7 | { 8 | [Key] 9 | [Description("Id")] 10 | public string Id { get; set; } 11 | 12 | [Description("Field")] 13 | public string Field { get; set; } 14 | 15 | [Description("Double")] 16 | public double Value { get; set; } 17 | 18 | [Description("Double 2")] 19 | public double? Value2 { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Models/Model19.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Example.Models 5 | { 6 | public class Model19 7 | { 8 | [Key] 9 | [Description("Id")] 10 | public string Id { get; set; } 11 | 12 | [Description("Field")] 13 | public string Field { get; set; } 14 | 15 | [Description("Double")] 16 | public decimal Value { get; set; } 17 | 18 | [Description("Double 2")] 19 | public decimal? Value2 { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Models/Model2.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.ComponentModel.DataAnnotations; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl.Example.Models 6 | { 7 | [Description("Types of Model1s")] 8 | public enum Model2Types 9 | { 10 | [Description("Model 2 Type 1")] 11 | M2Type1, 12 | 13 | [Description("Model 2 Type 2")] 14 | M2Type2 15 | } 16 | 17 | public class Model2 18 | { 19 | [Key] 20 | [Description("Id")] 21 | public string Id { get; set; } 22 | 23 | [Description("IntField")] 24 | public int IntField { get; set; } 25 | 26 | [Description("DoubleField")] 27 | public double DoubleField { get; set; } 28 | 29 | [Description("DateField")] 30 | public DateTime DateField { get; set; } 31 | 32 | [Description("Field")] 33 | public string Field { get; set; } 34 | 35 | [Description("Model2Types")] 36 | public Model2Types? Type { get; set; } 37 | } 38 | } -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Models/Model3.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.ComponentModel.DataAnnotations; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl.Example.Models 6 | { 7 | public class Model3 8 | { 9 | [Key] 10 | [Description("Id")] 11 | public string Id { get; set; } 12 | 13 | [Description("IntField")] 14 | public int IntField { get; set; } 15 | 16 | [Description("DoubleField")] 17 | public double DoubleField { get; set; } 18 | 19 | [Description("DateField")] 20 | public DateTime DateField { get; set; } 21 | 22 | [Description("Field")] 23 | public string Field { get; set; } 24 | } 25 | } -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Models/Model3V2.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl.Example.Models 4 | { 5 | public class Model3V2 : Model3 6 | { 7 | [Description("FieldTwo")] 8 | public string FieldTwo { get; set; } 9 | 10 | [Description("FieldThree")] 11 | public string FieldThree { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Models/Model4.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.ComponentModel.DataAnnotations; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl.Example.Models 6 | { 7 | public class Model4 8 | { 9 | [Key] 10 | [Description("Id")] 11 | public string Id { get; set; } 12 | 13 | [Description("IntField")] 14 | public int IntField { get; set; } 15 | 16 | [Description("DoubleField")] 17 | public double DoubleField { get; set; } 18 | 19 | [Description("DateField")] 20 | public DateTime DateField { get; set; } 21 | 22 | [StringLength(10, MinimumLength = 2)] 23 | [Description("Field")] 24 | public string Field { get; set; } 25 | } 26 | } -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Models/Model5.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.GraphQl.Connections; 2 | using System; 3 | using System.ComponentModel; 4 | using System.ComponentModel.DataAnnotations; 5 | 6 | namespace Eklee.Azure.Functions.GraphQl.Example.Models 7 | { 8 | public class Model5 9 | { 10 | [Key] 11 | [Description("Id")] 12 | public string Id { get; set; } 13 | 14 | [Description("IntField")] 15 | public int IntField { get; set; } 16 | 17 | [Description("DoubleField")] 18 | public double DoubleField { get; set; } 19 | 20 | [Description("DateField")] 21 | public DateTime DateField { get; set; } 22 | 23 | [Description("Field")] 24 | public string Field { get; set; } 25 | 26 | [Connection] 27 | [Description("A Best Friend")] 28 | public Model5Friend BestFriend { get; set; } 29 | 30 | [Connection] 31 | [Description("A Close Friend")] 32 | public Model5Friend CloseFriend { get; set; } 33 | } 34 | } -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Models/Model5Friend.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.GraphQl.Connections; 2 | using System.ComponentModel; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Example.Models 5 | { 6 | public class Model5Friend 7 | { 8 | [ConnectionEdgeDestinationKey] 9 | [Description("Id of Connection.")] 10 | public string Id { get; set; } 11 | 12 | [Description("Field")] 13 | public string Field { get; set; } 14 | 15 | [ConnectionEdgeDestination] 16 | [Description("TheFriend")] 17 | public Model5 TheFriend { get; set; } 18 | } 19 | } -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Models/Model6.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.GraphQl.Attributes; 2 | using Eklee.Azure.Functions.GraphQl.Connections; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.ComponentModel; 6 | using System.ComponentModel.DataAnnotations; 7 | 8 | namespace Eklee.Azure.Functions.GraphQl.Example.Models 9 | { 10 | public class Model6 11 | { 12 | [Key] 13 | [Description("Id")] 14 | public string Id { get; set; } 15 | 16 | [Description("IntField")] 17 | public int IntField { get; set; } 18 | 19 | [Description("DoubleField")] 20 | public double DoubleField { get; set; } 21 | 22 | [Description("DateField")] 23 | public DateTime DateField { get; set; } 24 | 25 | [Description("Field")] 26 | [ModelField(false, true)] 27 | public string Field { get; set; } 28 | 29 | [ModelField(false)] 30 | [Description("Field2")] 31 | public string Field2 { get; set; } 32 | 33 | [ModelField(false)] 34 | [Description("Field3")] 35 | public string Field3 { get; set; } 36 | 37 | [Connection] 38 | [Description("List of Best Friends")] 39 | public List BestFriends { get; set; } 40 | } 41 | } -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Models/Model6Friend.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.GraphQl.Connections; 2 | using System.ComponentModel; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Example.Models 5 | { 6 | public class Model6Friend 7 | { 8 | [ConnectionEdgeDestinationKey] 9 | [Description("Id of Connection.")] 10 | public string Id { get; set; } 11 | 12 | [Description("Field")] 13 | public string Field { get; set; } 14 | 15 | [ConnectionEdgeDestination] 16 | [Description("TheFriend")] 17 | public Model6 TheFriend { get; set; } 18 | } 19 | } -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Models/Model7.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.GraphQl.Connections; 2 | using System.ComponentModel; 3 | using System.ComponentModel.DataAnnotations; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl.Example.Models 6 | { 7 | public class Model7 8 | { 9 | [Key] 10 | [Description("Id")] 11 | public string Id { get; set; } 12 | 13 | [Description("Field")] 14 | public string Field { get; set; } 15 | 16 | [Connection] 17 | [Description("Model7ToModel8")] 18 | public Model7ToModel8 Model7ToModel8 { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Models/Model7ToModel8.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.GraphQl.Connections; 2 | using System.ComponentModel; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Example.Models 5 | { 6 | public class Model7ToModel8 7 | { 8 | [ConnectionEdgeDestinationKey] 9 | [Description("Id of destination")] 10 | public string Id { get; set; } 11 | 12 | [Description("Field")] 13 | public string FieldDescription { get; set; } 14 | 15 | [ConnectionEdgeDestination] 16 | [Description("TheModel8")] 17 | public Model8 TheModel8 { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Models/Model8.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Example.Models 5 | { 6 | public class Model8 7 | { 8 | [Key] 9 | [Description("Id")] 10 | public string Id { get; set; } 11 | 12 | [Description("Field")] 13 | public string Field { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Models/Model9.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.GraphQl.Connections; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.ComponentModel.DataAnnotations; 5 | 6 | namespace Eklee.Azure.Functions.GraphQl.Example.Models 7 | { 8 | public class Model9 9 | { 10 | [Key] 11 | [Description("Id")] 12 | public string Id { get; set; } 13 | 14 | [Description("Field")] 15 | public string Field { get; set; } 16 | 17 | [Connection] 18 | [Description("Model7ToModel8")] 19 | public List EachModel10List { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Models/Reviewer.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel; 3 | using System.ComponentModel.DataAnnotations; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl.Example.Models 6 | { 7 | public class Reviewer 8 | { 9 | [Key] 10 | [Description("Id of the Reviewer.")] 11 | public string Id { get; set; } 12 | 13 | [Description("Name of the reviewer.")] 14 | public string Name { get; set; } 15 | 16 | [Description("Different areas of interests of the reviewer.")] 17 | public virtual List Interests { get; set; } 18 | 19 | [Description("Region of where reviewer lives.")] 20 | public string Region { get; set; } 21 | } 22 | 23 | public class ReviewerSearch 24 | { 25 | [Key] 26 | [Description("Id of the Reviewer.")] 27 | public string Id { get; set; } 28 | 29 | [Description("Name of the reviewer.")] 30 | public string Name { get; set; } 31 | 32 | [Description("Region of where reviewer lives.")] 33 | public string Region { get; set; } 34 | } 35 | 36 | public class ReviewerId 37 | { 38 | [Key] 39 | [Description("Id of the Reviewer.")] 40 | public string Id { get; set; } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Models/Status.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl.Example.Models 4 | { 5 | public class Status 6 | { 7 | [Description("Message describing the status of the request.")] 8 | public string Message { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Models/TestPermissionModel1.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Example.Models 5 | { 6 | public class TestPermissionModel1 7 | { 8 | [Key] 9 | [Description("Id")] 10 | public string Id { get; set; } 11 | 12 | [Description("Category")] 13 | public string Category { get; set; } 14 | 15 | [Description("Value")] 16 | public string Value { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Models/TestPermissionModel2.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Example.Models 5 | { 6 | public class TestPermissionModel2 7 | { 8 | [Key] 9 | [Description("Id")] 10 | public string Id { get; set; } 11 | 12 | [Description("Category")] 13 | public string Category { get; set; } 14 | 15 | [Description("Value")] 16 | public string Value { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Models/TestPermissionModel3.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Example.Models 5 | { 6 | public class TestPermissionModel3 7 | { 8 | [Key] 9 | [Description("Id")] 10 | public string Id { get; set; } 11 | 12 | [Description("Category")] 13 | public string Category { get; set; } 14 | 15 | [Description("Value")] 16 | public string Value { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/MyModule.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | using Eklee.Azure.Functions.GraphQl.Example.BusinessLayer; 3 | using Eklee.Azure.Functions.Http; 4 | using Microsoft.Extensions.Caching.Distributed; 5 | 6 | namespace Eklee.Azure.Functions.GraphQl.Example 7 | { 8 | public class MyModule : Module 9 | { 10 | protected override void Load(ContainerBuilder builder) 11 | { 12 | builder.UseDistributedCache(); 13 | builder.UseJwtAuthorization(); 14 | builder.RegisterGraphQl(); 15 | builder.RegisterType(); 16 | builder.RegisterType(); 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/MyModule2.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | using Eklee.Azure.Functions.GraphQl.Example.HttpMocks; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Example 5 | { 6 | public class MyModule2 : Module 7 | { 8 | protected override void Load(ContainerBuilder builder) 9 | { 10 | builder.RegisterType().As>().SingleInstance(); 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/MyPagingBooksModule.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | using Eklee.Azure.Functions.GraphQl.Example.BusinessLayer; 3 | using Eklee.Azure.Functions.Http; 4 | using Microsoft.Extensions.Caching.Distributed; 5 | 6 | namespace Eklee.Azure.Functions.GraphQl.Example 7 | { 8 | public class MyPagingBooksModule : Module 9 | { 10 | protected override void Load(ContainerBuilder builder) 11 | { 12 | builder.UseDistributedCache(); 13 | builder.UseJwtAuthorization(); 14 | builder.RegisterGraphQl(); 15 | builder.RegisterType(); 16 | builder.RegisterType(); 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Operations/IOperations.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl.Example.Operations 4 | { 5 | public interface IOperations 6 | { 7 | Task DeleteSearchIndexes(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Operations/Operations.cs: -------------------------------------------------------------------------------- 1 | using Azure; 2 | using Azure.Search.Documents.Indexes; 3 | using Eklee.Azure.Functions.GraphQl.Repository.Search; 4 | using Microsoft.Extensions.Configuration; 5 | using System.Threading.Tasks; 6 | 7 | namespace Eklee.Azure.Functions.GraphQl.Example.Operations 8 | { 9 | public class Operations : IOperations 10 | { 11 | private readonly IConfiguration _configuration; 12 | 13 | public Operations(IConfiguration configuration) 14 | { 15 | _configuration = configuration; 16 | } 17 | public async Task DeleteSearchIndexes() 18 | { 19 | var key = _configuration["Search:ApiKey"]; 20 | var serviceName = _configuration["Search:ServiceName"]; 21 | 22 | var searchCredentials = new AzureKeyCredential(key); 23 | var searchServiceClient = new SearchIndexClient(serviceName.GetSearchServiceUri(), searchCredentials); 24 | 25 | // Unable to use GetIndexNamesAsync due to the following: https://github.com/Azure/azure-sdk-for-net/issues/15590 26 | var result = searchServiceClient.GetIndexesAsync(); 27 | 28 | await foreach (var index in result) 29 | { 30 | await searchServiceClient.DeleteIndexAsync(index.Name); 31 | } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Operations/OperationsHttpFunction.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.Http; 2 | using Microsoft.AspNetCore.Http; 3 | using Microsoft.AspNetCore.Mvc; 4 | using Microsoft.Azure.WebJobs; 5 | using Microsoft.Azure.WebJobs.Extensions.Http; 6 | using Microsoft.Extensions.Logging; 7 | using System.Threading.Tasks; 8 | 9 | namespace Eklee.Azure.Functions.GraphQl.Example.Operations 10 | { 11 | public static class OperationsHttpFunction 12 | { 13 | [ExecutionContextDependencyInjection(typeof(OperationsModule))] 14 | [FunctionName("DeleteSearchIndexes")] 15 | public static async Task Add( 16 | [HttpTrigger(AuthorizationLevel.Anonymous, "delete", Route = "searchIndexes")] HttpRequest req, 17 | ILogger log, 18 | ExecutionContext executionContext) 19 | { 20 | var operations = executionContext.Resolve(); 21 | await operations.DeleteSearchIndexes(); 22 | return new OkResult(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Operations/OperationsModule.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl.Example.Operations 4 | { 5 | public class OperationsModule : Module 6 | { 7 | protected override void Load(ContainerBuilder builder) 8 | { 9 | builder.RegisterType().As().SingleInstance(); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/PagingBooksGraphFunction.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Eklee.Azure.Functions.Http; 3 | using Microsoft.AspNetCore.Mvc; 4 | using Microsoft.Azure.WebJobs; 5 | using Microsoft.AspNetCore.Http; 6 | using Microsoft.Extensions.Logging; 7 | using Microsoft.Azure.WebJobs.Extensions.Http; 8 | 9 | namespace Eklee.Azure.Functions.GraphQl.Example 10 | { 11 | public static class PagingBooksGraphFunction 12 | { 13 | [ExecutionContextDependencyInjection(typeof(MyPagingBooksModule))] 14 | [FunctionName("paginggraph")] 15 | public static async Task Run( 16 | [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = "pagingbooks/graph")] HttpRequest req, 17 | ILogger log, 18 | ExecutionContext executionContext) 19 | { 20 | return await executionContext.ProcessGraphQlRequest(req); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/TestDocumentDb/Events/BarMutationPostAction.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Eklee.Azure.Functions.GraphQl.Repository; 3 | using Microsoft.Extensions.Logging; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl.Example.TestDocumentDb.Events 6 | { 7 | public class BarMutationPostAction : FooBarBase, IMutationPostAction 8 | { 9 | private readonly ILogger _logger; 10 | 11 | public BarMutationPostAction(ILogger logger) 12 | { 13 | _logger = logger; 14 | } 15 | 16 | public int ExecutionOrder => 1; 17 | 18 | public Task TryHandlePostItem(MutationActionItem mutationActionItem) 19 | { 20 | _logger.LogInformation($"BarMutationPostAction {GetBody(mutationActionItem)}"); 21 | 22 | return Task.CompletedTask; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/TestDocumentDb/Events/BarMutationPreAction.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Eklee.Azure.Functions.GraphQl.Repository; 3 | using Microsoft.Extensions.Logging; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl.Example.TestDocumentDb.Events 6 | { 7 | public class BarMutationPreAction : FooBarBase, IMutationPreAction 8 | { 9 | private readonly ILogger _logger; 10 | 11 | public int ExecutionOrder => 1; 12 | 13 | public BarMutationPreAction(ILogger logger) 14 | { 15 | _logger = logger; 16 | } 17 | public Task TryHandlePreItem(MutationActionItem mutationActionItem) 18 | { 19 | _logger.LogInformation($"BarMutationPreAction {GetBody(mutationActionItem)}"); 20 | 21 | return Task.CompletedTask; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/TestDocumentDb/Events/FooBarBase.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.GraphQl.Repository; 2 | using Newtonsoft.Json; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Example.TestDocumentDb.Events 5 | { 6 | public abstract class FooBarBase 7 | { 8 | protected string GetBody(MutationActionItem mutationActionItem) 9 | { 10 | if (mutationActionItem.Item != null) 11 | { 12 | return JsonConvert.SerializeObject(mutationActionItem.Item); 13 | } 14 | 15 | if (mutationActionItem.Items != null) 16 | { 17 | return JsonConvert.SerializeObject(mutationActionItem.Items); 18 | } 19 | 20 | if (mutationActionItem.ObjectItem != null) 21 | { 22 | return JsonConvert.SerializeObject(mutationActionItem.ObjectItem); 23 | } 24 | 25 | if (mutationActionItem.ObjectItems != null) 26 | { 27 | return JsonConvert.SerializeObject(mutationActionItem.ObjectItems); 28 | } 29 | 30 | return ""; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/TestDocumentDb/Events/FooMutationPostAction.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Eklee.Azure.Functions.GraphQl.Repository; 3 | using Microsoft.Extensions.Logging; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl.Example.TestDocumentDb.Events 6 | { 7 | public class FooMutationPostAction : FooBarBase, IMutationPostAction 8 | { 9 | private readonly ILogger _logger; 10 | 11 | public int ExecutionOrder => 1; 12 | 13 | public FooMutationPostAction(ILogger logger) 14 | { 15 | _logger = logger; 16 | } 17 | public Task TryHandlePostItem(MutationActionItem mutationActionItem) 18 | { 19 | _logger.LogInformation($"FooMutationPostAction {GetBody(mutationActionItem)}"); 20 | 21 | return Task.CompletedTask; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/TestDocumentDb/Events/FooMutationPreAction.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Eklee.Azure.Functions.GraphQl.Repository; 3 | using Microsoft.Extensions.Logging; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl.Example.TestDocumentDb.Events 6 | { 7 | public class FooMutationPreAction : FooBarBase, IMutationPreAction 8 | { 9 | private readonly ILogger _logger; 10 | 11 | public int ExecutionOrder => 1; 12 | 13 | public FooMutationPreAction(ILogger logger) 14 | { 15 | _logger = logger; 16 | } 17 | public Task TryHandlePreItem(MutationActionItem mutationActionItem) 18 | { 19 | _logger.LogInformation($"FooMutationPreAction {GetBody(mutationActionItem)}"); 20 | 21 | return Task.CompletedTask; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/TestDocumentDb/Query/GetModel7FromConnectionEdgeExtensions.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.GraphQl.Connections; 2 | using Eklee.Azure.Functions.GraphQl.Example.Models; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | 6 | namespace Eklee.Azure.Functions.GraphQl.Example.TestDocumentDb.Query 7 | { 8 | public static class GetModel7FromConnectionEdgeExtensions 9 | { 10 | public static void AddGetModel7FromConnectionEdge(this TestDocumentDbQuery current, QueryBuilderFactory queryBuilderFactory) 11 | { 12 | // This query is really only meant to demostrate the ability to query for connection edges from the node itself 13 | // even if user's query does not include the connection model. This is achieved via WithSourceIdFromSource. 14 | // Typically, the use case may be that the user is performing a search (which doesn't use connection model). This 15 | // means as a developer, you may want to query the connection edge yourself to figure out the child node hanging on 16 | // the connection model. 17 | queryBuilderFactory.Create(current, "GetModel7FromConnectionEdge") 18 | .WithParameterBuilder() 19 | .BeginQuery().WithProperty(x => x.Id) 20 | .BuildQueryResult(ctx => 21 | { 22 | ctx.Items["idList"] = ctx.GetQueryResults().Select(x => (object)x.Id).ToList(); 23 | }) 24 | .WithConnectionEdgeBuilder() 25 | .WithSourceIdFromSource(x => (List)x.Items["idList"]) 26 | .BuildConnectionEdgeParameters(ctx => 27 | { 28 | var connectionEdges = ctx.GetResults(); 29 | 30 | }) 31 | .BuildQuery() 32 | .BuildWithSingleResult(); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/TestDocumentDb/TestDocumentDbGraphFunction.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Eklee.Azure.Functions.Http; 3 | using Microsoft.AspNetCore.Http; 4 | using Microsoft.AspNetCore.Mvc; 5 | using Microsoft.Azure.WebJobs; 6 | using Microsoft.Azure.WebJobs.Extensions.Http; 7 | using Microsoft.Extensions.Logging; 8 | 9 | namespace Eklee.Azure.Functions.GraphQl.Example.TestDocumentDb 10 | { 11 | public static class TestDocumentDbGraphFunction 12 | { 13 | [ExecutionContextDependencyInjection(typeof(TestDocumentDbModule))] 14 | [FunctionName("TestDocumentDb")] 15 | public static async Task Run( 16 | [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = "testdocumentdb/graph")] HttpRequest req, 17 | ILogger log, 18 | ExecutionContext executionContext) 19 | { 20 | return await executionContext.ProcessGraphQlRequest(req); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/TestDocumentDb/TestDocumentDbModule.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | using Eklee.Azure.Functions.GraphQl.Example.TestDocumentDb.Events; 3 | using Eklee.Azure.Functions.GraphQl.Example.Validations; 4 | using Eklee.Azure.Functions.GraphQl.Repository; 5 | using Eklee.Azure.Functions.GraphQl.Validations; 6 | using Eklee.Azure.Functions.Http; 7 | using Microsoft.Extensions.Caching.Distributed; 8 | 9 | namespace Eklee.Azure.Functions.GraphQl.Example.TestDocumentDb 10 | { 11 | public class TestDocumentDbModule : Module 12 | { 13 | protected override void Load(ContainerBuilder builder) 14 | { 15 | builder.UseDistributedCache(); 16 | 17 | builder.RegisterGraphQl(); 18 | builder.RegisterType(); 19 | builder.RegisterType(); 20 | builder.UseDataAnnotationsValidation(); 21 | builder.RegisterType().As(); 22 | 23 | builder.RegisterType().As(); 24 | builder.RegisterType().As(); 25 | 26 | builder.RegisterType().As(); 27 | builder.RegisterType().As(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/TestDocumentDb/TestDocumentDbSchema.cs: -------------------------------------------------------------------------------- 1 | using GraphQL.Types; 2 | using System; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Example.TestDocumentDb 5 | { 6 | public class TestDocumentDbSchema : Schema 7 | { 8 | public TestDocumentDbSchema(IServiceProvider resolver, TestDocumentDbQuery query, TestDocumentDbMutation mutation) : 9 | base(resolver) 10 | { 11 | Query = query; 12 | Mutation = mutation; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/TestDocumentDbWithPermissions/TestDocumentDbWithPermissionsFunction.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.Http; 2 | using Microsoft.AspNetCore.Http; 3 | using Microsoft.AspNetCore.Mvc; 4 | using Microsoft.Azure.WebJobs; 5 | using Microsoft.Azure.WebJobs.Extensions.Http; 6 | using Microsoft.Extensions.Logging; 7 | using System.Threading.Tasks; 8 | 9 | namespace Eklee.Azure.Functions.GraphQl.Example.TestDocumentDbWithPermissions 10 | { 11 | public static class TestDocumentDbWithPermissionsFunction 12 | { 13 | [ExecutionContextDependencyInjection(typeof(TestDocumentDbWithPermissionsModule))] 14 | [FunctionName("TestDocumentDbWithPermissions")] 15 | public static async Task Run( 16 | [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = "testdocumentdbwithpermissions/graph")] HttpRequest req, 17 | ILogger log, 18 | ExecutionContext executionContext) 19 | { 20 | return await executionContext.ProcessGraphQlRequest(req); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/TestDocumentDbWithPermissions/TestDocumentDbWithPermissionsModule.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | using Eklee.Azure.Functions.GraphQl.Example.Validations; 3 | using Eklee.Azure.Functions.GraphQl.Validations; 4 | using Eklee.Azure.Functions.Http; 5 | using Microsoft.Extensions.Caching.Distributed; 6 | 7 | namespace Eklee.Azure.Functions.GraphQl.Example.TestDocumentDbWithPermissions 8 | { 9 | public class TestDocumentDbWithPermissionsModule : Module 10 | { 11 | protected override void Load(ContainerBuilder builder) 12 | { 13 | builder.UseDistributedCache(); 14 | builder.UseJwtAuthorization(); 15 | builder.RegisterGraphQl(); 16 | builder.RegisterType(); 17 | builder.RegisterType(); 18 | builder.UseDataAnnotationsValidation(); 19 | builder.RegisterType().As(); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/TestDocumentDbWithPermissions/TestDocumentDbWithPermissionsQuery.cs: -------------------------------------------------------------------------------- 1 | using GraphQL.Types; 2 | using Microsoft.Extensions.Logging; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Example.TestDocumentDbWithPermissions 5 | { 6 | public class TestDocumentDbWithPermissionsQuery : ObjectGraphType 7 | { 8 | public TestDocumentDbWithPermissionsQuery(QueryBuilderFactory queryBuilderFactory, ILogger logger) 9 | { 10 | logger.LogInformation("Creating document db queries."); 11 | 12 | Name = "query"; 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/TestDocumentDbWithPermissions/TestDocumentDbWithPermissionsSchema.cs: -------------------------------------------------------------------------------- 1 | using GraphQL.Types; 2 | using System; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Example.TestDocumentDbWithPermissions 5 | { 6 | public class TestDocumentDbWithPermissionsSchema : Schema 7 | { 8 | public TestDocumentDbWithPermissionsSchema(IServiceProvider resolver, TestDocumentDbWithPermissionsQuery query, TestDocumentDbWithPermissionsMutation mutation) : 9 | base(resolver) 10 | { 11 | Query = query; 12 | Mutation = mutation; 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/TestInMemory/TestInMemoryGraphFunction.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Eklee.Azure.Functions.Http; 3 | using Microsoft.AspNetCore.Http; 4 | using Microsoft.AspNetCore.Mvc; 5 | using Microsoft.Azure.WebJobs; 6 | using Microsoft.Azure.WebJobs.Extensions.Http; 7 | using Microsoft.Extensions.Logging; 8 | 9 | namespace Eklee.Azure.Functions.GraphQl.Example.TestInMemory 10 | { 11 | public static class TestInMemoryGraphFunction 12 | { 13 | [ExecutionContextDependencyInjection(typeof(TestInMemoryModule))] 14 | [FunctionName("TestInMemory")] 15 | public static async Task Run( 16 | [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = "testinmemory/graph")] HttpRequest req, 17 | ILogger log, 18 | ExecutionContext executionContext) 19 | { 20 | return await executionContext.ProcessGraphQlRequest(req); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/TestInMemory/TestInMemoryModule.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | using Eklee.Azure.Functions.Http; 3 | using Microsoft.Extensions.Caching.Distributed; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl.Example.TestInMemory 6 | { 7 | public class TestInMemoryModule : Module 8 | { 9 | protected override void Load(ContainerBuilder builder) 10 | { 11 | builder.UseDistributedCache(); 12 | 13 | builder.RegisterGraphQl(); 14 | builder.RegisterType(); 15 | builder.RegisterType(); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/TestInMemory/TestInMemoryMutation.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.GraphQl.Example.Models; 2 | using GraphQL.Types; 3 | using Microsoft.Extensions.Configuration; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl.Example.TestInMemory 6 | { 7 | public class TestInMemoryMutation : ObjectGraphType 8 | { 9 | public TestInMemoryMutation(InputBuilderFactory inputBuilderFactory, IConfiguration configuration) 10 | { 11 | Name = "mutation"; 12 | 13 | inputBuilderFactory.Create(this) 14 | .ConfigureInMemory() 15 | .BuildInMemory() 16 | .DeleteAll(() => new Status { Message = "All Model1 have been removed." }) 17 | .Build(); 18 | 19 | inputBuilderFactory.Create(this) 20 | .ConfigureInMemory() 21 | .BuildInMemory() 22 | .DeleteAll(() => new Status { Message = "All Model2 have been removed." }) 23 | .Build(); 24 | 25 | inputBuilderFactory.Create(this) 26 | .ConfigureInMemory() 27 | .BuildInMemory() 28 | .DeleteAll(() => new Status { Message = "All Model3 have been removed." }) 29 | .Build(); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/TestInMemory/TestInMemoryQuery.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Eklee.Azure.Functions.GraphQl.Example.Models; 3 | using GraphQL.Types; 4 | using Microsoft.Extensions.Logging; 5 | 6 | namespace Eklee.Azure.Functions.GraphQl.Example.TestInMemory 7 | { 8 | public class TestInMemoryQuery : ObjectGraphType 9 | { 10 | public TestInMemoryQuery(QueryBuilderFactory queryBuilderFactory, ILogger logger) 11 | { 12 | logger.LogInformation("Creating in memory queries."); 13 | 14 | Name = "query"; 15 | 16 | queryBuilderFactory.Create(this, "searchModel1", "Search for a single Model 1 by Id") 17 | .WithCache(TimeSpan.FromSeconds(15)) 18 | .WithParameterBuilder() 19 | .WithProperty(x => x.Id) 20 | .BuildQuery() 21 | .BuildWithSingleResult(); 22 | 23 | queryBuilderFactory.Create(this, "searchModel2", "Search for a single Model 2 by Id") 24 | .WithCache(TimeSpan.FromSeconds(15)) 25 | .WithParameterBuilder() 26 | .WithProperty(x => x.Id) 27 | .BuildQuery() 28 | .BuildWithSingleResult(); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/TestInMemory/TestInMemorySchema.cs: -------------------------------------------------------------------------------- 1 | using GraphQL.Types; 2 | using System; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Example.TestInMemory 5 | { 6 | public class TestInMemorySchema : Schema 7 | { 8 | public TestInMemorySchema(IServiceProvider resolver, TestInMemoryQuery query, TestInMemoryMutation mutation) : 9 | base(resolver) 10 | { 11 | Query = query; 12 | Mutation = mutation; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/TestSearch/Models/MySearch1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.ComponentModel.DataAnnotations; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl.Example.TestSearch.Models 6 | { 7 | public class MySearch1 8 | { 9 | [Key] 10 | [Description("Id")] 11 | public string Id { get; set; } 12 | 13 | [Description("IntField")] 14 | public string IntField { get; set; } 15 | 16 | 17 | [Description("DoubleField")] 18 | public string DoubleField { get; set; } 19 | 20 | 21 | [Description("DateField")] 22 | public DateTime DateField { get; set; } 23 | 24 | 25 | [Description("Field")] 26 | public string Field { get; set; } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/TestSearch/Models/MySearch2.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.ComponentModel.DataAnnotations; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl.Example.TestSearch.Models 6 | { 7 | public class MySearch2 8 | { 9 | [Key] 10 | [Description("Id")] 11 | public string Id { get; set; } 12 | 13 | [Description("IntField")] 14 | public string IntField { get; set; } 15 | 16 | 17 | [Description("DoubleField")] 18 | public string DoubleField { get; set; } 19 | 20 | 21 | [Description("DateField")] 22 | public DateTime DateField { get; set; } 23 | 24 | 25 | [Description("Field")] 26 | public string Field { get; set; } 27 | } 28 | } -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/TestSearch/Models/MySearch3.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.GraphQl.Repository.Search; 2 | using System; 3 | using System.ComponentModel; 4 | using System.ComponentModel.DataAnnotations; 5 | 6 | namespace Eklee.Azure.Functions.GraphQl.Example.TestSearch.Models 7 | { 8 | public class MySearch3 9 | { 10 | [Key] 11 | [Description("Id")] 12 | public string Id { get; set; } 13 | 14 | [IsFilterable] 15 | [IsFacetable] 16 | [Description("IntField")] 17 | public int IntField { get; set; } 18 | 19 | [IsFilterable] 20 | [IsFacetable] 21 | [Description("DoubleField")] 22 | public double DoubleField { get; set; } 23 | 24 | [IsFilterable] 25 | [IsFacetable] 26 | [Description("DateField")] 27 | public DateTime DateField { get; set; } 28 | 29 | [IsFilterable] 30 | [IsFacetable] 31 | [Description("Field")] 32 | public string Field { get; set; } 33 | 34 | [IsFilterable] 35 | [IsFacetable] 36 | [Description("FieldTwo")] 37 | public string FieldTwo { get; set; } 38 | 39 | [IsFilterable] 40 | [IsFacetable] 41 | [Description("FieldThree")] 42 | public string FieldThree { get; set; } 43 | } 44 | } -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/TestSearch/Models/MySearchResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.ComponentModel.DataAnnotations; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl.Example.TestSearch.Models 6 | { 7 | public class MySearchResult 8 | { 9 | [Key] 10 | [Description("Id")] 11 | public string Id { get; set; } 12 | 13 | [Description("IntField")] 14 | public int IntField { get; set; } 15 | 16 | [Description("DoubleField")] 17 | public double DoubleField { get; set; } 18 | 19 | [Description("DateField")] 20 | public DateTime DateField { get; set; } 21 | 22 | [Description("Field")] 23 | public string Field { get; set; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/TestSearch/Models/MySearchResult2.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.GraphQl.Repository.Search; 2 | using System.Collections.Generic; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Example.TestSearch.Models 5 | { 6 | public class MySearchResult2 7 | { 8 | public MySearchResult2() 9 | { 10 | Aggregates = new List(); 11 | } 12 | 13 | public List Results { get; set; } 14 | 15 | public List Aggregates { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/TestSearch/TestSearchGraphFunction.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Eklee.Azure.Functions.Http; 3 | using Microsoft.AspNetCore.Http; 4 | using Microsoft.AspNetCore.Mvc; 5 | using Microsoft.Azure.WebJobs; 6 | using Microsoft.Azure.WebJobs.Extensions.Http; 7 | using Microsoft.Extensions.Logging; 8 | 9 | namespace Eklee.Azure.Functions.GraphQl.Example.TestSearch 10 | { 11 | public static class TestSearchGraphFunction 12 | { 13 | [ExecutionContextDependencyInjection(typeof(TestSearchModule))] 14 | [FunctionName("TestSearch")] 15 | public static async Task Run( 16 | [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = "testsearch/graph")] HttpRequest req, 17 | ILogger log, 18 | ExecutionContext executionContext) 19 | { 20 | return await executionContext.ProcessGraphQlRequest(req); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/TestSearch/TestSearchModule.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | using Eklee.Azure.Functions.Http; 3 | using Microsoft.Extensions.Caching.Distributed; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl.Example.TestSearch 6 | { 7 | public class TestSearchModule : Module 8 | { 9 | protected override void Load(ContainerBuilder builder) 10 | { 11 | builder.UseDistributedCache(); 12 | 13 | builder.RegisterGraphQl(); 14 | builder.RegisterType(); 15 | builder.RegisterType(); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/TestSearch/TestSearchSchema.cs: -------------------------------------------------------------------------------- 1 | using GraphQL.Types; 2 | using System; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Example.TestSearch 5 | { 6 | public class TestSearchSchema : Schema 7 | { 8 | public TestSearchSchema(IServiceProvider resolver, TestSearchQuery query, TestSearchMutation mutation) : 9 | base(resolver) 10 | { 11 | Query = query; 12 | Mutation = mutation; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/TestSearch2/Models/MySearch4.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.GraphQl.Attributes; 2 | using Eklee.Azure.Functions.GraphQl.Repository.Search; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.ComponentModel; 6 | using System.ComponentModel.DataAnnotations; 7 | 8 | namespace Eklee.Azure.Functions.GraphQl.Example.TestSearch2.Models 9 | { 10 | public class MySearch4 11 | { 12 | [AutoId] 13 | [Key] 14 | [Description("Id")] 15 | public string Id { get; set; } 16 | 17 | [AutoDateTime(AutoDateTimeTypes.UtcToday)] 18 | [Description("DateField")] 19 | [ModelField(false)] 20 | public DateTime Created { get; set; } 21 | 22 | [Description("Field")] 23 | public string Field { get; set; } 24 | 25 | [IsFilterable] 26 | [IsFacetable] 27 | [Description("State")] 28 | public string State { get; set; } 29 | 30 | [Description("List5")] 31 | public List List5 { get; set; } 32 | 33 | [Description("List6")] 34 | public List List6 { get; set; } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/TestSearch2/Models/MySearch4Result.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.GraphQl.Repository.Search; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl.Example.TestSearch2.Models 6 | { 7 | public class MySearch4Result 8 | { 9 | [Description("Results")] 10 | public List Results { get; set; } 11 | 12 | [Description("List of search aggregates.")] 13 | public List Aggregates { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/TestSearch2/Models/MySearch5.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Example.TestSearch2.Models 5 | { 6 | public class MySearch5 7 | { 8 | [Key] 9 | [Description("Id")] 10 | public string Id { get; set; } 11 | 12 | [Description("IntField")] 13 | public int IntField { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/TestSearch2/Models/MySearch6.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel; 3 | using System.ComponentModel.DataAnnotations; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl.Example.TestSearch2.Models 6 | { 7 | public class MySearch6 8 | { 9 | [Key] 10 | [Description("Id")] 11 | public string Id { get; set; } 12 | 13 | [Description("StrField")] 14 | public string StrField { get; set; } 15 | 16 | public List List7 { get; set; } 17 | 18 | public MySearch8 MySearch8 { get; set; } 19 | } 20 | } -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/TestSearch2/Models/MySearch7.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Example.TestSearch2.Models 5 | { 6 | public class MySearch7 7 | { 8 | [Key] 9 | [Description("Id")] 10 | public string Id { get; set; } 11 | 12 | [Description("DobField")] 13 | public double DobField { get; set; } 14 | } 15 | } -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/TestSearch2/Models/MySearch8.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace Eklee.Azure.Functions.GraphQl.Example.TestSearch2.Models 4 | { 5 | public class MySearch8 6 | { 7 | [Description("Id")] 8 | public string Id { get; set; } 9 | 10 | [Description("StrField")] 11 | public string StrField { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/TestSearch2/TestSearchGraphFunction2.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Eklee.Azure.Functions.Http; 3 | using Microsoft.AspNetCore.Http; 4 | using Microsoft.AspNetCore.Mvc; 5 | using Microsoft.Azure.WebJobs; 6 | using Microsoft.Azure.WebJobs.Extensions.Http; 7 | using Microsoft.Extensions.Logging; 8 | 9 | namespace Eklee.Azure.Functions.GraphQl.Example.TestSearch2 10 | { 11 | public static class TestSearchGraphFunction2 12 | { 13 | [ExecutionContextDependencyInjection(typeof(TestSearchModule2))] 14 | [FunctionName("TestSearch2")] 15 | public static async Task Run( 16 | [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = "testsearch2/graph")] HttpRequest req, 17 | ILogger log, 18 | ExecutionContext executionContext) 19 | { 20 | return await executionContext.ProcessGraphQlRequest(req); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/TestSearch2/TestSearchModule2.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | using Eklee.Azure.Functions.Http; 3 | using Microsoft.Extensions.Caching.Distributed; 4 | 5 | namespace Eklee.Azure.Functions.GraphQl.Example.TestSearch2 6 | { 7 | public class TestSearchModule2 : Module 8 | { 9 | protected override void Load(ContainerBuilder builder) 10 | { 11 | builder.UseDistributedCache(); 12 | builder.UseSystemModelTransformers(); 13 | builder.RegisterGraphQl(); 14 | builder.RegisterType(); 15 | builder.RegisterType(); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/TestSearch2/TestSearchMutation2.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.GraphQl.Example.Models; 2 | using Eklee.Azure.Functions.GraphQl.Example.TestSearch2.Models; 3 | using GraphQL.Types; 4 | using Microsoft.Extensions.Configuration; 5 | 6 | namespace Eklee.Azure.Functions.GraphQl.Example.TestSearch2 7 | { 8 | public class TestSearchMutation2 : ObjectGraphType 9 | { 10 | public TestSearchMutation2(InputBuilderFactory inputBuilderFactory, IConfiguration configuration) 11 | { 12 | Name = "mutation"; 13 | 14 | var api = configuration["Search:ApiKey"]; 15 | var serviceName = configuration["Search:ServiceName"]; 16 | 17 | inputBuilderFactory.Create(this) 18 | .DeleteAll(() => new Status { Message = "All MySearch searches have been deleted." }) 19 | .ConfigureSearch() 20 | .AddApiKey(api) 21 | .AddServiceName(serviceName) 22 | .AddPrefix("lcl1") 23 | .BuildSearch() 24 | .Build(); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/TestSearch2/TestSearchQuery2.cs: -------------------------------------------------------------------------------- 1 | using Eklee.Azure.Functions.GraphQl.Example.TestSearch2.Models; 2 | using Eklee.Azure.Functions.GraphQl.Repository.Search; 3 | using GraphQL.Types; 4 | using Microsoft.Extensions.Logging; 5 | using System.Collections.Generic; 6 | 7 | namespace Eklee.Azure.Functions.GraphQl.Example.TestSearch2 8 | { 9 | public class TestSearchQuery2 : ObjectGraphType 10 | { 11 | public TestSearchQuery2(QueryBuilderFactory queryBuilderFactory, ILogger logger) 12 | { 13 | logger.LogInformation("Creating queries."); 14 | 15 | Name = "query"; 16 | 17 | queryBuilderFactory.Create(this, "searchModel4", "Search for all Model4") 18 | .WithParameterBuilder() 19 | .BeginSearch() 20 | .Add() 21 | .BuildWithAggregate() 22 | .BuildQueryResult(ctx => 23 | { 24 | var searches = ctx.GetQueryResults(); 25 | 26 | var result = new MySearch4Result(); 27 | result.Results = searches.GetTypeList(); 28 | result.Aggregates = new List(); 29 | 30 | var agg = ctx.GetSystemItems(); 31 | agg.ForEach(a => result.Aggregates.AddRange(a.Aggregates)); 32 | 33 | ctx.SetResults(new List { result }); 34 | 35 | }).BuildQuery().BuildWithSingleResult(); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/TestSearch2/TestSearchSchema2.cs: -------------------------------------------------------------------------------- 1 | using GraphQL.Types; 2 | using System; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Example.TestSearch2 5 | { 6 | public class TestSearchSchema2 : Schema 7 | { 8 | public TestSearchSchema2(IServiceProvider resolver, TestSearchQuery2 query, TestSearchMutation2 mutation) : 9 | base(resolver) 10 | { 11 | Query = query; 12 | Mutation = mutation; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/TestStorage/TestStorageFunctionModule.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | using Eklee.Azure.Functions.GraphQl.Actions.RequestContextValueExtractors; 3 | using Eklee.Azure.Functions.GraphQl.Example.Actions; 4 | using Eklee.Azure.Functions.Http; 5 | using Microsoft.Extensions.Caching.Distributed; 6 | 7 | namespace Eklee.Azure.Functions.GraphQl.Example.TestStorage.Core 8 | { 9 | public class TestStorageFunctionModule : Module 10 | { 11 | protected override void Load(ContainerBuilder builder) 12 | { 13 | builder.UseDistributedCache(); 14 | builder.UseSystemModelTransformers(); 15 | builder.UseValueFromRequestContextGenerator(); 16 | builder.RegisterType().As().SingleInstance(); 17 | 18 | builder.RegisterGraphQl(); 19 | builder.RegisterType(); 20 | builder.RegisterType(); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/TestStorage/TestStorageGraphQLFunction.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Microsoft.AspNetCore.Mvc; 3 | using Microsoft.Azure.WebJobs; 4 | using Microsoft.Azure.WebJobs.Extensions.Http; 5 | using Microsoft.AspNetCore.Http; 6 | using Microsoft.Extensions.Logging; 7 | using Eklee.Azure.Functions.GraphQl.Example.TestStorage.Core; 8 | using Eklee.Azure.Functions.Http; 9 | 10 | namespace Eklee.Azure.Functions.GraphQl.Example.TestStorage 11 | { 12 | public static class GraphQLFunction 13 | { 14 | [ExecutionContextDependencyInjection(typeof(TestStorageFunctionModule))] 15 | [FunctionName("TestStorage")] 16 | public static async Task Run( 17 | [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = "teststorage/graph")] HttpRequest req, 18 | ILogger log, 19 | ExecutionContext executionContext) 20 | { 21 | return await executionContext.ProcessGraphQlRequest(req); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/TestStorage/TestStorageSchemaConfig.cs: -------------------------------------------------------------------------------- 1 | using GraphQL.Types; 2 | using System; 3 | 4 | namespace Eklee.Azure.Functions.GraphQl.Example.TestStorage.Core 5 | { 6 | public class TestStorageSchemaConfig : Schema 7 | { 8 | public TestStorageSchemaConfig(IServiceProvider resolver, 9 | TestStorageQueryConfigObjectGraphType query, 10 | TestStorageMutationObjectGraphType mutation) : base(resolver) 11 | { 12 | Query = query; 13 | Mutation = mutation; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/Validations/MyValidation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Eklee.Azure.Functions.GraphQl.Example.Models; 3 | using Eklee.Azure.Functions.GraphQl.Validations; 4 | using FastMember; 5 | 6 | namespace Eklee.Azure.Functions.GraphQl.Example.Validations 7 | { 8 | public class MyValidation : IModelValidation 9 | { 10 | public bool CanHandle(Type type) 11 | { 12 | return type == typeof(Model4); 13 | } 14 | 15 | public bool TryAssertMemberValueIsValid(Member member, object value, out string errorCode, out string message) 16 | { 17 | if (member.Name == "DateField") 18 | { 19 | DateTime result; 20 | if (DateTime.TryParse(value.ToString(), out result)) 21 | { 22 | if (result == DateTime.MinValue) 23 | { 24 | errorCode = "DateTimeError"; 25 | message = "DateTime cannot be Min Value."; 26 | return false; 27 | } 28 | } 29 | else 30 | { 31 | errorCode = "DateTimeError"; 32 | message = "DateTime is invalid."; 33 | return false; 34 | } 35 | } 36 | 37 | errorCode = null; 38 | message = null; 39 | return true; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Examples/Eklee.Azure.Functions.GraphQl.Example/host.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0" 3 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 ENG KEONG DAVID LEE 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 | -------------------------------------------------------------------------------- /PrepNugetPack.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | [Parameter(Mandatory = $True)][string]$Path) 3 | 4 | $app = "Eklee.Azure.Functions.GraphQl" 5 | $filePath = "$Path\$app\bin\Release\netstandard2.1\bin\$app.dll" 6 | 7 | if (![System.IO.File]::Exists($filePath)){ 8 | Write-Host "Missing $filePath" 9 | Get-ChildItem -Path "$Path\$app\bin\Release\netstandard2.1\bin" 10 | } 11 | 12 | Remove-Item -Path "$Path\$app\bin\Release\netstandard2.1\bin" -Recurse -Force 13 | Copy-Item "$Path\LICENSE" "$Path\LICENSE.txt" -------------------------------------------------------------------------------- /ResetSearch.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | [Parameter(Mandatory=$True)][string]$ResourceGroupName, 3 | [Parameter(Mandatory=$True)][string]$ServiceName) 4 | 5 | $resource = Get-AzResource ` 6 | -ResourceType "Microsoft.Search/searchServices" ` 7 | -ResourceGroupName $ResourceGroupName ` 8 | -ResourceName $ServiceName ` 9 | -ApiVersion 2015-08-19 10 | 11 | # Get the primary admin API key 12 | $primaryKey = (Invoke-AzResourceAction ` 13 | -Action listAdminKeys ` 14 | -ResourceId $resource.ResourceId ` 15 | -ApiVersion 2015-08-19 ` 16 | -Force).PrimaryKey 17 | 18 | $headers = @{ "api-key" = $primaryKey} 19 | 20 | $url = "https://$ServiceName.search.windows.net/indexes?api-version=2019-05-06" 21 | 22 | $response = Invoke-WebRequest -Method GET -Uri $url -ContentType "application/json" -Headers $headers | ConvertFrom-Json 23 | 24 | $names = $response.value | select -Property name 25 | 26 | Write-Host "Removing searches..." 27 | 28 | $names | foreach { 29 | $name = $_.name 30 | Write-Host "Deleting $name" 31 | $url = "https://$ServiceName.search.windows.net/indexes/" + $name + "?api-version=2017-11-11" 32 | Write-Host "Invoking $url" 33 | Invoke-WebRequest -Method DELETE -Uri $url -Headers $headers 34 | } 35 | -------------------------------------------------------------------------------- /ResetTableStorage.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seekdavidlee/Eklee-Azure-Functions-GraphQl/ae74b89cc5286bec131ff79887168178136c5fb3/ResetTableStorage.ps1 -------------------------------------------------------------------------------- /Tests/Deployment/template.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "stackName": { 6 | "defaultValue": "", 7 | "type": "String" 8 | } 9 | }, 10 | "variables": { 11 | "location": "[resourceGroup().location]", 12 | "planName": "[variables('stackName')]", 13 | "stackName": "[replace(parameters('stackName'),'-','')]" 14 | }, 15 | "resources": [ 16 | { 17 | "type": "Microsoft.Search/searchServices", 18 | "sku": { 19 | "name": "free" 20 | }, 21 | "name": "[variables('stackName')]", 22 | "apiVersion": "2015-08-19", 23 | "location": "[variables('location')]", 24 | "scale": null, 25 | "properties": { 26 | "replicaCount": 1, 27 | "partitionCount": 1, 28 | "hostingMode": "Default" 29 | }, 30 | "dependsOn": [] 31 | } 32 | ] 33 | } -------------------------------------------------------------------------------- /version.txt: -------------------------------------------------------------------------------- 1 | 0.37 2 | --------------------------------------------------------------------------------