From 6ed32c155e5ba2f0148eca7fa2df92950ee3c9fe Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Tue, 16 May 2023 17:31:10 -0700 Subject: [PATCH 01/63] WIP, laid out the foundations for the field builders --- .../graphql-aspnet-subscriptions.csproj | 31 +++-- .../GraphQLFieldBuilderExtensions.cs | 25 ++++ .../GraphQLFieldGroupBuilderExtensions.cs | 25 ++++ .../GraphQLMinimalApiExtensions.cs | 114 +++++++++++++++++ .../MinimalApi/BaseGraphQLFieldBuilder.cs | 116 ++++++++++++++++++ .../MinimalApi/GraphQLFieldBuilder.cs | 30 +++++ .../MinimalApi/GraphQLFieldGroupBuilder.cs | 51 ++++++++ .../Configuration/SchemaOptions.cs | 6 + .../Execution/MetaDataCollection.cs | 2 +- .../Configuration/IGraphQLFieldBuilder.cs | 38 ++++++ .../IGraphQLFieldGroupBuilder.cs | 46 +++++++ .../Configuration/IGraphQLServerExtension.cs | 7 +- .../Configuration/ISchemaBuilder.cs | 34 +---- .../Configuration/ISchemaBuilder{TSchema}.cs | 52 ++++++++ src/graphql-aspnet/graphql-aspnet.csproj | 31 ++--- ...tGraphQLHttpSubscriptionMiddlewareTests.cs | 18 +-- .../TestData/FakeWebSocketHttpContext.cs | 80 ++++++++++++ .../Engine/TestData/FakeWebSocketManager.cs | 29 +++++ .../MutlipartRequests/ConfigTests.cs | 1 - ...ltipartRequestGraphQLHttpProcessorTests.cs | 1 - .../MultipartRequestPayloadAssemblerTests.cs | 1 - .../Web/GetRequestTests.cs | 11 +- 22 files changed, 663 insertions(+), 86 deletions(-) create mode 100644 src/graphql-aspnet/Configuration/GraphQLFieldBuilderExtensions.cs create mode 100644 src/graphql-aspnet/Configuration/GraphQLFieldGroupBuilderExtensions.cs create mode 100644 src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions.cs create mode 100644 src/graphql-aspnet/Configuration/MinimalApi/BaseGraphQLFieldBuilder.cs create mode 100644 src/graphql-aspnet/Configuration/MinimalApi/GraphQLFieldBuilder.cs create mode 100644 src/graphql-aspnet/Configuration/MinimalApi/GraphQLFieldGroupBuilder.cs create mode 100644 src/graphql-aspnet/Interfaces/Configuration/IGraphQLFieldBuilder.cs create mode 100644 src/graphql-aspnet/Interfaces/Configuration/IGraphQLFieldGroupBuilder.cs create mode 100644 src/graphql-aspnet/Interfaces/Configuration/ISchemaBuilder{TSchema}.cs create mode 100644 src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/TestData/FakeWebSocketHttpContext.cs create mode 100644 src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/TestData/FakeWebSocketManager.cs diff --git a/src/graphql-aspnet-subscriptions/graphql-aspnet-subscriptions.csproj b/src/graphql-aspnet-subscriptions/graphql-aspnet-subscriptions.csproj index fa4a93a7a..6432b4415 100644 --- a/src/graphql-aspnet-subscriptions/graphql-aspnet-subscriptions.csproj +++ b/src/graphql-aspnet-subscriptions/graphql-aspnet-subscriptions.csproj @@ -8,16 +8,12 @@ A package to support subscriptions for GraphQL ASP.NET. Provides the required functionality to setup a websocket connection and perform graphql subscriptions over web sockets. + + - - - - - - - - - + + + @@ -28,7 +24,20 @@ - - + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/GraphQLFieldBuilderExtensions.cs b/src/graphql-aspnet/Configuration/GraphQLFieldBuilderExtensions.cs new file mode 100644 index 000000000..b20ac40e7 --- /dev/null +++ b/src/graphql-aspnet/Configuration/GraphQLFieldBuilderExtensions.cs @@ -0,0 +1,25 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Configuration +{ + using GraphQL.AspNet.Interfaces.Configuration; + + /// + /// Extension methods for configuring specifical aspects of a field generated via + /// the minimal API + /// + public static class GraphQLFieldBuilderExtensions + { + public static IGraphQLFieldBuilder RequireAuthorization(this IGraphQLFieldBuilder template) + { + return template; + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/GraphQLFieldGroupBuilderExtensions.cs b/src/graphql-aspnet/Configuration/GraphQLFieldGroupBuilderExtensions.cs new file mode 100644 index 000000000..38a1567fe --- /dev/null +++ b/src/graphql-aspnet/Configuration/GraphQLFieldGroupBuilderExtensions.cs @@ -0,0 +1,25 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Configuration +{ + using GraphQL.AspNet.Interfaces.Configuration; + + /// + /// Extension methods for configuring specifical aspects of a field group generated via + /// the minimal API + /// + public static class GraphQLFieldGroupBuilderExtensions + { + public static IGraphQLFieldBuilder RequireAuthorization(this IGraphQLFieldBuilder template) + { + return template; + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions.cs b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions.cs new file mode 100644 index 000000000..623f86e2f --- /dev/null +++ b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions.cs @@ -0,0 +1,114 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Configuration +{ + using System; + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Configuration.MinimalApi; + using GraphQL.AspNet.Execution; + using GraphQL.AspNet.Interfaces.Configuration; + using GraphQL.AspNet.Schemas.Structural; + using GraphQL.AspNet.Schemas.TypeSystem; + + /// + /// Extension methods for configuring minimal API methods as fields on the graph. + /// + public static class GraphQLMinimalApiExtensions + { + public static IGraphQLFieldBuilder MapQuery(this SchemaOptions schemaOptions, string template) + { + return MapGraphQLField( + schemaOptions, + GraphOperationType.Query, + template); + } + + public static IGraphQLFieldBuilder MapMutation(this SchemaOptions schemaOptions, string template) + { + return MapGraphQLField( + schemaOptions, + GraphOperationType.Mutation, + template); + } + + public static IGraphQLFieldBuilder MapQuery(this ISchemaBuilder schemaBuilder, string template) + { + Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); + + return MapGraphQLField( + schemaBuilder.Options, + GraphOperationType.Query, + template); + } + + public static IGraphQLFieldBuilder MapMutation(this ISchemaBuilder schemaBuilder, string template, Delegate resolverMethod) + { + Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); + + return MapGraphQLField( + schemaBuilder.Options, + GraphOperationType.Mutation, + template); + } + + public static IGraphQLFieldBuilder MapQuery(this IGraphQLFieldGroupBuilder groupBuilder, string template, Delegate resolverMethod) + { + Validation.ThrowIfNull(groupBuilder, nameof(groupBuilder)); + + return MapGraphQLField( + groupBuilder.Options, + GraphOperationType.Query, + template); + } + + public static IGraphQLFieldBuilder MapMutation(this IGraphQLFieldGroupBuilder groupBuilder, string template, Delegate resolverMethod) + { + Validation.ThrowIfNull(groupBuilder, nameof(groupBuilder)); + + return MapGraphQLField( + groupBuilder.Options, + GraphOperationType.Mutation, + template); + } + + public static IGraphQLFieldGroupBuilder MapGroup(this ISchemaBuilder schemaBuilder, string template) + { + return MapGroup(schemaBuilder?.Options, template); + } + + public static IGraphQLFieldGroupBuilder MapGroup(this SchemaOptions schemaOptions, string template) + { + return new GraphQLFieldGroupBuilder(schemaOptions, template); + } + + public static IGraphQLFieldGroupBuilder MapGroup(this IGraphQLFieldGroupBuilder groupBuilder, string subTemplate) + { + return new GraphQLFieldGroupBuilder(groupBuilder, subTemplate); + } + + public static IGraphQLFieldBuilder MapGraphQLField( + SchemaOptions schemaOptions, + GraphOperationType operationType, + string pathTemplate) + { + schemaOptions = Validation.ThrowIfNullOrReturn(schemaOptions, nameof(schemaOptions)); + pathTemplate = Validation.ThrowIfNullWhiteSpaceOrReturn(pathTemplate, nameof(pathTemplate)); + + var path = new SchemaItemPath((SchemaItemCollections)operationType, pathTemplate); + + var fieldTemplate = new GraphQLFieldBuilder( + schemaOptions, + path.Path); + + schemaOptions.AddFieldTemplate(fieldTemplate); + return fieldTemplate; + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/MinimalApi/BaseGraphQLFieldBuilder.cs b/src/graphql-aspnet/Configuration/MinimalApi/BaseGraphQLFieldBuilder.cs new file mode 100644 index 000000000..c7bf4ba6d --- /dev/null +++ b/src/graphql-aspnet/Configuration/MinimalApi/BaseGraphQLFieldBuilder.cs @@ -0,0 +1,116 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Configuration.MinimalApi +{ + using System.Collections; + using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Interfaces.Configuration; + using GraphQL.AspNet.Schemas.Structural; + using Microsoft.Extensions.Options; + + /// + /// An abstract class containing all the common elements across minimal field builders and + /// their supporting classes. + /// + internal abstract class BaseGraphQLFieldBuilder : IReadOnlyDictionary + { + private Dictionary _dataElements; + private IGraphQLFieldGroupBuilder _parent; + private string _partialPathTemplate; + + /// + /// Initializes a new instance of the class. + /// + /// The schema options where this field item + /// is being defined. + /// The partial path template defined for this + /// individual entity. + protected BaseGraphQLFieldBuilder( + SchemaOptions options, + string partialPathTemplate) + { + _parent = null; + this.Options = Validation.ThrowIfNullOrReturn(options, nameof(options)); + + _partialPathTemplate = partialPathTemplate?.Trim() ?? string.Empty; + _dataElements = new Dictionary(); + } + + /// + /// Initializes a new instance of the class. + /// + /// The group builder from which this entity is being created. + /// The partial path template defined for this + /// individual entity. + protected BaseGraphQLFieldBuilder( + IGraphQLFieldGroupBuilder groupBuilder, + string partialPathTemplate) + { + _parent = Validation.ThrowIfNullOrReturn(groupBuilder, nameof(groupBuilder)); + this.Options = Validation.ThrowIfNullOrReturn(groupBuilder?.Options, nameof(groupBuilder.Options)); + + _partialPathTemplate = Validation.ThrowIfNullWhiteSpaceOrReturn(partialPathTemplate, nameof(partialPathTemplate)); + _dataElements = new Dictionary(); + } + + /// + public bool ContainsKey(string key) + { + return _dataElements.ContainsKey(key); + } + + /// + public bool TryGetValue(string key, out object value) + { + return _dataElements.TryGetValue(key, out value); + } + + /// + public IEnumerator> GetEnumerator() + { + return _dataElements.GetEnumerator(); + } + + /// + IEnumerator IEnumerable.GetEnumerator() + { + return this.GetEnumerator(); + } + + /// + public IEnumerable Keys => _dataElements.Keys; + + /// + public IEnumerable Values => _dataElements.Values; + + /// + public int Count => _dataElements.Count; + + /// + public object this[string key] => _dataElements[key]; + + /// + public virtual SchemaOptions Options { get; protected set; } + + /// + public string Template + { + get + { + if (_parent != null) + return SchemaItemPath.Join(_parent.Template, _partialPathTemplate); + + return _partialPathTemplate; + } + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/MinimalApi/GraphQLFieldBuilder.cs b/src/graphql-aspnet/Configuration/MinimalApi/GraphQLFieldBuilder.cs new file mode 100644 index 000000000..631e6e949 --- /dev/null +++ b/src/graphql-aspnet/Configuration/MinimalApi/GraphQLFieldBuilder.cs @@ -0,0 +1,30 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Configuration.MinimalApi +{ + using GraphQL.AspNet.Interfaces.Configuration; + + internal class GraphQLFieldBuilder : BaseGraphQLFieldBuilder, IGraphQLFieldBuilder + { + public GraphQLFieldBuilder( + SchemaOptions schemaOptions, + string fullPathTemplate) + : base(schemaOptions, fullPathTemplate) + { + } + + public GraphQLFieldBuilder( + IGraphQLFieldGroupBuilder groupBuilder, + string partialPathTemplate) + : base(groupBuilder, partialPathTemplate) + { + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/MinimalApi/GraphQLFieldGroupBuilder.cs b/src/graphql-aspnet/Configuration/MinimalApi/GraphQLFieldGroupBuilder.cs new file mode 100644 index 000000000..153eb5656 --- /dev/null +++ b/src/graphql-aspnet/Configuration/MinimalApi/GraphQLFieldGroupBuilder.cs @@ -0,0 +1,51 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Configuration.MinimalApi +{ + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Interfaces.Configuration; + using GraphQL.AspNet.Schemas.Structural; + + /// + /// An internal implementation of + /// used as a base object during minimal api construction. + /// + internal class GraphQLFieldGroupBuilder : BaseGraphQLFieldBuilder, IGraphQLFieldGroupBuilder + { + private IGraphQLFieldGroupBuilder _parent; + private string _partialTemplate; + + /// + /// Initializes a new instance of the class. + /// + /// The schema options that will own the fields created from + /// this builder. + /// The partial field path template + /// that will be prepended to any fields or groups created from this builder. + public GraphQLFieldGroupBuilder( + SchemaOptions options, + string groupTemplate) + : base(options, groupTemplate) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The parent group builder from which + /// this builder will copy its settings. + /// The partial path template to be appended to + /// the parent's already defined template. + public GraphQLFieldGroupBuilder(IGraphQLFieldGroupBuilder parentGroupBuilder, string groupSubTemplate) + : base(parentGroupBuilder, groupSubTemplate) + { + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/SchemaOptions.cs b/src/graphql-aspnet/Configuration/SchemaOptions.cs index 5e09a1ed4..a0c797f6c 100644 --- a/src/graphql-aspnet/Configuration/SchemaOptions.cs +++ b/src/graphql-aspnet/Configuration/SchemaOptions.cs @@ -16,6 +16,7 @@ namespace GraphQL.AspNet.Configuration using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Common.Generics; using GraphQL.AspNet.Configuration.Exceptions; + using GraphQL.AspNet.Configuration.MinimalApi; using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Directives; using GraphQL.AspNet.Interfaces.Configuration; @@ -347,6 +348,11 @@ internal void FinalizeServiceRegistration() } } + internal void AddFieldTemplate(IGraphQLFieldBuilder fieldTemplate) + { + throw new NotImplementedException(); + } + /// /// Gets the classes, enums, structs and other types that need to be /// registered to the schema when its created. diff --git a/src/graphql-aspnet/Execution/MetaDataCollection.cs b/src/graphql-aspnet/Execution/MetaDataCollection.cs index dfd12e371..b4107aa6a 100644 --- a/src/graphql-aspnet/Execution/MetaDataCollection.cs +++ b/src/graphql-aspnet/Execution/MetaDataCollection.cs @@ -33,7 +33,7 @@ public sealed class MetaDataCollection : IEnumerable _localDictionary; diff --git a/src/graphql-aspnet/Interfaces/Configuration/IGraphQLFieldBuilder.cs b/src/graphql-aspnet/Interfaces/Configuration/IGraphQLFieldBuilder.cs new file mode 100644 index 000000000..46ec77cb3 --- /dev/null +++ b/src/graphql-aspnet/Interfaces/Configuration/IGraphQLFieldBuilder.cs @@ -0,0 +1,38 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Interfaces.Configuration +{ + using System.Collections.Generic; + using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Schemas.Structural; + + /// + /// A builder that utilizies a key/value pair system to build up a set of component parts + /// that the templating engine will use to generate a full fledged field in a schema. + /// + public interface IGraphQLFieldBuilder : IReadOnlyDictionary + { + /// + /// Gets the full path template that points to a location in + /// the virtual field tree. + /// + /// + /// e.g. /path1/path2/path3 + /// + /// The fully qualified path template for this builder. + string Template { get; } + + /// + /// Gets the set of schema options under with this field is being defined. + /// + /// The schema options on which this field is being defined. + SchemaOptions Options { get; } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Configuration/IGraphQLFieldGroupBuilder.cs b/src/graphql-aspnet/Interfaces/Configuration/IGraphQLFieldGroupBuilder.cs new file mode 100644 index 000000000..e0d914479 --- /dev/null +++ b/src/graphql-aspnet/Interfaces/Configuration/IGraphQLFieldGroupBuilder.cs @@ -0,0 +1,46 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Interfaces.Configuration +{ + using System.Collections.Generic; + using GraphQL.AspNet.Configuration; + + /// + /// A field builder that can act as a parent for a set of fields. The defined + /// template for this builder will prefix all fields or other field groups created + /// underneath it. Also, all properties and settings, such as authorization requirements, for the "group", are carried + /// into any fields generated. + /// + public interface IGraphQLFieldGroupBuilder : IReadOnlyDictionary + { + // ********************** + // Implementation note (05/23) - Kevin + // This interface is functionally identical to the single field builder + // but is seperate to allow for divation in handling via extension methods and + // potential future development + // ********************** + + /// + /// Gets the full path template that points to a location in + /// the virtual field tree. + /// + /// + /// e.g. /path1/path2/path3 + /// + /// The fully qualified path template for this builder. + string Template { get; } + + /// + /// Gets the set of schema options under with this field is being defined. + /// + /// The schema options on which this field is being defined. + SchemaOptions Options { get; } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Configuration/IGraphQLServerExtension.cs b/src/graphql-aspnet/Interfaces/Configuration/IGraphQLServerExtension.cs index 47e25dda0..712fd5c4c 100644 --- a/src/graphql-aspnet/Interfaces/Configuration/IGraphQLServerExtension.cs +++ b/src/graphql-aspnet/Interfaces/Configuration/IGraphQLServerExtension.cs @@ -40,9 +40,12 @@ public interface IGraphQLServerExtension void Configure(SchemaOptions options); /// - /// Instructs this extension to perform any final setup requirements as part of - /// its configuration during startup. + /// Instructs this extension to perform any final setup requirements before the server starts. /// + /// + /// When this method is called, construction of the DI container is complete and all schemas + /// and types have been created and registered. + /// /// The application builder to register against. May be null in some rare instances /// where the middleware pipeline is not being setup. Usually during some unit testing edge cases. /// The configured service provider completed during setup. In diff --git a/src/graphql-aspnet/Interfaces/Configuration/ISchemaBuilder.cs b/src/graphql-aspnet/Interfaces/Configuration/ISchemaBuilder.cs index 02498c01b..885be25aa 100644 --- a/src/graphql-aspnet/Interfaces/Configuration/ISchemaBuilder.cs +++ b/src/graphql-aspnet/Interfaces/Configuration/ISchemaBuilder.cs @@ -17,42 +17,12 @@ namespace GraphQL.AspNet.Interfaces.Configuration /// /// A builder for performing advanced configuration of a schema's pipeline and processing settings. /// - /// The type of the schema this builder is created for. - public interface ISchemaBuilder - where TSchema : class, ISchema + public interface ISchemaBuilder { /// /// Gets the completed options used to configure this schema. /// - /// The options. + /// The options used to create and configure this builder. SchemaOptions Options { get; } - - /// - /// Gets a builder to construct the field execution pipeline. This pipeline is invoked per field resolution request to generate a - /// piece of data in the process of fulfilling the primary query. - /// - /// The field execution pipeline. - ISchemaPipelineBuilder FieldExecutionPipeline { get; } - - /// - /// Gets a builder to construct the field authorization pipeline. This pipeline is invoked per field resolution request to authorize - /// the user to the field allowing or denying them access to it. - /// - /// The field authorization pipeline. - ISchemaPipelineBuilder SchemaItemSecurityPipeline { get; } - - /// - /// Gets a builder to construct the primary query pipeline. This pipeline oversees the processing of a query and is invoked - /// directly by the http handler. - /// - /// The query execution pipeline. - ISchemaPipelineBuilder QueryExecutionPipeline { get; } - - /// - /// Gets the build useto construct the primary directive execution pipeline. This pipeline oversees the processing of directives against - /// data items for both the type system initial construction as well as during query execution. - /// - /// The directive execution pipeline. - ISchemaPipelineBuilder DirectiveExecutionPipeline { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Configuration/ISchemaBuilder{TSchema}.cs b/src/graphql-aspnet/Interfaces/Configuration/ISchemaBuilder{TSchema}.cs new file mode 100644 index 000000000..052ab9385 --- /dev/null +++ b/src/graphql-aspnet/Interfaces/Configuration/ISchemaBuilder{TSchema}.cs @@ -0,0 +1,52 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Interfaces.Configuration +{ + using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Execution.Contexts; + using GraphQL.AspNet.Interfaces.Middleware; + using GraphQL.AspNet.Interfaces.Schema; + + /// + /// A builder for performing advanced configuration of a schema's pipeline and processing settings. + /// + /// The type of the schema this builder is created for. + public interface ISchemaBuilder : ISchemaBuilder + where TSchema : class, ISchema + { + /// + /// Gets a builder to construct the field execution pipeline. This pipeline is invoked per field resolution request to generate a + /// piece of data in the process of fulfilling the primary query. + /// + /// The field execution pipeline. + ISchemaPipelineBuilder FieldExecutionPipeline { get; } + + /// + /// Gets a builder to construct the field authorization pipeline. This pipeline is invoked per field resolution request to authorize + /// the user to the field allowing or denying them access to it. + /// + /// The field authorization pipeline. + ISchemaPipelineBuilder SchemaItemSecurityPipeline { get; } + + /// + /// Gets a builder to construct the primary query pipeline. This pipeline oversees the processing of a query and is invoked + /// directly by the http handler. + /// + /// The query execution pipeline. + ISchemaPipelineBuilder QueryExecutionPipeline { get; } + + /// + /// Gets the build useto construct the primary directive execution pipeline. This pipeline oversees the processing of directives against + /// data items for both the type system initial construction as well as during query execution. + /// + /// The directive execution pipeline. + ISchemaPipelineBuilder DirectiveExecutionPipeline { get; } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/graphql-aspnet.csproj b/src/graphql-aspnet/graphql-aspnet.csproj index 3c84feaa4..b09a6e95d 100644 --- a/src/graphql-aspnet/graphql-aspnet.csproj +++ b/src/graphql-aspnet/graphql-aspnet.csproj @@ -13,20 +13,9 @@ - - - - - + - - - - - - - @@ -38,8 +27,22 @@ - - + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/DefaultGraphQLHttpSubscriptionMiddlewareTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/DefaultGraphQLHttpSubscriptionMiddlewareTests.cs index 7add63059..61e906cde 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/DefaultGraphQLHttpSubscriptionMiddlewareTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/DefaultGraphQLHttpSubscriptionMiddlewareTests.cs @@ -23,6 +23,7 @@ namespace GraphQL.AspNet.Tests.Engine using GraphQL.AspNet.Schemas; using GraphQL.AspNet.SubscriptionServer; using GraphQL.AspNet.SubscriptionServer.Exceptions; + using GraphQL.AspNet.Tests.Engine.TestData; using GraphQL.AspNet.Tests.Mocks; using Microsoft.AspNetCore.Http; using Moq; @@ -31,23 +32,6 @@ namespace GraphQL.AspNet.Tests.Engine [TestFixture] public class DefaultGraphQLHttpSubscriptionMiddlewareTests { - public class FakeWebSocketManager : WebSocketManager - { - public override bool IsWebSocketRequest => true; - - public override IList WebSocketRequestedProtocols => new List(); - - public override Task AcceptWebSocketAsync(string subProtocol) - { - return Task.FromResult(new FakeWebSocket(WebSocketState.Open) as WebSocket); - } - } - - public class FakeWebSocketHttpContext : DefaultHttpContext - { - public override WebSocketManager WebSockets => new FakeWebSocketManager(); - } - [Test] public async Task NonSocketRequest_AgainstListeningRoute_IsSkipped() { diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/TestData/FakeWebSocketHttpContext.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/TestData/FakeWebSocketHttpContext.cs new file mode 100644 index 000000000..648851090 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/TestData/FakeWebSocketHttpContext.cs @@ -0,0 +1,80 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Engine.TestData +{ + using System; + using System.Collections.Generic; + using System.Security.Claims; + using System.Threading; + using GraphQL.AspNet.Execution.RulesEngine.RuleSets.DocumentConstruction.Steps; + using Microsoft.AspNetCore.Http; + using Microsoft.AspNetCore.Http.Features; + + public class FakeWebSocketHttpContext : HttpContext + { + private DefaultHttpContext _subcontext; + + public FakeWebSocketHttpContext() + { + _subcontext = new DefaultHttpContext(); + } + + public override WebSocketManager WebSockets => new FakeWebSocketManager(); + + public override IFeatureCollection Features => _subcontext.Features; + + public override HttpRequest Request => _subcontext.Request; + + public override HttpResponse Response => _subcontext.Response; + + public override ConnectionInfo Connection => _subcontext.Connection; + + public override ClaimsPrincipal User + { + get => _subcontext.User; + set => _subcontext.User = value; + } + + public override IDictionary Items + { + get => _subcontext.Items; + set => _subcontext.Items = value; + } + + public override IServiceProvider RequestServices + { + get => _subcontext.RequestServices; + set => _subcontext.RequestServices = value; + } + + public override CancellationToken RequestAborted + { + get => _subcontext.RequestAborted; + set => _subcontext.RequestAborted = value; + } + + public override string TraceIdentifier + { + get => _subcontext.TraceIdentifier; + set => _subcontext.TraceIdentifier = value; + } + + public override ISession Session + { + get => _subcontext.Session; + set => _subcontext.Session = value; + } + + public override void Abort() + { + _subcontext.Abort(); + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/TestData/FakeWebSocketManager.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/TestData/FakeWebSocketManager.cs new file mode 100644 index 000000000..17ceff9cb --- /dev/null +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/TestData/FakeWebSocketManager.cs @@ -0,0 +1,29 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Engine.TestData +{ + using System.Collections.Generic; + using System.Net.WebSockets; + using System.Threading.Tasks; + using GraphQL.AspNet.Tests.Mocks; + using Microsoft.AspNetCore.Http; + + public class FakeWebSocketManager : WebSocketManager + { + public override bool IsWebSocketRequest => true; + + public override IList WebSocketRequestedProtocols => new List(); + + public override Task AcceptWebSocketAsync(string subProtocol) + { + return Task.FromResult(new FakeWebSocket(WebSocketState.Open) as WebSocket); + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/ServerExtensions/MutlipartRequests/ConfigTests.cs b/src/unit-tests/graphql-aspnet-tests/ServerExtensions/MutlipartRequests/ConfigTests.cs index 9a97ee82b..3f3ddc00c 100644 --- a/src/unit-tests/graphql-aspnet-tests/ServerExtensions/MutlipartRequests/ConfigTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/ServerExtensions/MutlipartRequests/ConfigTests.cs @@ -25,7 +25,6 @@ namespace GraphQL.AspNet.Tests.ServerExtensions.MutlipartRequests using GraphQL.AspNet.Tests.Framework; using GraphQL.AspNet.Web.Exceptions; using Microsoft.AspNetCore.Http; - using Microsoft.AspNetCore.Http.Internal; using Microsoft.Extensions.Primitives; using Moq; using NUnit.Framework; diff --git a/src/unit-tests/graphql-aspnet-tests/ServerExtensions/MutlipartRequests/MultipartRequestGraphQLHttpProcessorTests.cs b/src/unit-tests/graphql-aspnet-tests/ServerExtensions/MutlipartRequests/MultipartRequestGraphQLHttpProcessorTests.cs index 17f1fd4ba..a50ab4e93 100644 --- a/src/unit-tests/graphql-aspnet-tests/ServerExtensions/MutlipartRequests/MultipartRequestGraphQLHttpProcessorTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/ServerExtensions/MutlipartRequests/MultipartRequestGraphQLHttpProcessorTests.cs @@ -33,7 +33,6 @@ namespace GraphQL.AspNet.Tests.ServerExtensions.MutlipartRequests using GraphQL.AspNet.Tests.Framework.CommonHelpers; using GraphQL.AspNet.Tests.ServerExtensions.MutlipartRequests.TestData; using Microsoft.AspNetCore.Http; - using Microsoft.AspNetCore.Http.Internal; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Primitives; using Moq; diff --git a/src/unit-tests/graphql-aspnet-tests/ServerExtensions/MutlipartRequests/MultipartRequestPayloadAssemblerTests.cs b/src/unit-tests/graphql-aspnet-tests/ServerExtensions/MutlipartRequests/MultipartRequestPayloadAssemblerTests.cs index 269d3e45d..099369d30 100644 --- a/src/unit-tests/graphql-aspnet-tests/ServerExtensions/MutlipartRequests/MultipartRequestPayloadAssemblerTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/ServerExtensions/MutlipartRequests/MultipartRequestPayloadAssemblerTests.cs @@ -25,7 +25,6 @@ namespace GraphQL.AspNet.Tests.ServerExtensions.MutlipartRequests using GraphQL.AspNet.ServerExtensions.MultipartRequests.Model; using GraphQL.AspNet.ServerExtensions.MultipartRequests.Web; using Microsoft.AspNetCore.Http; - using Microsoft.AspNetCore.Http.Internal; using Microsoft.Extensions.Primitives; using Moq; using NUnit.Framework; diff --git a/src/unit-tests/graphql-aspnet-tests/Web/GetRequestTests.cs b/src/unit-tests/graphql-aspnet-tests/Web/GetRequestTests.cs index 13509d591..81a0d9cac 100644 --- a/src/unit-tests/graphql-aspnet-tests/Web/GetRequestTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Web/GetRequestTests.cs @@ -22,7 +22,6 @@ namespace GraphQL.AspNet.Tests.Web using GraphQL.AspNet.Tests.Web.CancelTokenTestData; using GraphQL.AspNet.Tests.Web.WebTestData; using Microsoft.AspNetCore.Http; - using Microsoft.AspNetCore.Http.Internal; using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; @@ -91,7 +90,7 @@ public async Task GETRequest_QueryStringTests(string queryText, int result) RequestServices = scope.ServiceProvider, }; - var request = httpContext.Request as DefaultHttpRequest; + var request = httpContext.Request; request.Method = "GET"; request.QueryString = new QueryString(queryText); @@ -160,7 +159,7 @@ public async Task POSTRequest_TreatedAsGETRequest_WhenQueryStringPresent() }, }; - var request = httpContext.Request as DefaultHttpRequest; + var request = httpContext.Request; request.Method = "POST"; httpContext.RequestServices = scope.ServiceProvider; @@ -213,7 +212,7 @@ public async Task POSTRequest_WithGraphQLContentType_TreatsBodyAsQuery() }, }; - var request = httpContext.Request as DefaultHttpRequest; + var request = httpContext.Request; request.Method = "POST"; request.ContentType = Constants.Web.GRAPHQL_CONTENT_TYPE_HEADER_VALUE; httpContext.RequestServices = scope.ServiceProvider; @@ -258,7 +257,7 @@ public async Task POSTRequest_WithQueryAsBody_WithoutGraphQLContentType_Fails() }, }; - var request = httpContext.Request as DefaultHttpRequest; + var request = httpContext.Request; request.Method = "POST"; httpContext.RequestServices = scope.ServiceProvider; @@ -303,7 +302,7 @@ public async Task CustomAddedRequestItem_MakesItToController() }, }; - var request = httpContext.Request as DefaultHttpRequest; + var request = httpContext.Request; request.Method = "POST"; request.ContentType = Constants.Web.GRAPHQL_CONTENT_TYPE_HEADER_VALUE; httpContext.RequestServices = scope.ServiceProvider; From 5a904760654eb62fb22e57cd6f2dbefe732475f2 Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Sat, 20 May 2023 06:17:13 -0700 Subject: [PATCH 02/63] WIP, building out extension methods for field builder --- .../GraphQLFieldBuilderExtensions.cs | 67 ++++++++++++++++++- .../GraphQLFieldGroupBuilderExtensions.cs | 10 +-- .../MinimalApi/BaseGraphQLFieldBuilder.cs | 58 +++++----------- .../GraphQLFieldBuilderConstants.cs | 11 +++ .../MinimalApi/GraphQLFieldGroupBuilder.cs | 3 - .../Configuration/IGraphQLFieldBuilder.cs | 11 ++- .../IGraphQLFieldGroupBuilder.cs | 10 ++- 7 files changed, 115 insertions(+), 55 deletions(-) create mode 100644 src/graphql-aspnet/Configuration/MinimalApi/GraphQLFieldBuilderConstants.cs diff --git a/src/graphql-aspnet/Configuration/GraphQLFieldBuilderExtensions.cs b/src/graphql-aspnet/Configuration/GraphQLFieldBuilderExtensions.cs index b20ac40e7..5b88c3f05 100644 --- a/src/graphql-aspnet/Configuration/GraphQLFieldBuilderExtensions.cs +++ b/src/graphql-aspnet/Configuration/GraphQLFieldBuilderExtensions.cs @@ -9,7 +9,11 @@ namespace GraphQL.AspNet.Configuration { + using System; + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Configuration.MinimalApi; using GraphQL.AspNet.Interfaces.Configuration; + using Microsoft.AspNetCore.Authorization; /// /// Extension methods for configuring specifical aspects of a field generated via @@ -17,9 +21,68 @@ namespace GraphQL.AspNet.Configuration /// public static class GraphQLFieldBuilderExtensions { - public static IGraphQLFieldBuilder RequireAuthorization(this IGraphQLFieldBuilder template) + /// + /// Adds policy-based authorization requirements to the field. + /// + /// + /// + /// This is similar to + /// adding an [Authorize] attribute to a controller methods. This method can be + /// called more than once. + /// + /// + /// Each subsequent call will append a new policy in a similar fashion + /// as if you added multiple [Authorize] attributes to a controller methods. + /// + /// + /// The field being built. + /// Name of the policy to assign via this authorization. + /// IGraphQLFieldBuilder. + public static IGraphQLFieldBuilder RequireAuthorization( + this IGraphQLFieldBuilder fieldBuilder, + string policyName) { - return template; + Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); + + fieldBuilder.Attributes.Add(new AuthorizeAttribute(policyName)); + return fieldBuilder; + } + + /// + /// Indicates that the field should allow anonymous access. + /// + /// + /// + /// This is similar to adding [AllowAnonymous] to a controller method + /// + /// + /// Any inherited authorization permissions from field groups are automatically + /// dropped from this field instance. + /// + /// + /// The field being built. + /// IGraphQLFieldBuilder. + public static IGraphQLFieldBuilder AllowAnonymous(this IGraphQLFieldBuilder fieldBuilder) + { + Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); + fieldBuilder.Attributes.Add(new AllowAnonymousAttribute()); + return fieldBuilder; + } + + /// + /// Sets the resolver to be used when this field is requested at runtime. + /// + /// + /// If this method is called more than once the previous resolver will be replaced. + /// + /// The field being built. + /// The delegate to assign as the resolver. This method will be + /// parsed to determine input arguments for the field on the target schema. + /// IGraphQLFieldBuilder. + public static IGraphQLFieldBuilder AddResolver(this IGraphQLFieldBuilder fieldBuilder, Delegate resolver) + { + fieldBuilder[GraphQLFieldBuilderConstants.RESOLVER] = resolver; + return fieldBuilder; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/GraphQLFieldGroupBuilderExtensions.cs b/src/graphql-aspnet/Configuration/GraphQLFieldGroupBuilderExtensions.cs index 38a1567fe..eeefda4bb 100644 --- a/src/graphql-aspnet/Configuration/GraphQLFieldGroupBuilderExtensions.cs +++ b/src/graphql-aspnet/Configuration/GraphQLFieldGroupBuilderExtensions.cs @@ -9,7 +9,13 @@ namespace GraphQL.AspNet.Configuration { + using System; + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Configuration.MinimalApi; using GraphQL.AspNet.Interfaces.Configuration; + using GraphQL.AspNet.Interfaces.Schema; + using Microsoft.AspNetCore.Authorization; + using Microsoft.AspNetCore.Builder; /// /// Extension methods for configuring specifical aspects of a field group generated via @@ -17,9 +23,5 @@ namespace GraphQL.AspNet.Configuration /// public static class GraphQLFieldGroupBuilderExtensions { - public static IGraphQLFieldBuilder RequireAuthorization(this IGraphQLFieldBuilder template) - { - return template; - } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/MinimalApi/BaseGraphQLFieldBuilder.cs b/src/graphql-aspnet/Configuration/MinimalApi/BaseGraphQLFieldBuilder.cs index c7bf4ba6d..150a44891 100644 --- a/src/graphql-aspnet/Configuration/MinimalApi/BaseGraphQLFieldBuilder.cs +++ b/src/graphql-aspnet/Configuration/MinimalApi/BaseGraphQLFieldBuilder.cs @@ -9,24 +9,29 @@ namespace GraphQL.AspNet.Configuration.MinimalApi { - using System.Collections; + using System; using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; using GraphQL.AspNet.Common; using GraphQL.AspNet.Interfaces.Configuration; using GraphQL.AspNet.Schemas.Structural; - using Microsoft.Extensions.Options; /// /// An abstract class containing all the common elements across minimal field builders and /// their supporting classes. /// - internal abstract class BaseGraphQLFieldBuilder : IReadOnlyDictionary + internal abstract class BaseGraphQLFieldBuilder : Dictionary { - private Dictionary _dataElements; private IGraphQLFieldGroupBuilder _parent; private string _partialPathTemplate; + /// + /// Prevents a default instance of the class from being created. + /// + private BaseGraphQLFieldBuilder() + { + this.Attributes = new List(); + } + /// /// Initializes a new instance of the class. /// @@ -37,12 +42,12 @@ internal abstract class BaseGraphQLFieldBuilder : IReadOnlyDictionary(); } /// @@ -54,53 +59,20 @@ protected BaseGraphQLFieldBuilder( protected BaseGraphQLFieldBuilder( IGraphQLFieldGroupBuilder groupBuilder, string partialPathTemplate) + : this() { _parent = Validation.ThrowIfNullOrReturn(groupBuilder, nameof(groupBuilder)); this.Options = Validation.ThrowIfNullOrReturn(groupBuilder?.Options, nameof(groupBuilder.Options)); _partialPathTemplate = Validation.ThrowIfNullWhiteSpaceOrReturn(partialPathTemplate, nameof(partialPathTemplate)); - _dataElements = new Dictionary(); - } - - /// - public bool ContainsKey(string key) - { - return _dataElements.ContainsKey(key); - } - - /// - public bool TryGetValue(string key, out object value) - { - return _dataElements.TryGetValue(key, out value); } - /// - public IEnumerator> GetEnumerator() - { - return _dataElements.GetEnumerator(); - } - - /// - IEnumerator IEnumerable.GetEnumerator() - { - return this.GetEnumerator(); - } - - /// - public IEnumerable Keys => _dataElements.Keys; - - /// - public IEnumerable Values => _dataElements.Values; - - /// - public int Count => _dataElements.Count; - - /// - public object this[string key] => _dataElements[key]; - /// public virtual SchemaOptions Options { get; protected set; } + /// + public IList Attributes { get; } + /// public string Template { diff --git a/src/graphql-aspnet/Configuration/MinimalApi/GraphQLFieldBuilderConstants.cs b/src/graphql-aspnet/Configuration/MinimalApi/GraphQLFieldBuilderConstants.cs new file mode 100644 index 000000000..2cfb17aea --- /dev/null +++ b/src/graphql-aspnet/Configuration/MinimalApi/GraphQLFieldBuilderConstants.cs @@ -0,0 +1,11 @@ +namespace GraphQL.AspNet.Configuration.MinimalApi +{ + using System; + using System.Collections.Generic; + using System.Text; + + internal static class GraphQLFieldBuilderConstants + { + public const string RESOLVER = "GraphQL:FieldBuilder:Resolver"; + } +} diff --git a/src/graphql-aspnet/Configuration/MinimalApi/GraphQLFieldGroupBuilder.cs b/src/graphql-aspnet/Configuration/MinimalApi/GraphQLFieldGroupBuilder.cs index 153eb5656..cbd96ca62 100644 --- a/src/graphql-aspnet/Configuration/MinimalApi/GraphQLFieldGroupBuilder.cs +++ b/src/graphql-aspnet/Configuration/MinimalApi/GraphQLFieldGroupBuilder.cs @@ -19,9 +19,6 @@ namespace GraphQL.AspNet.Configuration.MinimalApi /// internal class GraphQLFieldGroupBuilder : BaseGraphQLFieldBuilder, IGraphQLFieldGroupBuilder { - private IGraphQLFieldGroupBuilder _parent; - private string _partialTemplate; - /// /// Initializes a new instance of the class. /// diff --git a/src/graphql-aspnet/Interfaces/Configuration/IGraphQLFieldBuilder.cs b/src/graphql-aspnet/Interfaces/Configuration/IGraphQLFieldBuilder.cs index 46ec77cb3..3e0823f87 100644 --- a/src/graphql-aspnet/Interfaces/Configuration/IGraphQLFieldBuilder.cs +++ b/src/graphql-aspnet/Interfaces/Configuration/IGraphQLFieldBuilder.cs @@ -9,15 +9,15 @@ namespace GraphQL.AspNet.Interfaces.Configuration { + using System; using System.Collections.Generic; using GraphQL.AspNet.Configuration; - using GraphQL.AspNet.Schemas.Structural; /// /// A builder that utilizies a key/value pair system to build up a set of component parts /// that the templating engine will use to generate a full fledged field in a schema. /// - public interface IGraphQLFieldBuilder : IReadOnlyDictionary + public interface IGraphQLFieldBuilder : IDictionary { /// /// Gets the full path template that points to a location in @@ -34,5 +34,12 @@ public interface IGraphQLFieldBuilder : IReadOnlyDictionary /// /// The schema options on which this field is being defined. SchemaOptions Options { get; } + + /// + /// Gets a list of attributes that have been applied to this builder. This mimics + /// the collection of applied attributes to a controller method. + /// + /// The collection of applied attributes. + IList Attributes { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Configuration/IGraphQLFieldGroupBuilder.cs b/src/graphql-aspnet/Interfaces/Configuration/IGraphQLFieldGroupBuilder.cs index e0d914479..f1f9cd6aa 100644 --- a/src/graphql-aspnet/Interfaces/Configuration/IGraphQLFieldGroupBuilder.cs +++ b/src/graphql-aspnet/Interfaces/Configuration/IGraphQLFieldGroupBuilder.cs @@ -9,6 +9,7 @@ namespace GraphQL.AspNet.Interfaces.Configuration { + using System; using System.Collections.Generic; using GraphQL.AspNet.Configuration; @@ -18,7 +19,7 @@ namespace GraphQL.AspNet.Interfaces.Configuration /// underneath it. Also, all properties and settings, such as authorization requirements, for the "group", are carried /// into any fields generated. /// - public interface IGraphQLFieldGroupBuilder : IReadOnlyDictionary + public interface IGraphQLFieldGroupBuilder : IDictionary { // ********************** // Implementation note (05/23) - Kevin @@ -42,5 +43,12 @@ public interface IGraphQLFieldGroupBuilder : IReadOnlyDictionary /// /// The schema options on which this field is being defined. SchemaOptions Options { get; } + + /// + /// Gets a list of attributes that have been applied to this builder. This mimics + /// the collection of applied attributes to a controller method. + /// + /// The collection of applied attributes. + IList Attributes { get; } } } \ No newline at end of file From e82696b38ad118eb2f66d0ae898c5bea3c874e33 Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Sun, 11 Jun 2023 09:54:49 -0700 Subject: [PATCH 03/63] WIP, delete extra file from merge --- .../TestData/FakeWebSocketManager.cs~master | 29 ------------------- 1 file changed, 29 deletions(-) delete mode 100644 src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/TestData/FakeWebSocketManager.cs~master diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/TestData/FakeWebSocketManager.cs~master b/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/TestData/FakeWebSocketManager.cs~master deleted file mode 100644 index 17ceff9cb..000000000 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/TestData/FakeWebSocketManager.cs~master +++ /dev/null @@ -1,29 +0,0 @@ -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - -namespace GraphQL.AspNet.Tests.Engine.TestData -{ - using System.Collections.Generic; - using System.Net.WebSockets; - using System.Threading.Tasks; - using GraphQL.AspNet.Tests.Mocks; - using Microsoft.AspNetCore.Http; - - public class FakeWebSocketManager : WebSocketManager - { - public override bool IsWebSocketRequest => true; - - public override IList WebSocketRequestedProtocols => new List(); - - public override Task AcceptWebSocketAsync(string subProtocol) - { - return Task.FromResult(new FakeWebSocket(WebSocketState.Open) as WebSocket); - } - } -} \ No newline at end of file From 9a82ecb36157071bae11ae2e759d141ef39ab682 Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Fri, 16 Jun 2023 20:25:24 -0700 Subject: [PATCH 04/63] WIP, api extension methods completed. --- .../GraphQLFieldBuilderExtensions.cs | 88 ----------- .../GraphQLFieldGroupBuilderExtensions.cs | 27 ---- .../GraphQLMinimalApiExtensions.cs | 114 -------------- .../GraphQLMinimalApiExtensions_Internals.cs | 61 ++++++++ .../GraphQLMinimalApiExtensions_Mutations.cs | 69 +++++++++ .../GraphQLMinimalApiExtensions_Queries.cs | 69 +++++++++ ...phQLMinimalApiExtensions_ResolvedFields.cs | 120 +++++++++++++++ ...phQLMinimalApiExtensions_TypeExtensions.cs | 113 ++++++++++++++ ...aphQLMinimalApiExtensions_VirtualFields.cs | 143 ++++++++++++++++++ ...Builder.cs => BaseGraphQLFieldTemplate.cs} | 30 ++-- .../MinimalApi/GraphQLFieldBuilder.cs | 30 ---- .../GraphQLFieldBuilderConstants.cs | 11 -- .../GraphQLResolvedFieldTemplate.cs | 73 +++++++++ .../GraphQLTypeExtensionFieldTemplate.cs | 47 ++++++ ...lder.cs => GraphQLVirtualFieldTemplate.cs} | 28 ++-- .../Configuration/SchemaOptions.cs | 2 +- ...eldBuilder.cs => IGraphQLFieldTemplate.cs} | 4 +- ...er.cs => IGraphQLResolvedFieldTemplate.cs} | 32 ++-- .../IGraphQLTypeExtensionTemplate.cs | 37 +++++ 19 files changed, 783 insertions(+), 315 deletions(-) delete mode 100644 src/graphql-aspnet/Configuration/GraphQLFieldBuilderExtensions.cs delete mode 100644 src/graphql-aspnet/Configuration/GraphQLFieldGroupBuilderExtensions.cs delete mode 100644 src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions.cs create mode 100644 src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Internals.cs create mode 100644 src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Mutations.cs create mode 100644 src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Queries.cs create mode 100644 src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_ResolvedFields.cs create mode 100644 src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_TypeExtensions.cs create mode 100644 src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_VirtualFields.cs rename src/graphql-aspnet/Configuration/MinimalApi/{BaseGraphQLFieldBuilder.cs => BaseGraphQLFieldTemplate.cs} (70%) delete mode 100644 src/graphql-aspnet/Configuration/MinimalApi/GraphQLFieldBuilder.cs delete mode 100644 src/graphql-aspnet/Configuration/MinimalApi/GraphQLFieldBuilderConstants.cs create mode 100644 src/graphql-aspnet/Configuration/MinimalApi/GraphQLResolvedFieldTemplate.cs create mode 100644 src/graphql-aspnet/Configuration/MinimalApi/GraphQLTypeExtensionFieldTemplate.cs rename src/graphql-aspnet/Configuration/MinimalApi/{GraphQLFieldGroupBuilder.cs => GraphQLVirtualFieldTemplate.cs} (55%) rename src/graphql-aspnet/Interfaces/Configuration/{IGraphQLFieldBuilder.cs => IGraphQLFieldTemplate.cs} (89%) rename src/graphql-aspnet/Interfaces/Configuration/{IGraphQLFieldGroupBuilder.cs => IGraphQLResolvedFieldTemplate.cs} (56%) create mode 100644 src/graphql-aspnet/Interfaces/Configuration/IGraphQLTypeExtensionTemplate.cs diff --git a/src/graphql-aspnet/Configuration/GraphQLFieldBuilderExtensions.cs b/src/graphql-aspnet/Configuration/GraphQLFieldBuilderExtensions.cs deleted file mode 100644 index 5b88c3f05..000000000 --- a/src/graphql-aspnet/Configuration/GraphQLFieldBuilderExtensions.cs +++ /dev/null @@ -1,88 +0,0 @@ -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - -namespace GraphQL.AspNet.Configuration -{ - using System; - using GraphQL.AspNet.Common; - using GraphQL.AspNet.Configuration.MinimalApi; - using GraphQL.AspNet.Interfaces.Configuration; - using Microsoft.AspNetCore.Authorization; - - /// - /// Extension methods for configuring specifical aspects of a field generated via - /// the minimal API - /// - public static class GraphQLFieldBuilderExtensions - { - /// - /// Adds policy-based authorization requirements to the field. - /// - /// - /// - /// This is similar to - /// adding an [Authorize] attribute to a controller methods. This method can be - /// called more than once. - /// - /// - /// Each subsequent call will append a new policy in a similar fashion - /// as if you added multiple [Authorize] attributes to a controller methods. - /// - /// - /// The field being built. - /// Name of the policy to assign via this authorization. - /// IGraphQLFieldBuilder. - public static IGraphQLFieldBuilder RequireAuthorization( - this IGraphQLFieldBuilder fieldBuilder, - string policyName) - { - Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); - - fieldBuilder.Attributes.Add(new AuthorizeAttribute(policyName)); - return fieldBuilder; - } - - /// - /// Indicates that the field should allow anonymous access. - /// - /// - /// - /// This is similar to adding [AllowAnonymous] to a controller method - /// - /// - /// Any inherited authorization permissions from field groups are automatically - /// dropped from this field instance. - /// - /// - /// The field being built. - /// IGraphQLFieldBuilder. - public static IGraphQLFieldBuilder AllowAnonymous(this IGraphQLFieldBuilder fieldBuilder) - { - Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); - fieldBuilder.Attributes.Add(new AllowAnonymousAttribute()); - return fieldBuilder; - } - - /// - /// Sets the resolver to be used when this field is requested at runtime. - /// - /// - /// If this method is called more than once the previous resolver will be replaced. - /// - /// The field being built. - /// The delegate to assign as the resolver. This method will be - /// parsed to determine input arguments for the field on the target schema. - /// IGraphQLFieldBuilder. - public static IGraphQLFieldBuilder AddResolver(this IGraphQLFieldBuilder fieldBuilder, Delegate resolver) - { - fieldBuilder[GraphQLFieldBuilderConstants.RESOLVER] = resolver; - return fieldBuilder; - } - } -} \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/GraphQLFieldGroupBuilderExtensions.cs b/src/graphql-aspnet/Configuration/GraphQLFieldGroupBuilderExtensions.cs deleted file mode 100644 index eeefda4bb..000000000 --- a/src/graphql-aspnet/Configuration/GraphQLFieldGroupBuilderExtensions.cs +++ /dev/null @@ -1,27 +0,0 @@ -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - -namespace GraphQL.AspNet.Configuration -{ - using System; - using GraphQL.AspNet.Common; - using GraphQL.AspNet.Configuration.MinimalApi; - using GraphQL.AspNet.Interfaces.Configuration; - using GraphQL.AspNet.Interfaces.Schema; - using Microsoft.AspNetCore.Authorization; - using Microsoft.AspNetCore.Builder; - - /// - /// Extension methods for configuring specifical aspects of a field group generated via - /// the minimal API - /// - public static class GraphQLFieldGroupBuilderExtensions - { - } -} \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions.cs b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions.cs deleted file mode 100644 index 623f86e2f..000000000 --- a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions.cs +++ /dev/null @@ -1,114 +0,0 @@ -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - -namespace GraphQL.AspNet.Configuration -{ - using System; - using GraphQL.AspNet.Common; - using GraphQL.AspNet.Configuration.MinimalApi; - using GraphQL.AspNet.Execution; - using GraphQL.AspNet.Interfaces.Configuration; - using GraphQL.AspNet.Schemas.Structural; - using GraphQL.AspNet.Schemas.TypeSystem; - - /// - /// Extension methods for configuring minimal API methods as fields on the graph. - /// - public static class GraphQLMinimalApiExtensions - { - public static IGraphQLFieldBuilder MapQuery(this SchemaOptions schemaOptions, string template) - { - return MapGraphQLField( - schemaOptions, - GraphOperationType.Query, - template); - } - - public static IGraphQLFieldBuilder MapMutation(this SchemaOptions schemaOptions, string template) - { - return MapGraphQLField( - schemaOptions, - GraphOperationType.Mutation, - template); - } - - public static IGraphQLFieldBuilder MapQuery(this ISchemaBuilder schemaBuilder, string template) - { - Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); - - return MapGraphQLField( - schemaBuilder.Options, - GraphOperationType.Query, - template); - } - - public static IGraphQLFieldBuilder MapMutation(this ISchemaBuilder schemaBuilder, string template, Delegate resolverMethod) - { - Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); - - return MapGraphQLField( - schemaBuilder.Options, - GraphOperationType.Mutation, - template); - } - - public static IGraphQLFieldBuilder MapQuery(this IGraphQLFieldGroupBuilder groupBuilder, string template, Delegate resolverMethod) - { - Validation.ThrowIfNull(groupBuilder, nameof(groupBuilder)); - - return MapGraphQLField( - groupBuilder.Options, - GraphOperationType.Query, - template); - } - - public static IGraphQLFieldBuilder MapMutation(this IGraphQLFieldGroupBuilder groupBuilder, string template, Delegate resolverMethod) - { - Validation.ThrowIfNull(groupBuilder, nameof(groupBuilder)); - - return MapGraphQLField( - groupBuilder.Options, - GraphOperationType.Mutation, - template); - } - - public static IGraphQLFieldGroupBuilder MapGroup(this ISchemaBuilder schemaBuilder, string template) - { - return MapGroup(schemaBuilder?.Options, template); - } - - public static IGraphQLFieldGroupBuilder MapGroup(this SchemaOptions schemaOptions, string template) - { - return new GraphQLFieldGroupBuilder(schemaOptions, template); - } - - public static IGraphQLFieldGroupBuilder MapGroup(this IGraphQLFieldGroupBuilder groupBuilder, string subTemplate) - { - return new GraphQLFieldGroupBuilder(groupBuilder, subTemplate); - } - - public static IGraphQLFieldBuilder MapGraphQLField( - SchemaOptions schemaOptions, - GraphOperationType operationType, - string pathTemplate) - { - schemaOptions = Validation.ThrowIfNullOrReturn(schemaOptions, nameof(schemaOptions)); - pathTemplate = Validation.ThrowIfNullWhiteSpaceOrReturn(pathTemplate, nameof(pathTemplate)); - - var path = new SchemaItemPath((SchemaItemCollections)operationType, pathTemplate); - - var fieldTemplate = new GraphQLFieldBuilder( - schemaOptions, - path.Path); - - schemaOptions.AddFieldTemplate(fieldTemplate); - return fieldTemplate; - } - } -} \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Internals.cs b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Internals.cs new file mode 100644 index 000000000..e2f830ac0 --- /dev/null +++ b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Internals.cs @@ -0,0 +1,61 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Configuration +{ + using System; + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Configuration.MinimalApi; + using GraphQL.AspNet.Execution; + using GraphQL.AspNet.Interfaces.Configuration; + using GraphQL.AspNet.Schemas.Structural; + using GraphQL.AspNet.Schemas.TypeSystem; + + /// + /// Extension methods for configuring minimal API methods as fields on the graph. + /// + public static partial class GraphQLMinimalApiExtensions + { + private static IGraphQLFieldTemplate MapGraphQLField( + SchemaOptions schemaOptions, + GraphOperationType operationType, + string pathTemplate) + { + schemaOptions = Validation.ThrowIfNullOrReturn(schemaOptions, nameof(schemaOptions)); + pathTemplate = Validation.ThrowIfNullWhiteSpaceOrReturn(pathTemplate, nameof(pathTemplate)); + + var path = new SchemaItemPath((SchemaItemCollections)operationType, pathTemplate); + + var fieldTemplate = new GraphQLVirtualFieldTemplate( + schemaOptions, + path.Path); + + return fieldTemplate; + } + + private static IGraphQLResolvedFieldTemplate MapTypeExtension( + SchemaOptions schemaOptions, + Type typeToExtend, + string fieldName, + FieldResolutionMode resolutionMode) + { + schemaOptions = Validation.ThrowIfNullOrReturn(schemaOptions, nameof(schemaOptions)); + fieldName = Validation.ThrowIfNullWhiteSpaceOrReturn(fieldName, nameof(fieldName)); + + IGraphQLResolvedFieldTemplate field = new GraphQLTypeExtensionFieldTemplate( + schemaOptions, + typeToExtend, + fieldName, + resolutionMode); + + schemaOptions.AddFieldTemplate(field); + return field; + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Mutations.cs b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Mutations.cs new file mode 100644 index 000000000..c470038f1 --- /dev/null +++ b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Mutations.cs @@ -0,0 +1,69 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Configuration +{ + using System; + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Interfaces.Configuration; + using GraphQL.AspNet.Schemas.TypeSystem; + + /// + /// Extension methods for configuring minimal API methods as fields on the graph. + /// + public static partial class GraphQLMinimalApiExtensions + { + public static IGraphQLFieldTemplate MapMutation(this SchemaOptions schemaOptions, string template) + { + var field = MapGraphQLField( + schemaOptions, + GraphOperationType.Mutation, + template); + + return field; + } + + public static IGraphQLResolvedFieldTemplate MapMutation(this SchemaOptions schemaOptions, string template, Delegate resolverMethod) + { + Validation.ThrowIfNull(resolverMethod, nameof(resolverMethod)); + + var field = MapGraphQLField( + schemaOptions, + GraphOperationType.Mutation, + template); + + return field.AddResolver(resolverMethod); + } + + public static IGraphQLFieldTemplate MapMutation(this ISchemaBuilder schemaBuilder, string template) + { + Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); + + var field = MapGraphQLField( + schemaBuilder.Options, + GraphOperationType.Mutation, + template); + + return field; + } + + public static IGraphQLResolvedFieldTemplate MapMutation(this ISchemaBuilder schemaBuilder, string template, Delegate resolverMethod) + { + Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); + Validation.ThrowIfNull(resolverMethod, nameof(resolverMethod)); + + var field = MapGraphQLField( + schemaBuilder.Options, + GraphOperationType.Mutation, + template); + + return field.AddResolver(resolverMethod); + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Queries.cs b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Queries.cs new file mode 100644 index 000000000..7c1887b29 --- /dev/null +++ b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Queries.cs @@ -0,0 +1,69 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Configuration +{ + using System; + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Interfaces.Configuration; + using GraphQL.AspNet.Schemas.TypeSystem; + + /// + /// Extension methods for configuring minimal API methods as fields on the graph. + /// + public static partial class GraphQLMinimalApiExtensions + { + public static IGraphQLFieldTemplate MapQuery(this SchemaOptions schemaOptions, string template) + { + var field = MapGraphQLField( + schemaOptions, + GraphOperationType.Query, + template); + + return field; + } + + public static IGraphQLResolvedFieldTemplate MapQuery(this SchemaOptions schemaOptions, string template, Delegate resolverMethod) + { + Validation.ThrowIfNull(resolverMethod, nameof(resolverMethod)); + + var field = MapGraphQLField( + schemaOptions, + GraphOperationType.Query, + template); + + return field.AddResolver(resolverMethod); + } + + public static IGraphQLFieldTemplate MapQuery(this ISchemaBuilder schemaBuilder, string template) + { + Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); + + var field = MapGraphQLField( + schemaBuilder.Options, + GraphOperationType.Query, + template); + + return field; + } + + public static IGraphQLResolvedFieldTemplate MapQuery(this ISchemaBuilder schemaBuilder, string template, Delegate resolverMethod) + { + Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); + Validation.ThrowIfNull(resolverMethod, nameof(resolverMethod)); + + var field = MapGraphQLField( + schemaBuilder.Options, + GraphOperationType.Query, + template); + + return field.AddResolver(resolverMethod); + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_ResolvedFields.cs b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_ResolvedFields.cs new file mode 100644 index 000000000..352034a01 --- /dev/null +++ b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_ResolvedFields.cs @@ -0,0 +1,120 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Configuration +{ + using System; + using GraphQL.AspNet.Attributes; + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Interfaces.Configuration; + using GraphQL.AspNet.Interfaces.Controllers; + using Microsoft.AspNetCore.Authorization; + + /// + /// Extension methods for configuring minimal API methods as fields on the graph. + /// + public static partial class GraphQLMinimalApiExtensions + { + /// + /// Adds policy-based authorization requirements to the field. + /// + /// + /// This is similar to adding the to a controller method + /// + /// The field being built. + /// The name of the policy to assign via this requirement. + /// A comma-seperated list of roles to assign via this requirement. + /// IGraphQLFieldBuilder. + public static IGraphQLResolvedFieldTemplate RequireAuthorization( + this IGraphQLResolvedFieldTemplate fieldBuilder, + string policyName = null, + string roles = null) + { + Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); + + var attrib = new AuthorizeAttribute(); + attrib.Policy = policyName?.Trim(); + attrib.Roles = roles?.Trim(); + fieldBuilder.Attributes.Add(attrib); + return fieldBuilder; + } + + /// + /// Indicates that the field should allow anonymous access. + /// + /// + /// This is similar to adding the to a controller method + /// + /// The field being built. + /// IGraphQLFieldBuilder. + public static IGraphQLResolvedFieldTemplate AllowAnonymous(this IGraphQLResolvedFieldTemplate fieldBuilder) + { + Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); + fieldBuilder.Attributes.Add(new AllowAnonymousAttribute()); + return fieldBuilder; + } + + /// + /// Sets the resolver to be used when this field is requested at runtime. + /// + /// + /// If this method is called more than once the previously set resolver will be replaced. + /// + /// The field being built. + /// The delegate to assign as the resolver. This method will be + /// parsed to determine input arguments for the field on the target schema. + /// IGraphQLFieldBuilder. + public static IGraphQLResolvedFieldTemplate AddResolver(this IGraphQLResolvedFieldTemplate fieldBuilder, Delegate resolverMethod) + { + fieldBuilder.Resolver = resolverMethod; + fieldBuilder.ReturnType = null; + + return fieldBuilder; + } + + /// + /// Sets the resolver to be used when this field is requested at runtime. + /// + /// + /// If this method is called more than once the previously set resolver will be replaced. + /// + /// The expected, primary return type of the field. Must be provided + /// if the supplied delegate returns an . + /// The field being built. + /// The delegate to assign as the resolver. This method will be + /// parsed to determine input arguments for the field on the target schema. + /// IGraphQLFieldBuilder. + public static IGraphQLResolvedFieldTemplate AddResolver(this IGraphQLResolvedFieldTemplate fieldBuilder, Delegate resolverMethod) + { + fieldBuilder.Resolver = resolverMethod; + fieldBuilder.ReturnType = typeof(TReturnType); + return fieldBuilder; + } + + /// + /// Adds a set of possible return types for this field. This is synonymous to using the + /// on a controller's action method. + /// + /// + /// This method can be called multiple times. Any new types will be appended to the field. + /// + /// The field being built. + /// The first possible type that might be returned by this + /// field. + /// Any number of additional possible types that + /// might be returned by this field. + /// IGraphQLFieldBuilder. + public static IGraphQLResolvedFieldTemplate AddPossibleTypes(this IGraphQLResolvedFieldTemplate fieldBuilder, Type firstPossibleType, params Type[] additionalPossibleTypes) + { + var possibleTypes = new PossibleTypesAttribute(firstPossibleType, additionalPossibleTypes); + fieldBuilder.Attributes.Add(possibleTypes); + return fieldBuilder; + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_TypeExtensions.cs b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_TypeExtensions.cs new file mode 100644 index 000000000..6f1e2ed42 --- /dev/null +++ b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_TypeExtensions.cs @@ -0,0 +1,113 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Configuration +{ + using System; + using System.Collections.Generic; + using GraphQL.AspNet.Execution; + using GraphQL.AspNet.Interfaces.Configuration; + + /// + /// Extension methods for configuring minimal API methods as fields on the graph. + /// + public static partial class GraphQLMinimalApiExtensions + { + /// + /// Registers a new batched type extension to a given type for the target schema. + /// + /// + /// The supplied resolver must declare a parameter that implements an + /// for the supplied . + /// + /// The concrete interface, class or struct to extend with a new field. + /// The configuration options for the target schema. + /// Name of the field to add to the . + /// The resolver method to be called when the field is requested. + /// IGraphQLResolvedFieldTemplate. + public static IGraphQLResolvedFieldTemplate MapBatchTypeExtension(this SchemaOptions schemaOptions, string fieldName, Delegate resolverMethod = null) + { + return schemaOptions.MapBatchTypeExtension( + typeof(TType), + fieldName, + resolverMethod); + } + + /// + /// Registers a new batched type extension to a given type for the target schema. + /// + /// + /// The supplied resolver must declare a parameter that implements an + /// for the supplied . + /// + /// The configuration options for the target schema. + /// The concrete interface, class or struct to extend with a new field. + /// Name of the field to add to the . + /// The resolver method to be called when the field is requested. + /// IGraphQLResolvedFieldTemplate. + public static IGraphQLResolvedFieldTemplate MapBatchTypeExtension(this SchemaOptions schemaOptions, Type typeToExtend, string fieldName, Delegate resolverMethod = null) + { + var field = MapTypeExtension( + schemaOptions, + typeToExtend, + fieldName, + FieldResolutionMode.Batch); + + if (resolverMethod != null) + field = field.AddResolver(resolverMethod); + + return field; + } + + /// + /// Registers a new type extension to a given type for the target schema. + /// + /// + /// The supplied resolver must declare a parameter that is of the same type as . + /// + /// The concrete interface, class or struct to extend with a new field. + /// The configuration options for the target schema. + /// Name of the field to add to the . + /// The resolver method to be called when the field is requested. + /// IGraphQLResolvedFieldTemplate. + public static IGraphQLResolvedFieldTemplate MapTypeExtension(this SchemaOptions schemaOptions, string fieldName, Delegate resolverMethod = null) + { + return schemaOptions.MapTypeExtension( + typeof(TType), + fieldName, + resolverMethod); + } + + /// + /// Registers a new type extension to a given type for the target schema. + /// + /// + /// The supplied resolver must declare a parameter that is of the same type as + /// . + /// + /// The configuration options for the target schema. + /// The concrete interface, class or struct to extend with a new field. + /// Name of the field to add to the . + /// The resolver method to be called when the field is requested. + /// IGraphQLResolvedFieldTemplate. + public static IGraphQLResolvedFieldTemplate MapTypeExtension(this SchemaOptions schemaOptions, Type typeToExtend, string fieldName, Delegate resolverMethod = null) + { + var field = MapTypeExtension( + schemaOptions, + typeToExtend, + fieldName, + FieldResolutionMode.PerSourceItem); + + if (resolverMethod != null) + field = field.AddResolver(resolverMethod); + + return field; + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_VirtualFields.cs b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_VirtualFields.cs new file mode 100644 index 000000000..8ae386e4d --- /dev/null +++ b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_VirtualFields.cs @@ -0,0 +1,143 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Configuration +{ + using System; + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Configuration.MinimalApi; + using GraphQL.AspNet.Interfaces.Configuration; + using GraphQL.AspNet.Interfaces.Controllers; + using Microsoft.AspNetCore.Authorization; + + /// + /// Extension methods for configuring minimal API methods as fields on the graph. + /// + public static partial class GraphQLMinimalApiExtensions + { + /// + /// Adds policy-based authorization requirements to the field. + /// + /// + /// This is similar to adding the to a controller method + /// + /// The field being built. + /// The name of the policy to assign via this requirement. + /// A comma-seperated list of roles to assign via this requirement. + /// IGraphQLFieldBuilder. + public static IGraphQLFieldTemplate RequireAuthorization( + this IGraphQLFieldTemplate fieldBuilder, + string policyName = null, + string roles = null) + { + Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); + + var attrib = new AuthorizeAttribute(); + attrib.Policy = policyName?.Trim(); + attrib.Roles = roles?.Trim(); + fieldBuilder.Attributes.Add(attrib); + return fieldBuilder; + } + + /// + /// Indicates that the field should allow anonymous access. + /// + /// + /// + /// This is similar to adding the to a controller method + /// + /// + /// Any inherited authorization permissions from field groups are automatically + /// dropped from this field instance. + /// + /// + /// The field being built. + /// IGraphQLFieldBuilder. + public static IGraphQLFieldTemplate AllowAnonymous(this IGraphQLFieldTemplate fieldBuilder) + { + Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); + fieldBuilder.Attributes.Add(new AllowAnonymousAttribute()); + return fieldBuilder; + } + + /// + /// Sets the resolver to be used when this field is requested at runtime. + /// + /// + /// If this method is called more than once the previously set resolver will be replaced. + /// + /// The field being built. + /// The delegate to assign as the resolver. This method will be + /// parsed to determine input arguments for the field on the target schema. + /// IGraphQLFieldBuilder. + public static IGraphQLResolvedFieldTemplate AddResolver(this IGraphQLFieldTemplate field, Delegate resolverMethod) + { + // convert the virtual field to a resolved field + var resolvedBuilder = GraphQLResolvedFieldTemplate.FromFieldTemplate(field); + resolvedBuilder.Options.AddFieldTemplate(resolvedBuilder); + + resolvedBuilder.Resolver = resolverMethod; + resolvedBuilder.ReturnType = null; + + return resolvedBuilder; + } + + /// + /// Sets the resolver to be used when this field is requested at runtime. + /// + /// + /// If this method is called more than once the previously set resolver will be replaced. + /// + /// The expected, primary return type of the field. Must be provided + /// if the supplied delegate returns an . + /// The field being built. + /// The delegate to assign as the resolver. This method will be + /// parsed to determine input arguments for the field on the target schema. + /// IGraphQLFieldBuilder. + public static IGraphQLResolvedFieldTemplate AddResolver(this IGraphQLFieldTemplate field, Delegate resolverMethod) + { + // convert the virtual field to a resolved field + var resolvedBuilder = GraphQLResolvedFieldTemplate.FromFieldTemplate(field); + resolvedBuilder.Options.AddFieldTemplate(resolvedBuilder); + + resolvedBuilder.Resolver = resolverMethod; + resolvedBuilder.ReturnType = typeof(TReturnType); + return resolvedBuilder; + } + + /// + /// Maps a terminal child field into the schema and assigns the resolver method to it. + /// + /// The field under which this new field will be nested. + /// The template pattern to be appended to the supplied . + /// The resolver method to be called when this field is requested. + /// IGraphQLResolvedFieldBuilder. + public static IGraphQLResolvedFieldTemplate MapField(this IGraphQLFieldTemplate field, string subTemplate, Delegate resolverMethod) + { + var subField = new GraphQLResolvedFieldTemplate(field, subTemplate); + subField.AddResolver(resolverMethod); + + subField.Options.AddFieldTemplate(subField); + return subField; + } + + /// + /// Maps a child field into the schema underneath the supplied field. This field can be + /// further extended. + /// + /// The field under which this new field will be nested. + /// The template pattern to be appended to the supplied . + /// IGraphQLFieldBuilder. + public static IGraphQLFieldTemplate MapField(this IGraphQLFieldTemplate field, string subTemplate) + { + var subField = new GraphQLVirtualFieldTemplate(field, subTemplate); + return subField; + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/MinimalApi/BaseGraphQLFieldBuilder.cs b/src/graphql-aspnet/Configuration/MinimalApi/BaseGraphQLFieldTemplate.cs similarity index 70% rename from src/graphql-aspnet/Configuration/MinimalApi/BaseGraphQLFieldBuilder.cs rename to src/graphql-aspnet/Configuration/MinimalApi/BaseGraphQLFieldTemplate.cs index 150a44891..d435ec575 100644 --- a/src/graphql-aspnet/Configuration/MinimalApi/BaseGraphQLFieldBuilder.cs +++ b/src/graphql-aspnet/Configuration/MinimalApi/BaseGraphQLFieldTemplate.cs @@ -19,27 +19,27 @@ namespace GraphQL.AspNet.Configuration.MinimalApi /// An abstract class containing all the common elements across minimal field builders and /// their supporting classes. /// - internal abstract class BaseGraphQLFieldBuilder : Dictionary + internal abstract class BaseGraphQLFieldTemplate : Dictionary { - private IGraphQLFieldGroupBuilder _parent; + private IGraphQLFieldTemplate _parent; private string _partialPathTemplate; /// - /// Prevents a default instance of the class from being created. + /// Prevents a default instance of the class from being created. /// - private BaseGraphQLFieldBuilder() + private BaseGraphQLFieldTemplate() { this.Attributes = new List(); } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The schema options where this field item /// is being defined. /// The partial path template defined for this /// individual entity. - protected BaseGraphQLFieldBuilder( + protected BaseGraphQLFieldTemplate( SchemaOptions options, string partialPathTemplate) : this() @@ -51,29 +51,29 @@ protected BaseGraphQLFieldBuilder( } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// The group builder from which this entity is being created. + /// The group builder from which this entity is being created. /// The partial path template defined for this /// individual entity. - protected BaseGraphQLFieldBuilder( - IGraphQLFieldGroupBuilder groupBuilder, + protected BaseGraphQLFieldTemplate( + IGraphQLFieldTemplate parentVirtualFieldBuilder, string partialPathTemplate) : this() { - _parent = Validation.ThrowIfNullOrReturn(groupBuilder, nameof(groupBuilder)); - this.Options = Validation.ThrowIfNullOrReturn(groupBuilder?.Options, nameof(groupBuilder.Options)); + _parent = Validation.ThrowIfNullOrReturn(parentVirtualFieldBuilder, nameof(parentVirtualFieldBuilder)); + this.Options = Validation.ThrowIfNullOrReturn(parentVirtualFieldBuilder?.Options, nameof(parentVirtualFieldBuilder.Options)); _partialPathTemplate = Validation.ThrowIfNullWhiteSpaceOrReturn(partialPathTemplate, nameof(partialPathTemplate)); } - /// + /// public virtual SchemaOptions Options { get; protected set; } - /// + /// public IList Attributes { get; } - /// + /// public string Template { get diff --git a/src/graphql-aspnet/Configuration/MinimalApi/GraphQLFieldBuilder.cs b/src/graphql-aspnet/Configuration/MinimalApi/GraphQLFieldBuilder.cs deleted file mode 100644 index 631e6e949..000000000 --- a/src/graphql-aspnet/Configuration/MinimalApi/GraphQLFieldBuilder.cs +++ /dev/null @@ -1,30 +0,0 @@ -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - -namespace GraphQL.AspNet.Configuration.MinimalApi -{ - using GraphQL.AspNet.Interfaces.Configuration; - - internal class GraphQLFieldBuilder : BaseGraphQLFieldBuilder, IGraphQLFieldBuilder - { - public GraphQLFieldBuilder( - SchemaOptions schemaOptions, - string fullPathTemplate) - : base(schemaOptions, fullPathTemplate) - { - } - - public GraphQLFieldBuilder( - IGraphQLFieldGroupBuilder groupBuilder, - string partialPathTemplate) - : base(groupBuilder, partialPathTemplate) - { - } - } -} \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/MinimalApi/GraphQLFieldBuilderConstants.cs b/src/graphql-aspnet/Configuration/MinimalApi/GraphQLFieldBuilderConstants.cs deleted file mode 100644 index 2cfb17aea..000000000 --- a/src/graphql-aspnet/Configuration/MinimalApi/GraphQLFieldBuilderConstants.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace GraphQL.AspNet.Configuration.MinimalApi -{ - using System; - using System.Collections.Generic; - using System.Text; - - internal static class GraphQLFieldBuilderConstants - { - public const string RESOLVER = "GraphQL:FieldBuilder:Resolver"; - } -} diff --git a/src/graphql-aspnet/Configuration/MinimalApi/GraphQLResolvedFieldTemplate.cs b/src/graphql-aspnet/Configuration/MinimalApi/GraphQLResolvedFieldTemplate.cs new file mode 100644 index 000000000..f30aebefd --- /dev/null +++ b/src/graphql-aspnet/Configuration/MinimalApi/GraphQLResolvedFieldTemplate.cs @@ -0,0 +1,73 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Configuration.MinimalApi +{ + using System; + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Interfaces.Configuration; + + /// + /// An internal implementation of the + /// used to generate new graphql fields via a minimal api style of coding. + /// + internal class GraphQLResolvedFieldTemplate : BaseGraphQLFieldTemplate, IGraphQLResolvedFieldTemplate + { + /// + /// Converts the unresolved field into a resolved field. The newly generated field + /// will NOT be attached to any schema and will not have an assigned resolver. + /// + /// The field template. + /// IGraphQLResolvedFieldTemplate. + public static IGraphQLResolvedFieldTemplate FromFieldTemplate(IGraphQLFieldTemplate fieldTemplate) + { + Validation.ThrowIfNull(fieldTemplate, nameof(fieldTemplate)); + var field = new GraphQLResolvedFieldTemplate(fieldTemplate.Options, fieldTemplate.Template); + + foreach (var attrib in fieldTemplate.Attributes) + field.Attributes.Add(attrib); + + foreach (var kvp in fieldTemplate) + field.Add(kvp.Key, kvp.Value); + + return field; + } + + /// + /// Initializes a new instance of the class. + /// + /// The schema options to which this field is being added. + /// The full path template describing where the field will live. + public GraphQLResolvedFieldTemplate( + SchemaOptions schemaOptions, + string fullPathTemplate) + : base(schemaOptions, fullPathTemplate) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The parent field builder to which this new, resolved field + /// will be appended. + /// The template part to append to the parent field's template. + public GraphQLResolvedFieldTemplate( + IGraphQLFieldTemplate parentFieldBuilder, + string fieldSubTemplate) + : base(parentFieldBuilder, fieldSubTemplate) + { + } + + /// + public Delegate Resolver { get; set; } + + /// + public Type ReturnType { get; set; } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/MinimalApi/GraphQLTypeExtensionFieldTemplate.cs b/src/graphql-aspnet/Configuration/MinimalApi/GraphQLTypeExtensionFieldTemplate.cs new file mode 100644 index 000000000..ae007735a --- /dev/null +++ b/src/graphql-aspnet/Configuration/MinimalApi/GraphQLTypeExtensionFieldTemplate.cs @@ -0,0 +1,47 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Configuration.MinimalApi +{ + using System; + using GraphQL.AspNet.Execution; + using GraphQL.AspNet.Interfaces.Configuration; + + /// + /// An internal implementation of the + /// used to generate new type extensions via a minimal api style of coding. + /// + internal class GraphQLTypeExtensionFieldTemplate : GraphQLResolvedFieldTemplate, IGraphQLTypeExtensionTemplate + { + /// + /// Initializes a new instance of the class. + /// + /// The schema options where this type extension is being declared. + /// The target OBJECT or INTERFACE type to extend. + /// Name of the field to add to the . + /// The resolution mode for the resolver implemented by this + /// type extension. + public GraphQLTypeExtensionFieldTemplate( + SchemaOptions schemaOptions, + Type typeToExtend, + string fieldName, + FieldResolutionMode resolutionMode) + : base(schemaOptions, fieldName) + { + this.ExecutionMode = resolutionMode; + this.TargetType = typeToExtend; + } + + /// + public FieldResolutionMode ExecutionMode { get; } + + /// + public Type TargetType { get; } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/MinimalApi/GraphQLFieldGroupBuilder.cs b/src/graphql-aspnet/Configuration/MinimalApi/GraphQLVirtualFieldTemplate.cs similarity index 55% rename from src/graphql-aspnet/Configuration/MinimalApi/GraphQLFieldGroupBuilder.cs rename to src/graphql-aspnet/Configuration/MinimalApi/GraphQLVirtualFieldTemplate.cs index cbd96ca62..a4fc1ab22 100644 --- a/src/graphql-aspnet/Configuration/MinimalApi/GraphQLFieldGroupBuilder.cs +++ b/src/graphql-aspnet/Configuration/MinimalApi/GraphQLVirtualFieldTemplate.cs @@ -9,39 +9,37 @@ namespace GraphQL.AspNet.Configuration.MinimalApi { - using GraphQL.AspNet.Common; using GraphQL.AspNet.Interfaces.Configuration; - using GraphQL.AspNet.Schemas.Structural; /// - /// An internal implementation of - /// used as a base object during minimal api construction. + /// An internal implementation of the + /// used to generate new graphql fields via a minimal api style of coding. /// - internal class GraphQLFieldGroupBuilder : BaseGraphQLFieldBuilder, IGraphQLFieldGroupBuilder + internal class GraphQLVirtualFieldTemplate : BaseGraphQLFieldTemplate, IGraphQLFieldTemplate { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The schema options that will own the fields created from /// this builder. - /// The partial field path template + /// The partial field path template /// that will be prepended to any fields or groups created from this builder. - public GraphQLFieldGroupBuilder( + public GraphQLVirtualFieldTemplate( SchemaOptions options, - string groupTemplate) - : base(options, groupTemplate) + string fieldTemplate) + : base(options, fieldTemplate) { } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// The parent group builder from which + /// The parent virtual field from which /// this builder will copy its settings. - /// The partial path template to be appended to + /// The partial path template to be appended to /// the parent's already defined template. - public GraphQLFieldGroupBuilder(IGraphQLFieldGroupBuilder parentGroupBuilder, string groupSubTemplate) - : base(parentGroupBuilder, groupSubTemplate) + public GraphQLVirtualFieldTemplate(IGraphQLFieldTemplate parentFieldBuilder, string fieldSubTemplate) + : base(parentFieldBuilder, fieldSubTemplate) { } } diff --git a/src/graphql-aspnet/Configuration/SchemaOptions.cs b/src/graphql-aspnet/Configuration/SchemaOptions.cs index a0c797f6c..d0c595694 100644 --- a/src/graphql-aspnet/Configuration/SchemaOptions.cs +++ b/src/graphql-aspnet/Configuration/SchemaOptions.cs @@ -348,7 +348,7 @@ internal void FinalizeServiceRegistration() } } - internal void AddFieldTemplate(IGraphQLFieldBuilder fieldTemplate) + internal void AddFieldTemplate(IGraphQLResolvedFieldTemplate fieldTemplate) { throw new NotImplementedException(); } diff --git a/src/graphql-aspnet/Interfaces/Configuration/IGraphQLFieldBuilder.cs b/src/graphql-aspnet/Interfaces/Configuration/IGraphQLFieldTemplate.cs similarity index 89% rename from src/graphql-aspnet/Interfaces/Configuration/IGraphQLFieldBuilder.cs rename to src/graphql-aspnet/Interfaces/Configuration/IGraphQLFieldTemplate.cs index 3e0823f87..4f8aff8d6 100644 --- a/src/graphql-aspnet/Interfaces/Configuration/IGraphQLFieldBuilder.cs +++ b/src/graphql-aspnet/Interfaces/Configuration/IGraphQLFieldTemplate.cs @@ -14,10 +14,10 @@ namespace GraphQL.AspNet.Interfaces.Configuration using GraphQL.AspNet.Configuration; /// - /// A builder that utilizies a key/value pair system to build up a set of component parts + /// An intermediate template that utilizies a key/value pair system to build up a set of component parts /// that the templating engine will use to generate a full fledged field in a schema. /// - public interface IGraphQLFieldBuilder : IDictionary + public interface IGraphQLFieldTemplate : IDictionary { /// /// Gets the full path template that points to a location in diff --git a/src/graphql-aspnet/Interfaces/Configuration/IGraphQLFieldGroupBuilder.cs b/src/graphql-aspnet/Interfaces/Configuration/IGraphQLResolvedFieldTemplate.cs similarity index 56% rename from src/graphql-aspnet/Interfaces/Configuration/IGraphQLFieldGroupBuilder.cs rename to src/graphql-aspnet/Interfaces/Configuration/IGraphQLResolvedFieldTemplate.cs index f1f9cd6aa..d88dcbadb 100644 --- a/src/graphql-aspnet/Interfaces/Configuration/IGraphQLFieldGroupBuilder.cs +++ b/src/graphql-aspnet/Interfaces/Configuration/IGraphQLResolvedFieldTemplate.cs @@ -14,20 +14,14 @@ namespace GraphQL.AspNet.Interfaces.Configuration using GraphQL.AspNet.Configuration; /// - /// A field builder that can act as a parent for a set of fields. The defined - /// template for this builder will prefix all fields or other field groups created - /// underneath it. Also, all properties and settings, such as authorization requirements, for the "group", are carried - /// into any fields generated. + /// An intermediate template that utilizies a key/value pair system to build up a set of component parts + /// that the templating engine will use to generate a full fledged field in a schema. + /// A field generated via this builder is identicial to a field parsed from a controller action + /// in that it has an explicit resolver applied. The runtime will not attempt to + /// autoresolve this field. /// - public interface IGraphQLFieldGroupBuilder : IDictionary + public interface IGraphQLResolvedFieldTemplate : IDictionary { - // ********************** - // Implementation note (05/23) - Kevin - // This interface is functionally identical to the single field builder - // but is seperate to allow for divation in handling via extension methods and - // potential future development - // ********************** - /// /// Gets the full path template that points to a location in /// the virtual field tree. @@ -50,5 +44,19 @@ public interface IGraphQLFieldGroupBuilder : IDictionary /// /// The collection of applied attributes. IList Attributes { get; } + + /// + /// Gets or sets the resolver function that has been assigned to execute when this + /// field is requested in a query. + /// + /// The field's assigned resolver. + Delegate Resolver { get; set; } + + /// + /// Gets or sets the explicitly declared return type of this field. Can be + /// null if the returns a valid concrete type. + /// + /// The data type this field will return. + Type ReturnType { get; set; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Configuration/IGraphQLTypeExtensionTemplate.cs b/src/graphql-aspnet/Interfaces/Configuration/IGraphQLTypeExtensionTemplate.cs new file mode 100644 index 000000000..20557d735 --- /dev/null +++ b/src/graphql-aspnet/Interfaces/Configuration/IGraphQLTypeExtensionTemplate.cs @@ -0,0 +1,37 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Interfaces.Configuration +{ + using System; + using GraphQL.AspNet.Execution; + + /// + /// An intermediate template that utilizies a key/value pair system to build up a set of component parts + /// that the templating engine will use to generate a full fledged type extension in a schema. + /// + public interface IGraphQLTypeExtensionTemplate : IGraphQLResolvedFieldTemplate + { + /// + /// Gets the execution mode of this type extension. + /// + /// + /// The mode must match the resolver definition for this + /// instance or an exception will be thrown. + /// + /// The execution mode of this type extension. + public FieldResolutionMode ExecutionMode { get; } + + /// + /// Gets the OBJECT or INTERFACE type that will be extended. + /// + /// The class, interface or struct that will be extended with this new field. + public Type TargetType { get; } + } +} \ No newline at end of file From 175af771203b5432510f213efa82e729965e79e5 Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Sat, 17 Jun 2023 10:34:24 -0700 Subject: [PATCH 05/63] WIP, added directives to minimal api --- .../GraphQLMinimalApiExtensions_Directives.cs | 190 ++++++++++++++++++ .../GraphQLMinimalApiExtensions_Internals.cs | 20 +- .../GraphQLMinimalApiExtensions_Mutations.cs | 44 +++- .../GraphQLMinimalApiExtensions_Queries.cs | 45 ++++- ...phQLMinimalApiExtensions_ResolvedFields.cs | 2 +- ...phQLMinimalApiExtensions_TypeExtensions.cs | 167 +++++++++++---- ...aphQLMinimalApiExtensions_VirtualFields.cs | 10 +- .../Configuration/SchemaOptions.cs | 23 ++- .../BaseGraphQLRuntimeSchemaItemTemplate.cs} | 25 +-- .../Templates/GraphQLDirectiveTemplate.cs | 38 ++++ .../GraphQLResolvedFieldTemplate.cs | 7 +- .../GraphQLTypeExtensionFieldTemplate.cs | 7 +- .../GraphQLVirtualFieldTemplate.cs | 7 +- .../IGraphQLResolvedFieldTemplate.cs | 62 ------ .../Templates/IGraphQLDirectiveTemplate.cs | 19 ++ .../Templates/IGraphQLFieldTemplate.cs | 23 +++ .../IGraphQLResolvableSchemaItemTemplate.cs | 34 ++++ .../IGraphQLResolvedFieldTemplate.cs | 26 +++ .../IGraphQLRuntimeSchemaItemTemplate.cs} | 23 +-- .../IGraphQLTypeExtensionTemplate.cs | 21 +- .../Engine/TestData/FakeWebSocketManager.cs | 2 +- 21 files changed, 619 insertions(+), 176 deletions(-) create mode 100644 src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Directives.cs rename src/graphql-aspnet/Configuration/{MinimalApi/BaseGraphQLFieldTemplate.cs => Templates/BaseGraphQLRuntimeSchemaItemTemplate.cs} (77%) create mode 100644 src/graphql-aspnet/Configuration/Templates/GraphQLDirectiveTemplate.cs rename src/graphql-aspnet/Configuration/{MinimalApi => Templates}/GraphQLResolvedFieldTemplate.cs (91%) rename src/graphql-aspnet/Configuration/{MinimalApi => Templates}/GraphQLTypeExtensionFieldTemplate.cs (88%) rename src/graphql-aspnet/Configuration/{MinimalApi => Templates}/GraphQLVirtualFieldTemplate.cs (86%) delete mode 100644 src/graphql-aspnet/Interfaces/Configuration/IGraphQLResolvedFieldTemplate.cs create mode 100644 src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLDirectiveTemplate.cs create mode 100644 src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLFieldTemplate.cs create mode 100644 src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLResolvableSchemaItemTemplate.cs create mode 100644 src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLResolvedFieldTemplate.cs rename src/graphql-aspnet/Interfaces/Configuration/{IGraphQLFieldTemplate.cs => Templates/IGraphQLRuntimeSchemaItemTemplate.cs} (53%) rename src/graphql-aspnet/Interfaces/Configuration/{ => Templates}/IGraphQLTypeExtensionTemplate.cs (61%) diff --git a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Directives.cs b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Directives.cs new file mode 100644 index 000000000..059e02284 --- /dev/null +++ b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Directives.cs @@ -0,0 +1,190 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Configuration +{ + using System; + using GraphQL.AspNet.Attributes; + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Interfaces.Configuration; + using GraphQL.AspNet.Interfaces.Configuration.Templates; + using GraphQL.AspNet.Interfaces.Controllers; + using GraphQL.AspNet.Schemas.TypeSystem; + using Microsoft.AspNetCore.Authorization; + + /// + /// Extension methods for configuring minimal API methods as fields on the graph. + /// + public static partial class GraphQLMinimalApiExtensions + { + /// + /// Adds policy-based authorization requirements to the directive. + /// + /// + /// This is similar to adding the to a controller method + /// + /// The directive being built. + /// The name of the policy to assign via this requirement. + /// A comma-seperated list of roles to assign via this requirement. + /// IGraphQLFieldBuilder. + public static IGraphQLDirectiveTemplate RequireAuthorization( + this IGraphQLDirectiveTemplate directiveTemplate, + string policyName = null, + string roles = null) + { + Validation.ThrowIfNull(directiveTemplate, nameof(directiveTemplate)); + + var attrib = new AuthorizeAttribute(); + attrib.Policy = policyName?.Trim(); + attrib.Roles = roles?.Trim(); + directiveTemplate.Attributes.Add(attrib); + return directiveTemplate; + } + + /// + /// Indicates that the directive should allow anonymous access. + /// + /// + /// + /// This is similar to adding the to a controller method + /// + /// + /// Any inherited authorization permissions from field groups are automatically + /// dropped from this field instance. + /// + /// + /// The directive being built. + /// IGraphQLFieldBuilder. + public static IGraphQLDirectiveTemplate AllowAnonymous(this IGraphQLDirectiveTemplate directiveTemplate) + { + Validation.ThrowIfNull(directiveTemplate, nameof(directiveTemplate)); + directiveTemplate.Attributes.Add(new AllowAnonymousAttribute()); + return directiveTemplate; + } + + /// + /// Marks this directive as being repeatable such that it can be applie to a single + /// schema item more than once. + /// + /// The directive template. + /// IGraphQLDirectiveTemplate. + public static IGraphQLDirectiveTemplate IsRepeatable(this IGraphQLDirectiveTemplate directiveTemplate) + { + var repeatable = new RepeatableAttribute(); + directiveTemplate.Attributes.Add(repeatable); + return directiveTemplate; + } + + /// + /// Restricts the locations that this directive can be applied. + /// + /// + /// If called more than once this method acts as an additive restrictor. Each additional + /// call will add more location restrictions. Duplicate restrictions are ignored. + /// + /// The directive template to alter. + /// The bitwise set of locations where this + /// directive can be applied. + /// IGraphQLDirectiveTemplate. + public static IGraphQLDirectiveTemplate RestrictLocations( + this IGraphQLDirectiveTemplate directiveTemplate, + DirectiveLocation locations) + { + var restrictions = new DirectiveLocationsAttribute(locations); + directiveTemplate.Attributes.Add(restrictions); + + return directiveTemplate; + } + + /// + /// Sets the resolver to be used when this directive is requested at runtime. + /// + /// + /// + /// If this method is called more than once, the previously set resolver will be replaced. + /// + /// + /// Directive resolver methods must return a . + /// + /// + /// The directive being built. + /// The delegate to assign as the resolver. This method will be + /// parsed to determine input arguments for the field on the target schema. + /// IGraphQLFieldBuilder. + public static IGraphQLDirectiveTemplate AddResolver(this IGraphQLDirectiveTemplate directiveTemplate, Delegate resolverMethod) + { + directiveTemplate.Resolver = resolverMethod; + directiveTemplate.ReturnType = null; + + return directiveTemplate; + } + + /// + /// Maps a new directive into the target schema. + /// + /// The schema options where the directive will be created. + /// Name of the directive (e.g. '@myDirective'). + /// IGraphQLDirectiveTemplate. + public static IGraphQLDirectiveTemplate MapDirective(this SchemaOptions schemaOptions, string directiveName) + { + return MapDirectiveInternal(schemaOptions, directiveName); + } + + /// + /// Maps a new directive into the target schema. + /// + /// The schema options where the directive will be created. + /// Name of the directive (e.g. '@myDirective'). + /// The resolver that will be executed when the directive is invoked. + /// IGraphQLDirectiveTemplate. + public static IGraphQLDirectiveTemplate MapDirective(this SchemaOptions schemaOptions, string directiveName, Delegate resolverMethod) + { + Validation.ThrowIfNull(resolverMethod, nameof(resolverMethod)); + + var directive = MapDirectiveInternal(schemaOptions, directiveName); + return directive.AddResolver(resolverMethod); + } + + /// + /// Maps a new directive into the target schema. + /// + /// The builder representing the schema being constructed. + /// Name of the directive (e.g. '@myDirective'). + /// IGraphQLDirectiveTemplate. + public static IGraphQLDirectiveTemplate MapDirective(this ISchemaBuilder schemaBuilder, string directiveName) + { + Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); + + var directive = MapDirectiveInternal( + schemaBuilder.Options, + directiveName); + + return directive; + } + + /// + /// Maps a new directive into the target schema. + /// + /// The builder representing the schema being constructed. + /// Name of the directive (e.g. '@myDirective'). + /// The resolver that will be executed when the directive is invoked. + /// IGraphQLDirectiveTemplate. + public static IGraphQLDirectiveTemplate MapDirective(this ISchemaBuilder schemaBuilder, string directiveName, Delegate resolverMethod) + { + Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); + Validation.ThrowIfNull(resolverMethod, nameof(resolverMethod)); + + var directive = MapDirectiveInternal( + schemaBuilder.Options, + directiveName); + + return directive.AddResolver(resolverMethod); + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Internals.cs b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Internals.cs index e2f830ac0..ff8334309 100644 --- a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Internals.cs +++ b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Internals.cs @@ -11,9 +11,9 @@ namespace GraphQL.AspNet.Configuration { using System; using GraphQL.AspNet.Common; - using GraphQL.AspNet.Configuration.MinimalApi; + using GraphQL.AspNet.Configuration.Templates; using GraphQL.AspNet.Execution; - using GraphQL.AspNet.Interfaces.Configuration; + using GraphQL.AspNet.Interfaces.Configuration.Templates; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; @@ -22,7 +22,7 @@ namespace GraphQL.AspNet.Configuration /// public static partial class GraphQLMinimalApiExtensions { - private static IGraphQLFieldTemplate MapGraphQLField( + private static IGraphQLFieldTemplate MapGraphQLFieldInternal( SchemaOptions schemaOptions, GraphOperationType operationType, string pathTemplate) @@ -39,7 +39,7 @@ private static IGraphQLFieldTemplate MapGraphQLField( return fieldTemplate; } - private static IGraphQLResolvedFieldTemplate MapTypeExtension( + private static IGraphQLTypeExtensionTemplate MapTypeExtensionInternal( SchemaOptions schemaOptions, Type typeToExtend, string fieldName, @@ -48,14 +48,22 @@ private static IGraphQLResolvedFieldTemplate MapTypeExtension( schemaOptions = Validation.ThrowIfNullOrReturn(schemaOptions, nameof(schemaOptions)); fieldName = Validation.ThrowIfNullWhiteSpaceOrReturn(fieldName, nameof(fieldName)); - IGraphQLResolvedFieldTemplate field = new GraphQLTypeExtensionFieldTemplate( + IGraphQLTypeExtensionTemplate field = new GraphQLTypeExtensionFieldTemplate( schemaOptions, typeToExtend, fieldName, resolutionMode); - schemaOptions.AddFieldTemplate(field); + schemaOptions.AddSchemaItemTemplate(field); return field; } + + private static IGraphQLDirectiveTemplate MapDirectiveInternal(this SchemaOptions schemaOptions, string directiveName) + { + var directive = new GraphQLDirectiveTemplate(schemaOptions, directiveName); + + schemaOptions.AddSchemaItemTemplate(directive); + return directive; + } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Mutations.cs b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Mutations.cs index c470038f1..ddc6ead4e 100644 --- a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Mutations.cs +++ b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Mutations.cs @@ -12,6 +12,7 @@ namespace GraphQL.AspNet.Configuration using System; using GraphQL.AspNet.Common; using GraphQL.AspNet.Interfaces.Configuration; + using GraphQL.AspNet.Interfaces.Configuration.Templates; using GraphQL.AspNet.Schemas.TypeSystem; /// @@ -19,9 +20,17 @@ namespace GraphQL.AspNet.Configuration /// public static partial class GraphQLMinimalApiExtensions { + /// + /// Creates a new field in the mutation root object with the given path. This field can act as a + /// grouping field of other resolvable fields or be converted to an explicitly resolvable field itself. + /// + /// The options representing the schema where this field + /// will be created. + /// The template path string for his field. (e.g. /path1/path2/path3) + /// IGraphQLFieldTemplate. public static IGraphQLFieldTemplate MapMutation(this SchemaOptions schemaOptions, string template) { - var field = MapGraphQLField( + var field = MapGraphQLFieldInternal( schemaOptions, GraphOperationType.Mutation, template); @@ -29,11 +38,21 @@ public static IGraphQLFieldTemplate MapMutation(this SchemaOptions schemaOptions return field; } + /// + /// Creates a new, explicitly resolvable field in the mutation root object with the given path. This field cannot be + /// further extended or nested with other fields via the Mapping API. + /// + /// The options representing the schema where this field + /// will be created. + /// The template path string for his field. (e.g. /path1/path2/path3) + /// The resolver method to execute when + /// this field is requested by a caller. + /// IGraphQLResolvedFieldTemplate. public static IGraphQLResolvedFieldTemplate MapMutation(this SchemaOptions schemaOptions, string template, Delegate resolverMethod) { Validation.ThrowIfNull(resolverMethod, nameof(resolverMethod)); - var field = MapGraphQLField( + var field = MapGraphQLFieldInternal( schemaOptions, GraphOperationType.Mutation, template); @@ -41,11 +60,19 @@ public static IGraphQLResolvedFieldTemplate MapMutation(this SchemaOptions schem return field.AddResolver(resolverMethod); } + /// + /// Creates a new, explicitly resolvable field in the mutation root object with the given path. This field cannot be + /// further extended or nested with other fields via the Mapping API. + /// + /// The builder representing the schema where this field + /// will be created. + /// The template path string for his field. (e.g. /path1/path2/path3) + /// IGraphQLFieldTemplate. public static IGraphQLFieldTemplate MapMutation(this ISchemaBuilder schemaBuilder, string template) { Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); - var field = MapGraphQLField( + var field = MapGraphQLFieldInternal( schemaBuilder.Options, GraphOperationType.Mutation, template); @@ -53,12 +80,21 @@ public static IGraphQLFieldTemplate MapMutation(this ISchemaBuilder schemaBuilde return field; } + /// + /// Creates a new field in the mutation root object with the given path. This field can act as a + /// grouping field of other resolvable fields or be converted to an explicitly resolvable field itself. + /// + /// The builder representing the schema where this field + /// will be created. + /// The template path string for his field. (e.g. /path1/path2/path3) + /// The resolver method to execute when this field is requested. + /// IGraphQLFieldTemplate. public static IGraphQLResolvedFieldTemplate MapMutation(this ISchemaBuilder schemaBuilder, string template, Delegate resolverMethod) { Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); Validation.ThrowIfNull(resolverMethod, nameof(resolverMethod)); - var field = MapGraphQLField( + var field = MapGraphQLFieldInternal( schemaBuilder.Options, GraphOperationType.Mutation, template); diff --git a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Queries.cs b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Queries.cs index 7c1887b29..9936f8ae6 100644 --- a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Queries.cs +++ b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Queries.cs @@ -12,6 +12,7 @@ namespace GraphQL.AspNet.Configuration using System; using GraphQL.AspNet.Common; using GraphQL.AspNet.Interfaces.Configuration; + using GraphQL.AspNet.Interfaces.Configuration.Templates; using GraphQL.AspNet.Schemas.TypeSystem; /// @@ -19,9 +20,17 @@ namespace GraphQL.AspNet.Configuration /// public static partial class GraphQLMinimalApiExtensions { + /// + /// Creates a new field in the query root object with the given path. This field can act as a + /// grouping field of other resolvable fields or be converted to an explicitly resolvable field itself. + /// + /// The options representing the schema where this field + /// will be created. + /// The template path string for his field. (e.g. /path1/path2/path3) + /// IGraphQLFieldTemplate. public static IGraphQLFieldTemplate MapQuery(this SchemaOptions schemaOptions, string template) { - var field = MapGraphQLField( + var field = MapGraphQLFieldInternal( schemaOptions, GraphOperationType.Query, template); @@ -29,11 +38,21 @@ public static IGraphQLFieldTemplate MapQuery(this SchemaOptions schemaOptions, s return field; } + /// + /// Creates a new, explicitly resolvable field in the query root object with the given path. This field cannot be + /// further extended or nested with other fields via the Mapping API. + /// + /// The options representing the schema where this field + /// will be created. + /// The template path string for his field. (e.g. /path1/path2/path3) + /// The resolver method to execute when + /// this field is requested by a caller. + /// IGraphQLResolvedFieldTemplate. public static IGraphQLResolvedFieldTemplate MapQuery(this SchemaOptions schemaOptions, string template, Delegate resolverMethod) { Validation.ThrowIfNull(resolverMethod, nameof(resolverMethod)); - var field = MapGraphQLField( + var field = MapGraphQLFieldInternal( schemaOptions, GraphOperationType.Query, template); @@ -41,11 +60,19 @@ public static IGraphQLResolvedFieldTemplate MapQuery(this SchemaOptions schemaOp return field.AddResolver(resolverMethod); } + /// + /// Creates a new, explicitly resolvable field in the query root object with the given path. This field cannot be + /// further extended or nested with other fields via the Mapping API. + /// + /// The builder representing the schema where this field + /// will be created. + /// The template path string for his field. (e.g. /path1/path2/path3) + /// IGraphQLFieldTemplate. public static IGraphQLFieldTemplate MapQuery(this ISchemaBuilder schemaBuilder, string template) { Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); - var field = MapGraphQLField( + var field = MapGraphQLFieldInternal( schemaBuilder.Options, GraphOperationType.Query, template); @@ -53,12 +80,22 @@ public static IGraphQLFieldTemplate MapQuery(this ISchemaBuilder schemaBuilder, return field; } + /// + /// Creates a new field in the query object with the given path. This field can act as a + /// grouping field of other resolvable fields or be converted to an explicitly resolvable field itself. + /// + /// The builder representing the schema where this field + /// will be created. + /// The template path string for his field. (e.g. /path1/path2/path3) + /// The resolver method to execute when this + /// field is requested. + /// IGraphQLFieldTemplate. public static IGraphQLResolvedFieldTemplate MapQuery(this ISchemaBuilder schemaBuilder, string template, Delegate resolverMethod) { Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); Validation.ThrowIfNull(resolverMethod, nameof(resolverMethod)); - var field = MapGraphQLField( + var field = MapGraphQLFieldInternal( schemaBuilder.Options, GraphOperationType.Query, template); diff --git a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_ResolvedFields.cs b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_ResolvedFields.cs index 352034a01..f195c6c01 100644 --- a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_ResolvedFields.cs +++ b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_ResolvedFields.cs @@ -12,7 +12,7 @@ namespace GraphQL.AspNet.Configuration using System; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Common; - using GraphQL.AspNet.Interfaces.Configuration; + using GraphQL.AspNet.Interfaces.Configuration.Templates; using GraphQL.AspNet.Interfaces.Controllers; using Microsoft.AspNetCore.Authorization; diff --git a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_TypeExtensions.cs b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_TypeExtensions.cs index 6f1e2ed42..18b019097 100644 --- a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_TypeExtensions.cs +++ b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_TypeExtensions.cs @@ -11,8 +11,12 @@ namespace GraphQL.AspNet.Configuration { using System; using System.Collections.Generic; + using GraphQL.AspNet.Attributes; + using GraphQL.AspNet.Common; using GraphQL.AspNet.Execution; - using GraphQL.AspNet.Interfaces.Configuration; + using GraphQL.AspNet.Interfaces.Configuration.Templates; + using GraphQL.AspNet.Interfaces.Controllers; + using Microsoft.AspNetCore.Authorization; /// /// Extension methods for configuring minimal API methods as fields on the graph. @@ -20,66 +24,102 @@ namespace GraphQL.AspNet.Configuration public static partial class GraphQLMinimalApiExtensions { /// - /// Registers a new batched type extension to a given type for the target schema. + /// Adds policy-based authorization requirements to the field. /// /// - /// The supplied resolver must declare a parameter that implements an - /// for the supplied . + /// This is similar to adding the to a controller method /// - /// The concrete interface, class or struct to extend with a new field. - /// The configuration options for the target schema. - /// Name of the field to add to the . - /// The resolver method to be called when the field is requested. - /// IGraphQLResolvedFieldTemplate. - public static IGraphQLResolvedFieldTemplate MapBatchTypeExtension(this SchemaOptions schemaOptions, string fieldName, Delegate resolverMethod = null) + /// The field being built. + /// The name of the policy to assign via this requirement. + /// A comma-seperated list of roles to assign via this requirement. + /// IGraphQLFieldBuilder. + public static IGraphQLTypeExtensionTemplate RequireAuthorization( + this IGraphQLTypeExtensionTemplate fieldBuilder, + string policyName = null, + string roles = null) { - return schemaOptions.MapBatchTypeExtension( - typeof(TType), - fieldName, - resolverMethod); + Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); + + var attrib = new AuthorizeAttribute(); + attrib.Policy = policyName?.Trim(); + attrib.Roles = roles?.Trim(); + fieldBuilder.Attributes.Add(attrib); + return fieldBuilder; } /// - /// Registers a new batched type extension to a given type for the target schema. + /// Indicates that the field should allow anonymous access. /// /// - /// The supplied resolver must declare a parameter that implements an - /// for the supplied . + /// This is similar to adding the to a controller method /// - /// The configuration options for the target schema. - /// The concrete interface, class or struct to extend with a new field. - /// Name of the field to add to the . - /// The resolver method to be called when the field is requested. - /// IGraphQLResolvedFieldTemplate. - public static IGraphQLResolvedFieldTemplate MapBatchTypeExtension(this SchemaOptions schemaOptions, Type typeToExtend, string fieldName, Delegate resolverMethod = null) + /// The field being built. + /// IGraphQLFieldBuilder. + public static IGraphQLTypeExtensionTemplate AllowAnonymous(this IGraphQLTypeExtensionTemplate fieldBuilder) { - var field = MapTypeExtension( - schemaOptions, - typeToExtend, - fieldName, - FieldResolutionMode.Batch); + Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); + fieldBuilder.Attributes.Add(new AllowAnonymousAttribute()); + return fieldBuilder; + } - if (resolverMethod != null) - field = field.AddResolver(resolverMethod); + /// + /// Sets the resolver to be used when this field is requested at runtime. + /// + /// + /// If this method is called more than once the previously set resolver will be replaced. + /// + /// The field being built. + /// The delegate to assign as the resolver. This method will be + /// parsed to determine input arguments for the field on the target schema. + /// IGraphQLFieldBuilder. + public static IGraphQLTypeExtensionTemplate AddResolver(this IGraphQLTypeExtensionTemplate fieldBuilder, Delegate resolverMethod) + { + fieldBuilder.Resolver = resolverMethod; + fieldBuilder.ReturnType = null; - return field; + return fieldBuilder; + } + + /// + /// Sets the resolver to be used when this field is requested at runtime. + /// + /// + /// If this method is called more than once the previously set resolver will be replaced. + /// + /// The expected, primary return type of the field. Must be provided + /// if the supplied delegate returns an . + /// The field being built. + /// The delegate to assign as the resolver. This method will be + /// parsed to determine input arguments for the field on the target schema. + /// IGraphQLFieldBuilder. + public static IGraphQLTypeExtensionTemplate AddResolver(this IGraphQLTypeExtensionTemplate fieldBuilder, Delegate resolverMethod) + { + fieldBuilder.Resolver = resolverMethod; + fieldBuilder.ReturnType = typeof(TReturnType); + return fieldBuilder; } /// /// Registers a new type extension to a given type for the target schema. /// /// - /// The supplied resolver must declare a parameter that is of the same type as . + /// + /// This method is synonymous with using the on + /// a controller action. + /// + /// + /// The supplied resolver must declare a parameter that is of the same type as . + /// /// - /// The concrete interface, class or struct to extend with a new field. + /// The concrete interface, class or struct to extend with a new field. /// The configuration options for the target schema. - /// Name of the field to add to the . + /// Name of the field to add to the . /// The resolver method to be called when the field is requested. /// IGraphQLResolvedFieldTemplate. - public static IGraphQLResolvedFieldTemplate MapTypeExtension(this SchemaOptions schemaOptions, string fieldName, Delegate resolverMethod = null) + public static IGraphQLTypeExtensionTemplate MapField(this SchemaOptions schemaOptions, string fieldName, Delegate resolverMethod = null) { - return schemaOptions.MapTypeExtension( - typeof(TType), + return schemaOptions.MapField( + typeof(TOwnerType), fieldName, resolverMethod); } @@ -88,19 +128,20 @@ public static IGraphQLResolvedFieldTemplate MapTypeExtension(this SchemaO /// Registers a new type extension to a given type for the target schema. /// /// - /// The supplied resolver must declare a parameter that is of the same type as - /// . + /// + /// The supplied resolver must declare a parameter that is of the same type as . + /// /// /// The configuration options for the target schema. - /// The concrete interface, class or struct to extend with a new field. - /// Name of the field to add to the . + /// The concrete interface, class or struct to extend with a new field. + /// Name of the field to add to the . /// The resolver method to be called when the field is requested. /// IGraphQLResolvedFieldTemplate. - public static IGraphQLResolvedFieldTemplate MapTypeExtension(this SchemaOptions schemaOptions, Type typeToExtend, string fieldName, Delegate resolverMethod = null) + public static IGraphQLTypeExtensionTemplate MapField(this SchemaOptions schemaOptions, Type fieldOwnerType, string fieldName, Delegate resolverMethod = null) { - var field = MapTypeExtension( + var field = MapTypeExtensionInternal( schemaOptions, - typeToExtend, + fieldOwnerType, fieldName, FieldResolutionMode.PerSourceItem); @@ -109,5 +150,43 @@ public static IGraphQLResolvedFieldTemplate MapTypeExtension(this SchemaOptions return field; } + + /// + /// Instructs the new type extension field that it should process data in batched mode rather than + /// in a "per source item" mode. + /// + /// + /// + /// The supplied resolver must declare a parameter that is an of the same as + /// class, interface or struct that was originally extended as indicated by . + /// + /// + /// The type extension to make into a batch field. + /// IGraphQLTypeExtensionTemplate. + public static IGraphQLTypeExtensionTemplate WithBatchProcessing(this IGraphQLTypeExtensionTemplate typeExtension) + { + typeExtension.ExecutionMode = FieldResolutionMode.Batch; + return typeExtension; + } + + /// + /// Adds a set of possible return types for this field. This is synonymous to using the + /// on a controller's action method. + /// + /// + /// This method can be called multiple times. Any new types will be appended to the field. + /// + /// The field being built. + /// The first possible type that might be returned by this + /// field. + /// Any number of additional possible types that + /// might be returned by this field. + /// IGraphQLFieldBuilder. + public static IGraphQLTypeExtensionTemplate AddPossibleTypes(this IGraphQLTypeExtensionTemplate fieldBuilder, Type firstPossibleType, params Type[] additionalPossibleTypes) + { + var possibleTypes = new PossibleTypesAttribute(firstPossibleType, additionalPossibleTypes); + fieldBuilder.Attributes.Add(possibleTypes); + return fieldBuilder; + } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_VirtualFields.cs b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_VirtualFields.cs index 8ae386e4d..a2bebd665 100644 --- a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_VirtualFields.cs +++ b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_VirtualFields.cs @@ -11,8 +11,8 @@ namespace GraphQL.AspNet.Configuration { using System; using GraphQL.AspNet.Common; - using GraphQL.AspNet.Configuration.MinimalApi; - using GraphQL.AspNet.Interfaces.Configuration; + using GraphQL.AspNet.Configuration.Templates; + using GraphQL.AspNet.Interfaces.Configuration.Templates; using GraphQL.AspNet.Interfaces.Controllers; using Microsoft.AspNetCore.Authorization; @@ -80,7 +80,7 @@ public static IGraphQLResolvedFieldTemplate AddResolver(this IGraphQLFieldTempla { // convert the virtual field to a resolved field var resolvedBuilder = GraphQLResolvedFieldTemplate.FromFieldTemplate(field); - resolvedBuilder.Options.AddFieldTemplate(resolvedBuilder); + resolvedBuilder.Options.AddSchemaItemTemplate(resolvedBuilder); resolvedBuilder.Resolver = resolverMethod; resolvedBuilder.ReturnType = null; @@ -104,7 +104,7 @@ public static IGraphQLResolvedFieldTemplate AddResolver(this IGraph { // convert the virtual field to a resolved field var resolvedBuilder = GraphQLResolvedFieldTemplate.FromFieldTemplate(field); - resolvedBuilder.Options.AddFieldTemplate(resolvedBuilder); + resolvedBuilder.Options.AddSchemaItemTemplate(resolvedBuilder); resolvedBuilder.Resolver = resolverMethod; resolvedBuilder.ReturnType = typeof(TReturnType); @@ -123,7 +123,7 @@ public static IGraphQLResolvedFieldTemplate MapField(this IGraphQLFieldTemplate var subField = new GraphQLResolvedFieldTemplate(field, subTemplate); subField.AddResolver(resolverMethod); - subField.Options.AddFieldTemplate(subField); + subField.Options.AddSchemaItemTemplate(subField); return subField; } diff --git a/src/graphql-aspnet/Configuration/SchemaOptions.cs b/src/graphql-aspnet/Configuration/SchemaOptions.cs index d0c595694..b5b95fa8e 100644 --- a/src/graphql-aspnet/Configuration/SchemaOptions.cs +++ b/src/graphql-aspnet/Configuration/SchemaOptions.cs @@ -16,10 +16,10 @@ namespace GraphQL.AspNet.Configuration using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Common.Generics; using GraphQL.AspNet.Configuration.Exceptions; - using GraphQL.AspNet.Configuration.MinimalApi; using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Directives; using GraphQL.AspNet.Interfaces.Configuration; + using GraphQL.AspNet.Interfaces.Configuration.Templates; using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Schemas.TypeSystem; @@ -35,6 +35,7 @@ public abstract class SchemaOptions private readonly HashSet _possibleTypes; private readonly List _registeredServices; + private readonly List _runtimeTemplates; private List _configExtensions; /// @@ -51,6 +52,7 @@ public SchemaOptions(Type schemaType, IServiceCollection serviceCollection) Validation.ThrowIfNotCastable(schemaType, nameof(schemaType)); _possibleTypes = new HashSet(SchemaTypeToRegister.DefaultEqualityComparer); + _runtimeTemplates = new List(); _serverExtensions = new Dictionary(); _registeredServices = new List(); _configExtensions = new List(); @@ -348,11 +350,26 @@ internal void FinalizeServiceRegistration() } } - internal void AddFieldTemplate(IGraphQLResolvedFieldTemplate fieldTemplate) + /// + /// Adds the runtime schema item template to the schema options so that it can be + /// created when the schema is set up. + /// + /// The template to add. + internal void AddSchemaItemTemplate(IGraphQLRuntimeSchemaItemTemplate template) { - throw new NotImplementedException(); + _runtimeTemplates.Add(template); } + /// + /// Gets the runtime configured schema item templates that need to be setup + /// when the schema is generated. + /// + /// + /// These are the templates created via the Minimal API methods. + /// + /// The runtime templates. + public IEnumerable RuntimeTemplates => _runtimeTemplates; + /// /// Gets the classes, enums, structs and other types that need to be /// registered to the schema when its created. diff --git a/src/graphql-aspnet/Configuration/MinimalApi/BaseGraphQLFieldTemplate.cs b/src/graphql-aspnet/Configuration/Templates/BaseGraphQLRuntimeSchemaItemTemplate.cs similarity index 77% rename from src/graphql-aspnet/Configuration/MinimalApi/BaseGraphQLFieldTemplate.cs rename to src/graphql-aspnet/Configuration/Templates/BaseGraphQLRuntimeSchemaItemTemplate.cs index d435ec575..c379a870e 100644 --- a/src/graphql-aspnet/Configuration/MinimalApi/BaseGraphQLFieldTemplate.cs +++ b/src/graphql-aspnet/Configuration/Templates/BaseGraphQLRuntimeSchemaItemTemplate.cs @@ -7,39 +7,40 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Configuration.MinimalApi +namespace GraphQL.AspNet.Configuration.Templates { using System; using System.Collections.Generic; using GraphQL.AspNet.Common; - using GraphQL.AspNet.Interfaces.Configuration; + using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Interfaces.Configuration.Templates; using GraphQL.AspNet.Schemas.Structural; /// /// An abstract class containing all the common elements across minimal field builders and /// their supporting classes. /// - internal abstract class BaseGraphQLFieldTemplate : Dictionary + internal abstract class BaseGraphQLRuntimeSchemaItemTemplate : Dictionary, IGraphQLRuntimeSchemaItemTemplate { private IGraphQLFieldTemplate _parent; private string _partialPathTemplate; /// - /// Prevents a default instance of the class from being created. + /// Prevents a default instance of the class from being created. /// - private BaseGraphQLFieldTemplate() + private BaseGraphQLRuntimeSchemaItemTemplate() { this.Attributes = new List(); } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The schema options where this field item /// is being defined. /// The partial path template defined for this /// individual entity. - protected BaseGraphQLFieldTemplate( + protected BaseGraphQLRuntimeSchemaItemTemplate( SchemaOptions options, string partialPathTemplate) : this() @@ -51,12 +52,12 @@ protected BaseGraphQLFieldTemplate( } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The group builder from which this entity is being created. /// The partial path template defined for this /// individual entity. - protected BaseGraphQLFieldTemplate( + protected BaseGraphQLRuntimeSchemaItemTemplate( IGraphQLFieldTemplate parentVirtualFieldBuilder, string partialPathTemplate) : this() @@ -67,13 +68,13 @@ protected BaseGraphQLFieldTemplate( _partialPathTemplate = Validation.ThrowIfNullWhiteSpaceOrReturn(partialPathTemplate, nameof(partialPathTemplate)); } - /// + /// public virtual SchemaOptions Options { get; protected set; } - /// + /// public IList Attributes { get; } - /// + /// public string Template { get diff --git a/src/graphql-aspnet/Configuration/Templates/GraphQLDirectiveTemplate.cs b/src/graphql-aspnet/Configuration/Templates/GraphQLDirectiveTemplate.cs new file mode 100644 index 000000000..57074dba9 --- /dev/null +++ b/src/graphql-aspnet/Configuration/Templates/GraphQLDirectiveTemplate.cs @@ -0,0 +1,38 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Configuration.Templates +{ + using System; + using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Interfaces.Configuration.Templates; + + /// + /// An internal implementation of the + /// used to generate new graphql directives via a minimal api style of coding. + /// + internal class GraphQLDirectiveTemplate : BaseGraphQLRuntimeSchemaItemTemplate, IGraphQLDirectiveTemplate + { + /// + /// Initializes a new instance of the class. + /// + /// The schema options where this directive will be created. + /// Name of the directive to use in the schema. + public GraphQLDirectiveTemplate(SchemaOptions schemaOptions, string directiveName) + : base(schemaOptions, directiveName) + { + } + + /// + public Delegate Resolver { get; set; } + + /// + public Type ReturnType { get; set; } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/MinimalApi/GraphQLResolvedFieldTemplate.cs b/src/graphql-aspnet/Configuration/Templates/GraphQLResolvedFieldTemplate.cs similarity index 91% rename from src/graphql-aspnet/Configuration/MinimalApi/GraphQLResolvedFieldTemplate.cs rename to src/graphql-aspnet/Configuration/Templates/GraphQLResolvedFieldTemplate.cs index f30aebefd..a4b02269b 100644 --- a/src/graphql-aspnet/Configuration/MinimalApi/GraphQLResolvedFieldTemplate.cs +++ b/src/graphql-aspnet/Configuration/Templates/GraphQLResolvedFieldTemplate.cs @@ -7,17 +7,18 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Configuration.MinimalApi +namespace GraphQL.AspNet.Configuration.Templates { using System; using GraphQL.AspNet.Common; - using GraphQL.AspNet.Interfaces.Configuration; + using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Interfaces.Configuration.Templates; /// /// An internal implementation of the /// used to generate new graphql fields via a minimal api style of coding. /// - internal class GraphQLResolvedFieldTemplate : BaseGraphQLFieldTemplate, IGraphQLResolvedFieldTemplate + internal class GraphQLResolvedFieldTemplate : BaseGraphQLRuntimeSchemaItemTemplate, IGraphQLResolvedFieldTemplate { /// /// Converts the unresolved field into a resolved field. The newly generated field diff --git a/src/graphql-aspnet/Configuration/MinimalApi/GraphQLTypeExtensionFieldTemplate.cs b/src/graphql-aspnet/Configuration/Templates/GraphQLTypeExtensionFieldTemplate.cs similarity index 88% rename from src/graphql-aspnet/Configuration/MinimalApi/GraphQLTypeExtensionFieldTemplate.cs rename to src/graphql-aspnet/Configuration/Templates/GraphQLTypeExtensionFieldTemplate.cs index ae007735a..58527cb74 100644 --- a/src/graphql-aspnet/Configuration/MinimalApi/GraphQLTypeExtensionFieldTemplate.cs +++ b/src/graphql-aspnet/Configuration/Templates/GraphQLTypeExtensionFieldTemplate.cs @@ -7,11 +7,12 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Configuration.MinimalApi +namespace GraphQL.AspNet.Configuration.Templates { using System; + using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Execution; - using GraphQL.AspNet.Interfaces.Configuration; + using GraphQL.AspNet.Interfaces.Configuration.Templates; /// /// An internal implementation of the @@ -39,7 +40,7 @@ public GraphQLTypeExtensionFieldTemplate( } /// - public FieldResolutionMode ExecutionMode { get; } + public FieldResolutionMode ExecutionMode { get; set; } /// public Type TargetType { get; } diff --git a/src/graphql-aspnet/Configuration/MinimalApi/GraphQLVirtualFieldTemplate.cs b/src/graphql-aspnet/Configuration/Templates/GraphQLVirtualFieldTemplate.cs similarity index 86% rename from src/graphql-aspnet/Configuration/MinimalApi/GraphQLVirtualFieldTemplate.cs rename to src/graphql-aspnet/Configuration/Templates/GraphQLVirtualFieldTemplate.cs index a4fc1ab22..a915b667a 100644 --- a/src/graphql-aspnet/Configuration/MinimalApi/GraphQLVirtualFieldTemplate.cs +++ b/src/graphql-aspnet/Configuration/Templates/GraphQLVirtualFieldTemplate.cs @@ -7,15 +7,16 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Configuration.MinimalApi +namespace GraphQL.AspNet.Configuration.Templates { - using GraphQL.AspNet.Interfaces.Configuration; + using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Interfaces.Configuration.Templates; /// /// An internal implementation of the /// used to generate new graphql fields via a minimal api style of coding. /// - internal class GraphQLVirtualFieldTemplate : BaseGraphQLFieldTemplate, IGraphQLFieldTemplate + internal class GraphQLVirtualFieldTemplate : BaseGraphQLRuntimeSchemaItemTemplate, IGraphQLFieldTemplate { /// /// Initializes a new instance of the class. diff --git a/src/graphql-aspnet/Interfaces/Configuration/IGraphQLResolvedFieldTemplate.cs b/src/graphql-aspnet/Interfaces/Configuration/IGraphQLResolvedFieldTemplate.cs deleted file mode 100644 index d88dcbadb..000000000 --- a/src/graphql-aspnet/Interfaces/Configuration/IGraphQLResolvedFieldTemplate.cs +++ /dev/null @@ -1,62 +0,0 @@ -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - -namespace GraphQL.AspNet.Interfaces.Configuration -{ - using System; - using System.Collections.Generic; - using GraphQL.AspNet.Configuration; - - /// - /// An intermediate template that utilizies a key/value pair system to build up a set of component parts - /// that the templating engine will use to generate a full fledged field in a schema. - /// A field generated via this builder is identicial to a field parsed from a controller action - /// in that it has an explicit resolver applied. The runtime will not attempt to - /// autoresolve this field. - /// - public interface IGraphQLResolvedFieldTemplate : IDictionary - { - /// - /// Gets the full path template that points to a location in - /// the virtual field tree. - /// - /// - /// e.g. /path1/path2/path3 - /// - /// The fully qualified path template for this builder. - string Template { get; } - - /// - /// Gets the set of schema options under with this field is being defined. - /// - /// The schema options on which this field is being defined. - SchemaOptions Options { get; } - - /// - /// Gets a list of attributes that have been applied to this builder. This mimics - /// the collection of applied attributes to a controller method. - /// - /// The collection of applied attributes. - IList Attributes { get; } - - /// - /// Gets or sets the resolver function that has been assigned to execute when this - /// field is requested in a query. - /// - /// The field's assigned resolver. - Delegate Resolver { get; set; } - - /// - /// Gets or sets the explicitly declared return type of this field. Can be - /// null if the returns a valid concrete type. - /// - /// The data type this field will return. - Type ReturnType { get; set; } - } -} \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLDirectiveTemplate.cs b/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLDirectiveTemplate.cs new file mode 100644 index 000000000..c3ce8a9dc --- /dev/null +++ b/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLDirectiveTemplate.cs @@ -0,0 +1,19 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Interfaces.Configuration.Templates +{ + /// + /// An intermediate template that utilizies a key/value pair system to build up a set of component parts + /// that the templating engine will use to generate a full fledged field in a schema. + /// + public interface IGraphQLDirectiveTemplate : IGraphQLRuntimeSchemaItemTemplate, IGraphQLResolvableSchemaItemTemplate + { + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLFieldTemplate.cs b/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLFieldTemplate.cs new file mode 100644 index 000000000..6a43b61fd --- /dev/null +++ b/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLFieldTemplate.cs @@ -0,0 +1,23 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Interfaces.Configuration.Templates +{ + using System; + using System.Collections.Generic; + using GraphQL.AspNet.Configuration; + + /// + /// An intermediate template that utilizies a key/value pair system to build up a set of component parts + /// that the templating engine will use to generate a full fledged field in a schema. + /// + public interface IGraphQLFieldTemplate : IGraphQLRuntimeSchemaItemTemplate + { + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLResolvableSchemaItemTemplate.cs b/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLResolvableSchemaItemTemplate.cs new file mode 100644 index 000000000..992bd2f22 --- /dev/null +++ b/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLResolvableSchemaItemTemplate.cs @@ -0,0 +1,34 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Interfaces.Configuration.Templates +{ + using System; + + /// + /// A template for a runtime created schema item that has an attached resolver. Usually + /// a field or a directive. + /// + public interface IGraphQLResolvableSchemaItemTemplate + { + /// + /// Gets or sets the resolver function that has been assigned to execute when this + /// schema item is requested or processed. + /// + /// The field's assigned resolver. + Delegate Resolver { get; set; } + + /// + /// Gets or sets the explicitly declared return type of this schema item. Can be + /// null if the returns a valid concrete type. + /// + /// The data type this schema item will return. + Type ReturnType { get; set; } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLResolvedFieldTemplate.cs b/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLResolvedFieldTemplate.cs new file mode 100644 index 000000000..ffcc613d5 --- /dev/null +++ b/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLResolvedFieldTemplate.cs @@ -0,0 +1,26 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Interfaces.Configuration.Templates +{ + using System; + using System.Collections.Generic; + using GraphQL.AspNet.Configuration; + + /// + /// An intermediate template that utilizies a key/value pair system to build up a set of component parts + /// that the templating engine will use to generate a full fledged field in a schema. + /// A field generated via this builder is identicial to a field parsed from a controller action + /// in that it has an explicit resolver applied. The runtime will not attempt to + /// autoresolve this field. + /// + public interface IGraphQLResolvedFieldTemplate : IGraphQLRuntimeSchemaItemTemplate, IGraphQLResolvableSchemaItemTemplate + { + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Configuration/IGraphQLFieldTemplate.cs b/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLRuntimeSchemaItemTemplate.cs similarity index 53% rename from src/graphql-aspnet/Interfaces/Configuration/IGraphQLFieldTemplate.cs rename to src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLRuntimeSchemaItemTemplate.cs index 4f8aff8d6..97cd3938d 100644 --- a/src/graphql-aspnet/Interfaces/Configuration/IGraphQLFieldTemplate.cs +++ b/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLRuntimeSchemaItemTemplate.cs @@ -7,36 +7,33 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Interfaces.Configuration +namespace GraphQL.AspNet.Interfaces.Configuration.Templates { using System; using System.Collections.Generic; using GraphQL.AspNet.Configuration; /// - /// An intermediate template that utilizies a key/value pair system to build up a set of component parts - /// that the templating engine will use to generate a full fledged field in a schema. + /// A marker templtae for any runtime-built schema item (field, directive etc.) + /// being added to the schema. /// - public interface IGraphQLFieldTemplate : IDictionary + public interface IGraphQLRuntimeSchemaItemTemplate : IDictionary { /// - /// Gets the full path template that points to a location in - /// the virtual field tree. + /// Gets the templated name that will be given to the item on the target schema. /// - /// - /// e.g. /path1/path2/path3 - /// - /// The fully qualified path template for this builder. + /// The fully qualified template for this item. + /// (e.g. '@myDirective', '/path1/path2'). string Template { get; } /// - /// Gets the set of schema options under with this field is being defined. + /// Gets the set of schema options under which this directive is being defined. /// - /// The schema options on which this field is being defined. + /// The schema options on which this directive is being defined. SchemaOptions Options { get; } /// - /// Gets a list of attributes that have been applied to this builder. This mimics + /// Gets a list of attributes that have been applied to this directive. This mimics /// the collection of applied attributes to a controller method. /// /// The collection of applied attributes. diff --git a/src/graphql-aspnet/Interfaces/Configuration/IGraphQLTypeExtensionTemplate.cs b/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLTypeExtensionTemplate.cs similarity index 61% rename from src/graphql-aspnet/Interfaces/Configuration/IGraphQLTypeExtensionTemplate.cs rename to src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLTypeExtensionTemplate.cs index 20557d735..c5eb34267 100644 --- a/src/graphql-aspnet/Interfaces/Configuration/IGraphQLTypeExtensionTemplate.cs +++ b/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLTypeExtensionTemplate.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Interfaces.Configuration +namespace GraphQL.AspNet.Interfaces.Configuration.Templates { using System; using GraphQL.AspNet.Execution; @@ -16,22 +16,19 @@ namespace GraphQL.AspNet.Interfaces.Configuration /// An intermediate template that utilizies a key/value pair system to build up a set of component parts /// that the templating engine will use to generate a full fledged type extension in a schema. /// - public interface IGraphQLTypeExtensionTemplate : IGraphQLResolvedFieldTemplate + public interface IGraphQLTypeExtensionTemplate : IGraphQLRuntimeSchemaItemTemplate, IGraphQLResolvableSchemaItemTemplate { /// - /// Gets the execution mode of this type extension. + /// Gets the concrcete type of the OBJECT or INTERFACE that will be extended. /// - /// - /// The mode must match the resolver definition for this - /// instance or an exception will be thrown. - /// - /// The execution mode of this type extension. - public FieldResolutionMode ExecutionMode { get; } + /// The class, interface or struct that will be extended with this new field. + Type TargetType { get; } /// - /// Gets the OBJECT or INTERFACE type that will be extended. + /// Gets or sets the expected processing mode of data when this field is invoked + /// by the runtime. /// - /// The class, interface or struct that will be extended with this new field. - public Type TargetType { get; } + /// The execution mode of this type extension. + FieldResolutionMode ExecutionMode { get; set; } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/TestData/FakeWebSocketManager.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/TestData/FakeWebSocketManager.cs index 9f3136fa2..17ceff9cb 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/TestData/FakeWebSocketManager.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/TestData/FakeWebSocketManager.cs @@ -1,4 +1,4 @@ -// ************************************************************* +// ************************************************************* // project: graphql-aspnet // -- // repo: https://github.com/graphql-aspnet From cc8105a76af75613dcb85249f03c086d7a05e773 Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Sun, 18 Jun 2023 10:27:53 -0700 Subject: [PATCH 06/63] WIP, added tests for minimal API endpoints --- .../GraphQLMinimalApiExtensions_Directives.cs | 19 ++ .../BaseGraphQLRuntimeSchemaItemTemplate.cs | 12 +- .../Templates/GraphQLDirectiveTemplate.cs | 2 + .../Templates/GraphQLResolvedFieldTemplate.cs | 2 + .../GraphQLTypeExtensionFieldTemplate.cs | 2 + .../Templates/GraphQLVirtualFieldTemplate.cs | 2 + .../IGraphQLResolvedFieldTemplate.cs | 1 + .../IGraphQLRuntimeSchemaItemTemplate.cs | 9 + .../Templates/MappedDirectiveTemplateTests.cs | 170 +++++++++++++++++ .../Templates/MappedMutationTemplateTests.cs | 92 ++++++++++ .../Templates/MappedQueryTemplateTests.cs | 94 ++++++++++ .../MappedTypeExtensionTemplateTests.cs | 173 ++++++++++++++++++ .../Templates/ResolvedFieldTemplateTests.cs | 101 ++++++++++ .../Templates/UnresolvedFieldTemplateTests.cs | 143 +++++++++++++++ 14 files changed, 819 insertions(+), 3 deletions(-) create mode 100644 src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedDirectiveTemplateTests.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedMutationTemplateTests.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedQueryTemplateTests.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedTypeExtensionTemplateTests.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Configuration/Templates/ResolvedFieldTemplateTests.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Configuration/Templates/UnresolvedFieldTemplateTests.cs diff --git a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Directives.cs b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Directives.cs index 059e02284..8b54980e4 100644 --- a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Directives.cs +++ b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Directives.cs @@ -125,6 +125,25 @@ public static IGraphQLDirectiveTemplate AddResolver(this IGraphQLDirectiveTempla return directiveTemplate; } + /// + /// Sets the resolver to be used when this directive is requested at runtime. + /// + /// + /// If this method is called more than once the previously set resolver will be replaced. + /// + /// The expected, primary return type of the directive. Must be provided + /// if the supplied delegate returns an . + /// The directive being built. + /// The delegate to assign as the resolver. This method will be + /// parsed to determine input arguments for the directive on the target schema. + /// IGraphQLFieldBuilder. + public static IGraphQLDirectiveTemplate AddResolver(this IGraphQLDirectiveTemplate directiveTemplate, Delegate resolverMethod) + { + directiveTemplate.Resolver = resolverMethod; + directiveTemplate.ReturnType = typeof(TReturnType); + return directiveTemplate; + } + /// /// Maps a new directive into the target schema. /// diff --git a/src/graphql-aspnet/Configuration/Templates/BaseGraphQLRuntimeSchemaItemTemplate.cs b/src/graphql-aspnet/Configuration/Templates/BaseGraphQLRuntimeSchemaItemTemplate.cs index c379a870e..0254730af 100644 --- a/src/graphql-aspnet/Configuration/Templates/BaseGraphQLRuntimeSchemaItemTemplate.cs +++ b/src/graphql-aspnet/Configuration/Templates/BaseGraphQLRuntimeSchemaItemTemplate.cs @@ -68,13 +68,19 @@ protected BaseGraphQLRuntimeSchemaItemTemplate( _partialPathTemplate = Validation.ThrowIfNullWhiteSpaceOrReturn(partialPathTemplate, nameof(partialPathTemplate)); } - /// + /// + public SchemaItemPath CreatePath() + { + return new SchemaItemPath(this.Template); + } + + /// public virtual SchemaOptions Options { get; protected set; } - /// + /// public IList Attributes { get; } - /// + /// public string Template { get diff --git a/src/graphql-aspnet/Configuration/Templates/GraphQLDirectiveTemplate.cs b/src/graphql-aspnet/Configuration/Templates/GraphQLDirectiveTemplate.cs index 57074dba9..c776e859c 100644 --- a/src/graphql-aspnet/Configuration/Templates/GraphQLDirectiveTemplate.cs +++ b/src/graphql-aspnet/Configuration/Templates/GraphQLDirectiveTemplate.cs @@ -10,6 +10,7 @@ namespace GraphQL.AspNet.Configuration.Templates { using System; + using System.Diagnostics; using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Interfaces.Configuration.Templates; @@ -17,6 +18,7 @@ namespace GraphQL.AspNet.Configuration.Templates /// An internal implementation of the /// used to generate new graphql directives via a minimal api style of coding. /// + [DebuggerDisplay("{Template}")] internal class GraphQLDirectiveTemplate : BaseGraphQLRuntimeSchemaItemTemplate, IGraphQLDirectiveTemplate { /// diff --git a/src/graphql-aspnet/Configuration/Templates/GraphQLResolvedFieldTemplate.cs b/src/graphql-aspnet/Configuration/Templates/GraphQLResolvedFieldTemplate.cs index a4b02269b..b2a6fcd1c 100644 --- a/src/graphql-aspnet/Configuration/Templates/GraphQLResolvedFieldTemplate.cs +++ b/src/graphql-aspnet/Configuration/Templates/GraphQLResolvedFieldTemplate.cs @@ -10,6 +10,7 @@ namespace GraphQL.AspNet.Configuration.Templates { using System; + using System.Diagnostics; using GraphQL.AspNet.Common; using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Interfaces.Configuration.Templates; @@ -18,6 +19,7 @@ namespace GraphQL.AspNet.Configuration.Templates /// An internal implementation of the /// used to generate new graphql fields via a minimal api style of coding. /// + [DebuggerDisplay("{Template}")] internal class GraphQLResolvedFieldTemplate : BaseGraphQLRuntimeSchemaItemTemplate, IGraphQLResolvedFieldTemplate { /// diff --git a/src/graphql-aspnet/Configuration/Templates/GraphQLTypeExtensionFieldTemplate.cs b/src/graphql-aspnet/Configuration/Templates/GraphQLTypeExtensionFieldTemplate.cs index 58527cb74..d77635f41 100644 --- a/src/graphql-aspnet/Configuration/Templates/GraphQLTypeExtensionFieldTemplate.cs +++ b/src/graphql-aspnet/Configuration/Templates/GraphQLTypeExtensionFieldTemplate.cs @@ -10,6 +10,7 @@ namespace GraphQL.AspNet.Configuration.Templates { using System; + using System.Diagnostics; using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Execution; using GraphQL.AspNet.Interfaces.Configuration.Templates; @@ -18,6 +19,7 @@ namespace GraphQL.AspNet.Configuration.Templates /// An internal implementation of the /// used to generate new type extensions via a minimal api style of coding. /// + [DebuggerDisplay("{Template}")] internal class GraphQLTypeExtensionFieldTemplate : GraphQLResolvedFieldTemplate, IGraphQLTypeExtensionTemplate { /// diff --git a/src/graphql-aspnet/Configuration/Templates/GraphQLVirtualFieldTemplate.cs b/src/graphql-aspnet/Configuration/Templates/GraphQLVirtualFieldTemplate.cs index a915b667a..1d0d2b567 100644 --- a/src/graphql-aspnet/Configuration/Templates/GraphQLVirtualFieldTemplate.cs +++ b/src/graphql-aspnet/Configuration/Templates/GraphQLVirtualFieldTemplate.cs @@ -9,6 +9,7 @@ namespace GraphQL.AspNet.Configuration.Templates { + using System.Diagnostics; using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Interfaces.Configuration.Templates; @@ -16,6 +17,7 @@ namespace GraphQL.AspNet.Configuration.Templates /// An internal implementation of the /// used to generate new graphql fields via a minimal api style of coding. /// + [DebuggerDisplay("{Template}")] internal class GraphQLVirtualFieldTemplate : BaseGraphQLRuntimeSchemaItemTemplate, IGraphQLFieldTemplate { /// diff --git a/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLResolvedFieldTemplate.cs b/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLResolvedFieldTemplate.cs index ffcc613d5..8a1877e81 100644 --- a/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLResolvedFieldTemplate.cs +++ b/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLResolvedFieldTemplate.cs @@ -11,6 +11,7 @@ namespace GraphQL.AspNet.Interfaces.Configuration.Templates { using System; using System.Collections.Generic; + using System.Diagnostics; using GraphQL.AspNet.Configuration; /// diff --git a/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLRuntimeSchemaItemTemplate.cs b/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLRuntimeSchemaItemTemplate.cs index 97cd3938d..19a1c0bfd 100644 --- a/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLRuntimeSchemaItemTemplate.cs +++ b/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLRuntimeSchemaItemTemplate.cs @@ -12,6 +12,7 @@ namespace GraphQL.AspNet.Interfaces.Configuration.Templates using System; using System.Collections.Generic; using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Schemas.Structural; /// /// A marker templtae for any runtime-built schema item (field, directive etc.) @@ -19,6 +20,14 @@ namespace GraphQL.AspNet.Interfaces.Configuration.Templates /// public interface IGraphQLRuntimeSchemaItemTemplate : IDictionary { + /// + /// Creates a path object using the current template path assigned to this template. This + /// path object is not guarunteed to be the final path when the template is rendered into + /// a schema. + /// + /// SchemaItemPath. + SchemaItemPath CreatePath(); + /// /// Gets the templated name that will be given to the item on the target schema. /// diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedDirectiveTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedDirectiveTemplateTests.cs new file mode 100644 index 000000000..0a3d0b21b --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedDirectiveTemplateTests.cs @@ -0,0 +1,170 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Configuration.Templates +{ + using System.Linq; + using GraphQL.AspNet.Attributes; + using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Interfaces.Configuration; + using GraphQL.AspNet.Interfaces.Configuration.Templates; + using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Schemas.TypeSystem; + using Microsoft.AspNetCore.Authorization; + using Microsoft.Extensions.DependencyInjection; + using Moq; + using NUnit.Framework; + + [TestFixture] + public class MappedDirectiveTemplateTests + { + [Test] + public void MapDirective_ByOptions_AddsDirectiveToOptions() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var directive = options.MapDirective("@myDirective"); + Assert.IsInstanceOf(typeof(IGraphQLDirectiveTemplate), directive); + + Assert.AreEqual(1, options.RuntimeTemplates.Count()); + Assert.IsNotNull(options.RuntimeTemplates.FirstOrDefault(x => x == directive)); + Assert.AreEqual("@myDirective", directive.Template); + Assert.IsNull(directive.ReturnType); + Assert.IsNull(directive.Resolver); + } + + [Test] + public void MapDirective_ByBuilder_AddsDirectiveToOptions() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var builderMock = new Mock(); + builderMock.Setup(x => x.Options).Returns(options); + + var directive = builderMock.Object.MapDirective("@myDirective"); + Assert.IsInstanceOf(typeof(IGraphQLDirectiveTemplate), directive); + + Assert.AreEqual(1, options.RuntimeTemplates.Count()); + Assert.IsNotNull(options.RuntimeTemplates.FirstOrDefault(x => x == directive)); + } + + [Test] + public void MapDirective_ByOptions_WithResolver_AddsDirectiveToOptions() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var directive = options.MapDirective("@myDirective", (string a) => 1); + Assert.IsInstanceOf(typeof(IGraphQLDirectiveTemplate), directive); + + Assert.AreEqual(1, options.RuntimeTemplates.Count()); + Assert.IsNotNull(options.RuntimeTemplates.FirstOrDefault(x => x == directive)); + Assert.AreEqual("@myDirective", directive.Template); + Assert.IsNull(directive.ReturnType); + Assert.AreEqual(typeof(int), directive.Resolver.Method.ReturnType); + } + + [Test] + public void MapDirective_ByBuilder_WithResolver_AddsDirectiveToOptions() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var builderMock = new Mock(); + builderMock.Setup(x => x.Options).Returns(options); + + var directive = builderMock.Object.MapDirective("@myDirective", (string a) => 1); + Assert.IsInstanceOf(typeof(IGraphQLDirectiveTemplate), directive); + + Assert.AreEqual(1, options.RuntimeTemplates.Count()); + Assert.IsNotNull(options.RuntimeTemplates.FirstOrDefault(x => x == directive)); + Assert.IsNull(directive.ReturnType); + Assert.AreEqual(typeof(int), directive.Resolver.Method.ReturnType); + } + + [Test] + public void MappedDirective_WhenAllowAnonymousAdded_AddsAnonymousAttribute() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var directive = options.MapDirective("@mydirective", (string a) => 1); + + directive.AllowAnonymous(); + + Assert.AreEqual(1, directive.Attributes.Count); + Assert.IsNotNull(directive.Attributes.FirstOrDefault(x => x is AllowAnonymousAttribute)); + } + + [Test] + public void MappedDirective_WhenRequireAuthAdded_AddsAuthAttribute() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var directive = options.MapDirective("@mydirective", (string a) => 1); + + directive.RequireAuthorization("policy1", "roles1"); + + Assert.AreEqual(1, directive.Attributes.Count); + var attrib = directive.Attributes.FirstOrDefault(x => x is AuthorizeAttribute) as AuthorizeAttribute; + Assert.IsNotNull(attrib); + Assert.AreEqual("policy1", attrib.Policy); + Assert.AreEqual("roles1", attrib.Roles); + } + + [Test] + public void MappedDirective_WhenLocationRestricted_AddsAttribute() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var directive = options.MapDirective("@mydirective", (string a) => 1); + + directive.RestrictLocations(DirectiveLocation.QUERY | DirectiveLocation.MUTATION); + + Assert.AreEqual(1, directive.Attributes.Count); + var attrib = directive.Attributes.FirstOrDefault(x => x is DirectiveLocationsAttribute) as DirectiveLocationsAttribute; + Assert.IsNotNull(attrib); + Assert.IsTrue(attrib.Locations.HasFlag(DirectiveLocation.QUERY)); + Assert.IsTrue(attrib.Locations.HasFlag(DirectiveLocation.MUTATION)); + } + + [Test] + public void MappedDirective_WhenRepeatableAdded_AddsAttribute() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var directive = options.MapDirective("@mydirective", (string a) => 1); + + directive.IsRepeatable(); + + Assert.AreEqual(1, directive.Attributes.Count); + var attrib = directive.Attributes.FirstOrDefault(x => x is RepeatableAttribute) as RepeatableAttribute; + Assert.IsNotNull(attrib); + } + + [Test] + public void MappedDirective_WhenResolverIsChangedWithExplicitType_NewResolverIsUsedAndTypeIsUsed() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var directive = options.MapDirective("@mydirective", (string a) => 1); + Assert.AreEqual(typeof(int), directive.Resolver.Method.ReturnType); + + directive.AddResolver((string a) => "bob"); + Assert.AreEqual(typeof(string), directive.Resolver.Method.ReturnType); + Assert.AreEqual(typeof(decimal), directive.ReturnType); + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedMutationTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedMutationTemplateTests.cs new file mode 100644 index 000000000..6257c876c --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedMutationTemplateTests.cs @@ -0,0 +1,92 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Configuration.Templates +{ + using System.Linq; + using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Execution; + using GraphQL.AspNet.Interfaces.Configuration; + using GraphQL.AspNet.Interfaces.Configuration.Templates; + using GraphQL.AspNet.Schemas; + using Microsoft.Extensions.DependencyInjection; + using Moq; + using NUnit.Framework; + + [TestFixture] + public class MappedMutationTemplateTests + { + public int TestDelegate(string a) + { + return 0; + } + + [Test] + public void MapMutation_FromSchemaOptions_WithNoDelegate_DoesNotAddFieldToSchema() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapMutation("/path1/path2"); + + Assert.IsNotNull(field); + Assert.AreEqual(SchemaItemCollections.Mutation, field.CreatePath().RootCollection); + Assert.IsInstanceOf(typeof(IGraphQLFieldTemplate), field); + Assert.AreEqual(0, options.RuntimeTemplates.Count()); + } + + [Test] + public void MapMutation_FromSchemaOptions_WithDelegate_DoesAddFieldToSchema() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapMutation("/path1/path2", TestDelegate); + + Assert.IsNotNull(field); + Assert.AreEqual(SchemaItemCollections.Mutation, field.CreatePath().RootCollection); + Assert.IsInstanceOf(typeof(IGraphQLResolvedFieldTemplate), field); + Assert.AreEqual(1, options.RuntimeTemplates.Count()); + } + + [Test] + public void MapMutation_FromBuilder_WithNoDelegate_DoesNotAddFieldToSchema() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var builderMock = new Mock(); + builderMock.Setup(x => x.Options).Returns(options); + + var field = builderMock.Object.MapMutation("/path1/path2"); + + Assert.IsNotNull(field); + Assert.AreEqual(SchemaItemCollections.Mutation, field.CreatePath().RootCollection); + Assert.IsInstanceOf(typeof(IGraphQLFieldTemplate), field); + Assert.AreEqual(0, options.RuntimeTemplates.Count()); + } + + [Test] + public void MapMutation_FromBuilder_WithDelegate_DoesAddFieldToSchema() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var builderMock = new Mock(); + builderMock.Setup(x => x.Options).Returns(options); + + var field = builderMock.Object.MapMutation("/path1/path2", TestDelegate); + + Assert.IsNotNull(field); + Assert.AreEqual(SchemaItemCollections.Mutation, field.CreatePath().RootCollection); + Assert.IsInstanceOf(typeof(IGraphQLResolvedFieldTemplate), field); + Assert.AreEqual(1, options.RuntimeTemplates.Count()); + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedQueryTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedQueryTemplateTests.cs new file mode 100644 index 000000000..15854956f --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedQueryTemplateTests.cs @@ -0,0 +1,94 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Configuration.Templates +{ + using System.Linq; + using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Execution; + using GraphQL.AspNet.Interfaces.Configuration; + using GraphQL.AspNet.Interfaces.Configuration.Templates; + using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Tests.Framework; + using Microsoft.Extensions.DependencyInjection; + using Moq; + using NUnit.Framework; + + [TestFixture] + public class MappedQueryTemplateTests + { + public int TestDelegate(string a) + { + return 0; + } + + [Test] + public void MapQuery_FromSchemaOptions_WithNoDelegate_DoesNotAddFieldToSchema() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapQuery("/path1/path2"); + + Assert.IsNotNull(field); + Assert.AreEqual(SchemaItemCollections.Query, field.CreatePath().RootCollection); + Assert.IsInstanceOf(typeof(IGraphQLFieldTemplate), field); + Assert.AreEqual(0, options.RuntimeTemplates.Count()); + } + + [Test] + public void MapQuery_FromSchemaOptions_WithDelegate_DoesAddFieldToSchema() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapQuery("/path1/path2", TestDelegate); + + Assert.IsNotNull(field); + Assert.AreEqual(SchemaItemCollections.Query, field.CreatePath().RootCollection); + Assert.IsInstanceOf(typeof(IGraphQLResolvedFieldTemplate), field); + Assert.AreEqual(1, options.RuntimeTemplates.Count()); + } + + [Test] + public void MapQuery_FromBuilder_WithNoDelegate_DoesNotAddFieldToSchema() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var builderMock = new Mock(); + builderMock.Setup(x => x.Options).Returns(options); + + var field = builderMock.Object.MapQuery("/path1/path2"); + + Assert.IsNotNull(field); + Assert.AreEqual(SchemaItemCollections.Query, field.CreatePath().RootCollection); + Assert.IsInstanceOf(typeof(IGraphQLFieldTemplate), field); + Assert.AreEqual(0, options.RuntimeTemplates.Count()); + } + + [Test] + public void MapQuery_FromBuilder_WithDelegate_DoesAddFieldToSchema() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var builderMock = new Mock(); + builderMock.Setup(x => x.Options).Returns(options); + + var field = builderMock.Object.MapQuery("/path1/path2", TestDelegate); + + Assert.IsNotNull(field); + Assert.AreEqual(SchemaItemCollections.Query, field.CreatePath().RootCollection); + + Assert.IsInstanceOf(typeof(IGraphQLResolvedFieldTemplate), field); + Assert.AreEqual(1, options.RuntimeTemplates.Count()); + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedTypeExtensionTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedTypeExtensionTemplateTests.cs new file mode 100644 index 000000000..7f35cdc29 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedTypeExtensionTemplateTests.cs @@ -0,0 +1,173 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Configuration.Templates +{ + using System.Linq; + using GraphQL.AspNet.Attributes; + using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Execution; + using GraphQL.AspNet.Interfaces.Configuration; + using GraphQL.AspNet.Interfaces.Configuration.Templates; + using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using Microsoft.AspNetCore.Authorization; + using Microsoft.Extensions.DependencyInjection; + using Moq; + using NUnit.Framework; + + [TestFixture] + public class MappedTypeExtensionTemplateTests + { + public IGraphQLRuntimeSchemaItemTemplate TypeExtension { get; private set; } + + [Test] + public void MapTypeExtension_ByOptions_AddsTypeExtensionToOptions() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var typeExt = options.MapField("myField"); + Assert.IsInstanceOf(typeof(IGraphQLTypeExtensionTemplate), typeExt); + + Assert.AreEqual(1, options.RuntimeTemplates.Count()); + Assert.IsNotNull(options.RuntimeTemplates.FirstOrDefault(x => x == typeExt)); + Assert.AreEqual("myField", typeExt.Template); + Assert.IsNull(typeExt.ReturnType); + Assert.IsNull(typeExt.Resolver); + Assert.AreEqual(FieldResolutionMode.PerSourceItem, typeExt.ExecutionMode); + } + + [Test] + public void MapTypeExtension_ByBuilder_AddsTypeExtensionToOptions() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var builderMock = new Mock(); + builderMock.Setup(x => x.Options).Returns(options); + + var typeExt = options.MapField("myField"); + Assert.IsInstanceOf(typeof(IGraphQLTypeExtensionTemplate), typeExt); + + Assert.AreEqual(1, options.RuntimeTemplates.Count()); + Assert.IsNotNull(options.RuntimeTemplates.FirstOrDefault(x => x == typeExt)); + Assert.AreEqual(FieldResolutionMode.PerSourceItem, typeExt.ExecutionMode); + } + + [Test] + public void MapTypeExtension_ByOptions_WithResolver_AddsTypeExtensionToOptions() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var typeExt = options.MapField("myField", (string a) => 1); + Assert.IsInstanceOf(typeof(IGraphQLTypeExtensionTemplate), typeExt); + + Assert.AreEqual(1, options.RuntimeTemplates.Count()); + Assert.IsNotNull(options.RuntimeTemplates.FirstOrDefault(x => x == typeExt)); + Assert.AreEqual("myField", typeExt.Template); + Assert.IsNull(typeExt.ReturnType); + Assert.AreEqual(typeof(int), typeExt.Resolver.Method.ReturnType); + } + + [Test] + public void MapTypeExtension_ByBuilder_WithResolver_AddsTypeExtensionToOptions() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var builderMock = new Mock(); + builderMock.Setup(x => x.Options).Returns(options); + + var typeExt = options.MapField("myField", (string a) => 1); + Assert.IsInstanceOf(typeof(IGraphQLTypeExtensionTemplate), typeExt); + + Assert.AreEqual(1, options.RuntimeTemplates.Count()); + Assert.IsNotNull(options.RuntimeTemplates.FirstOrDefault(x => x == typeExt)); + Assert.IsNull(typeExt.ReturnType); + Assert.AreEqual(typeof(int), typeExt.Resolver.Method.ReturnType); + } + + [Test] + public void MappedTypeExtension_WhenAllowAnonymousAdded_AddsAnonymousAttribute() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var typeExt = options.MapField("myField", (string a) => 1); + + typeExt.AllowAnonymous(); + + Assert.AreEqual(1, typeExt.Attributes.Count); + Assert.IsNotNull(typeExt.Attributes.FirstOrDefault(x => x is AllowAnonymousAttribute)); + } + + [Test] + public void MappedTypeExtension_WhenRequireAuthAdded_AddsAuthAttribute() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var typeExt = options.MapField("myField", (string a) => 1); + + typeExt.RequireAuthorization("policy1", "roles1"); + + Assert.AreEqual(1, typeExt.Attributes.Count); + var attrib = typeExt.Attributes.FirstOrDefault(x => x is AuthorizeAttribute) as AuthorizeAttribute; + Assert.IsNotNull(attrib); + Assert.AreEqual("policy1", attrib.Policy); + Assert.AreEqual("roles1", attrib.Roles); + } + + [Test] + public void MappedTypeExtension_WhenResolverIsChangedWithExplicitType_NewResolverIsUsedAndTypeIsUsed() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var typeExt = options.MapField("myField", (string a) => 1); + Assert.AreEqual(typeof(int), typeExt.Resolver.Method.ReturnType); + + typeExt.AddResolver((string a) => "bob"); + Assert.AreEqual(typeof(string), typeExt.Resolver.Method.ReturnType); + Assert.AreEqual(typeof(decimal), typeExt.ReturnType); + } + + [Test] + public void MappedTypeExtension_WithBatchProcessing_ChangesExecutionMode() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var typeExt = options.MapField("myField", (string a) => 1); + Assert.AreEqual(FieldResolutionMode.PerSourceItem, typeExt.ExecutionMode); + + typeExt.WithBatchProcessing(); + Assert.AreEqual(FieldResolutionMode.Batch, typeExt.ExecutionMode); + } + + [Test] + public void MappedTypeExtension_AddPossibleTypes_AddsAppropriateAttribute() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var typeExt = options.MapField("myField", (string a) => 1); + typeExt.AddPossibleTypes(typeof(TwoPropertyObjectV2), typeof(TwoPropertyObjectV3)); + + Assert.AreEqual(1, typeExt.Attributes.Count); + var attrib = typeExt.Attributes.FirstOrDefault(x => x is PossibleTypesAttribute) as PossibleTypesAttribute; + + Assert.AreEqual(2, attrib.PossibleTypes.Count); + Assert.IsNotNull(attrib.PossibleTypes.FirstOrDefault(x => x == typeof(TwoPropertyObjectV2))); + Assert.IsNotNull(attrib.PossibleTypes.FirstOrDefault(x => x == typeof(TwoPropertyObjectV3))); + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/ResolvedFieldTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/ResolvedFieldTemplateTests.cs new file mode 100644 index 000000000..a672aaf49 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/ResolvedFieldTemplateTests.cs @@ -0,0 +1,101 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Configuration.Templates +{ + using System.Linq; + using GraphQL.AspNet.Attributes; + using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Interfaces.Configuration.Templates; + using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using Microsoft.AspNetCore.Authorization; + using Microsoft.Extensions.DependencyInjection; + using NUnit.Framework; + + [TestFixture] + public class ResolvedFieldTemplateTests + { + [Test] + public void ResolvedField_WhenAllowAnonymousAdded_AddsAnonymousAttribute() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapQuery("/path1/path2", (string a) => 1); + + field.AllowAnonymous(); + + Assert.AreEqual(1, field.Attributes.Count); + Assert.IsNotNull(field.Attributes.FirstOrDefault(x => x is AllowAnonymousAttribute)); + } + + [Test] + public void ResolvedField_WhenRequireAuthAdded_AddsAuthAttribute() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapQuery("/path1/path2", (string a) => 1); + + field.RequireAuthorization("policy1", "roles1"); + + Assert.AreEqual(1, field.Attributes.Count); + var attrib = field.Attributes.FirstOrDefault(x => x is AuthorizeAttribute) as AuthorizeAttribute; + Assert.IsNotNull(attrib); + Assert.AreEqual("policy1", attrib.Policy); + Assert.AreEqual("roles1", attrib.Roles); + } + + [Test] + public void ResolvedField_WhenResolverIsChanged_NewResolverIsUsed() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapQuery("/path1/path2", (string a) => 1); + Assert.AreEqual(typeof(int), field.Resolver.Method.ReturnType); + + field.AddResolver((string a) => "bob"); + Assert.AreEqual(typeof(string), field.Resolver.Method.ReturnType); + Assert.IsNull(field.ReturnType); + } + + [Test] + public void ResolvedField_WhenResolverIsChangedWithExplicitType_NewResolverIsUsedAndTypeIsUsed() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapQuery("/path1/path2", (string a) => 1); + Assert.AreEqual(typeof(int), field.Resolver.Method.ReturnType); + + field.AddResolver((string a) => "bob"); + Assert.AreEqual(typeof(string), field.Resolver.Method.ReturnType); + Assert.AreEqual(typeof(decimal), field.ReturnType); + } + + [Test] + public void ResolvedField_AddPossibleTypes_AddsAppropriateAttribute() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapMutation("/path1/path2", (string a) => 1); + field.AddPossibleTypes(typeof(TwoPropertyObject), typeof(TwoPropertyObjectV2)); + + Assert.AreEqual(1, field.Attributes.Count); + var attrib = field.Attributes.FirstOrDefault(x => x is PossibleTypesAttribute) as PossibleTypesAttribute; + + Assert.AreEqual(2, attrib.PossibleTypes.Count); + Assert.IsNotNull(attrib.PossibleTypes.FirstOrDefault(x => x == typeof(TwoPropertyObject))); + Assert.IsNotNull(attrib.PossibleTypes.FirstOrDefault(x => x == typeof(TwoPropertyObjectV2))); + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/UnresolvedFieldTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/UnresolvedFieldTemplateTests.cs new file mode 100644 index 000000000..503747526 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/UnresolvedFieldTemplateTests.cs @@ -0,0 +1,143 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Configuration.Templates +{ + using System.Linq; + using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Interfaces.Configuration.Templates; + using GraphQL.AspNet.Schemas; + using Microsoft.AspNetCore.Authorization; + using Microsoft.Extensions.DependencyInjection; + using NUnit.Framework; + + [TestFixture] + public class UnresolvedFieldTemplateTests + { + [Test] + public void UnresolvedField_WhenAllowAnonymousAdded_AddsAnonymousAttribute() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapQuery("/path1/path2"); + + field.AllowAnonymous(); + + Assert.AreEqual(1, field.Attributes.Count); + Assert.IsNotNull(field.Attributes.FirstOrDefault(x => x is AllowAnonymousAttribute)); + } + + [Test] + public void UnresolvedField_WhenRequireAuthAdded_AddsAuthAttribute() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapQuery("/path1/path2"); + + field.RequireAuthorization("policy1", "roles1"); + + Assert.AreEqual(1, field.Attributes.Count); + var attrib = field.Attributes.FirstOrDefault(x => x is AuthorizeAttribute) as AuthorizeAttribute; + Assert.IsNotNull(attrib); + Assert.AreEqual("policy1", attrib.Policy); + Assert.AreEqual("roles1", attrib.Roles); + } + + [Test] + public void UnresolvedField_WhenResolverAdded_BecomesResolvedField() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapQuery("/path1/path2"); + + Assert.IsInstanceOf(typeof(IGraphQLFieldTemplate), field); + Assert.IsNotInstanceOf(typeof(IGraphQLResolvedFieldTemplate), field); + + var field1 = field.AddResolver((string a) => 1); + Assert.IsInstanceOf(typeof(IGraphQLResolvedFieldTemplate), field1); + Assert.IsNull(field1.ReturnType); + } + + [Test] + public void UnresolvedField_WhenResolverAddedWithSpecificType_BecomesResolvedField() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapQuery("/path1/path2"); + + Assert.IsInstanceOf(typeof(IGraphQLFieldTemplate), field); + Assert.IsNotInstanceOf(typeof(IGraphQLResolvedFieldTemplate), field); + + var field1 = field.AddResolver((string a) => 1); + Assert.IsInstanceOf(typeof(IGraphQLResolvedFieldTemplate), field1); + Assert.AreEqual(typeof(decimal), field1.ReturnType); + } + + [Test] + public void UnresolvedField_WhenUnresolvedChildFieldIsAdded_PathIsCorrect() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapQuery("/path1/path2"); + + var childField = field.MapField("/path3/path4"); + + var path = childField.CreatePath(); + Assert.AreEqual("[query]/path1/path2/path3/path4", path.Path); + } + + [Test] + public void UnresolvedField_WhenResolvedChildFieldIsAdded_PathIsCorrect() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapQuery("/path1/path2"); + + var childField = field.MapField("/path3/path4", (string a) => 1); + + var path = childField.CreatePath(); + Assert.AreEqual("[query]/path1/path2/path3/path4", path.Path); + } + + [Test] + public void UnresolvedField_WhenResolvedChildFieldIsAddedToUnresolvedChildField_PathIsCorrect() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapQuery("/path1/path2"); + var childField = field.MapField("/path3/path4"); + var resolvedField = childField.MapField("/path5/path6", (string a) => 1); + + var path = resolvedField.CreatePath(); + Assert.AreEqual("[query]/path1/path2/path3/path4/path5/path6", path.Path); + Assert.IsNotNull(resolvedField.Resolver); + } + + [Test] + public void UnresolvedField_WhenResolvedChildFieldIsAdded_AndParentPathIsChanged_PathIsCorrect() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapQuery("/path1/path2"); + + var childField = field.MapField("/path3/path4", (string a) => 1); + + var path = childField.CreatePath(); + Assert.AreEqual("[query]/path1/path2/path3/path4", path.Path); + } + } +} \ No newline at end of file From 39a3ef6190fde78b54e972896df1c725807b04a6 Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Sun, 18 Jun 2023 16:32:54 -0700 Subject: [PATCH 07/63] WIP, working through templating --- .../GraphQLMinimalApiExtensions_Directives.cs | 24 +++++++------- .../GraphQLMinimalApiExtensions_Internals.cs | 6 ++-- .../GraphQLMinimalApiExtensions_Mutations.cs | 4 +-- .../GraphQLMinimalApiExtensions_Queries.cs | 4 +-- ...phQLMinimalApiExtensions_ResolvedFields.cs | 12 +++---- ...phQLMinimalApiExtensions_TypeExtensions.cs | 22 ++++++------- ...aphQLMinimalApiExtensions_VirtualFields.cs | 6 ++-- .../Templates/GraphQLDirectiveTemplate.cs | 4 +-- .../Templates/GraphQLResolvedFieldTemplate.cs | 6 ++-- .../GraphQLTypeExtensionFieldTemplate.cs | 2 +- ...cs => IGraphQLRuntimeDirectiveTemplate.cs} | 2 +- ...> IGraphQLRuntimeResolvedFieldTemplate.cs} | 2 +- ...> IGraphQLRuntimeTypeExtensionTemplate.cs} | 2 +- .../RuntimeSchemaItemTemplate.cs | 31 +++++++++++++++++++ .../RuntimeSchemaItemTypeMarker.cs | 20 ++++++++++++ .../Templates/MappedDirectiveTemplateTests.cs | 8 ++--- .../Templates/MappedMutationTemplateTests.cs | 4 +-- .../Templates/MappedQueryTemplateTests.cs | 4 +-- .../MappedTypeExtensionTemplateTests.cs | 10 +++--- .../Templates/UnresolvedFieldTemplateTests.cs | 8 ++--- 20 files changed, 115 insertions(+), 66 deletions(-) rename src/graphql-aspnet/Interfaces/Configuration/Templates/{IGraphQLDirectiveTemplate.cs => IGraphQLRuntimeDirectiveTemplate.cs} (82%) rename src/graphql-aspnet/Interfaces/Configuration/Templates/{IGraphQLResolvedFieldTemplate.cs => IGraphQLRuntimeResolvedFieldTemplate.cs} (87%) rename src/graphql-aspnet/Interfaces/Configuration/Templates/{IGraphQLTypeExtensionTemplate.cs => IGraphQLRuntimeTypeExtensionTemplate.cs} (90%) create mode 100644 src/graphql-aspnet/Internal/TypeTemplates/RuntimeSchemaItemTemplate.cs create mode 100644 src/graphql-aspnet/Internal/TypeTemplates/RuntimeSchemaItemTypeMarker.cs diff --git a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Directives.cs b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Directives.cs index 8b54980e4..0eeae9b48 100644 --- a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Directives.cs +++ b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Directives.cs @@ -33,8 +33,8 @@ public static partial class GraphQLMinimalApiExtensions /// The name of the policy to assign via this requirement. /// A comma-seperated list of roles to assign via this requirement. /// IGraphQLFieldBuilder. - public static IGraphQLDirectiveTemplate RequireAuthorization( - this IGraphQLDirectiveTemplate directiveTemplate, + public static IGraphQLRuntimeDirectiveTemplate RequireAuthorization( + this IGraphQLRuntimeDirectiveTemplate directiveTemplate, string policyName = null, string roles = null) { @@ -61,7 +61,7 @@ public static IGraphQLDirectiveTemplate RequireAuthorization( /// /// The directive being built. /// IGraphQLFieldBuilder. - public static IGraphQLDirectiveTemplate AllowAnonymous(this IGraphQLDirectiveTemplate directiveTemplate) + public static IGraphQLRuntimeDirectiveTemplate AllowAnonymous(this IGraphQLRuntimeDirectiveTemplate directiveTemplate) { Validation.ThrowIfNull(directiveTemplate, nameof(directiveTemplate)); directiveTemplate.Attributes.Add(new AllowAnonymousAttribute()); @@ -74,7 +74,7 @@ public static IGraphQLDirectiveTemplate AllowAnonymous(this IGraphQLDirectiveTem /// /// The directive template. /// IGraphQLDirectiveTemplate. - public static IGraphQLDirectiveTemplate IsRepeatable(this IGraphQLDirectiveTemplate directiveTemplate) + public static IGraphQLRuntimeDirectiveTemplate IsRepeatable(this IGraphQLRuntimeDirectiveTemplate directiveTemplate) { var repeatable = new RepeatableAttribute(); directiveTemplate.Attributes.Add(repeatable); @@ -92,8 +92,8 @@ public static IGraphQLDirectiveTemplate IsRepeatable(this IGraphQLDirectiveTempl /// The bitwise set of locations where this /// directive can be applied. /// IGraphQLDirectiveTemplate. - public static IGraphQLDirectiveTemplate RestrictLocations( - this IGraphQLDirectiveTemplate directiveTemplate, + public static IGraphQLRuntimeDirectiveTemplate RestrictLocations( + this IGraphQLRuntimeDirectiveTemplate directiveTemplate, DirectiveLocation locations) { var restrictions = new DirectiveLocationsAttribute(locations); @@ -117,7 +117,7 @@ public static IGraphQLDirectiveTemplate RestrictLocations( /// The delegate to assign as the resolver. This method will be /// parsed to determine input arguments for the field on the target schema. /// IGraphQLFieldBuilder. - public static IGraphQLDirectiveTemplate AddResolver(this IGraphQLDirectiveTemplate directiveTemplate, Delegate resolverMethod) + public static IGraphQLRuntimeDirectiveTemplate AddResolver(this IGraphQLRuntimeDirectiveTemplate directiveTemplate, Delegate resolverMethod) { directiveTemplate.Resolver = resolverMethod; directiveTemplate.ReturnType = null; @@ -137,7 +137,7 @@ public static IGraphQLDirectiveTemplate AddResolver(this IGraphQLDirectiveTempla /// The delegate to assign as the resolver. This method will be /// parsed to determine input arguments for the directive on the target schema. /// IGraphQLFieldBuilder. - public static IGraphQLDirectiveTemplate AddResolver(this IGraphQLDirectiveTemplate directiveTemplate, Delegate resolverMethod) + public static IGraphQLRuntimeDirectiveTemplate AddResolver(this IGraphQLRuntimeDirectiveTemplate directiveTemplate, Delegate resolverMethod) { directiveTemplate.Resolver = resolverMethod; directiveTemplate.ReturnType = typeof(TReturnType); @@ -150,7 +150,7 @@ public static IGraphQLDirectiveTemplate AddResolver(this IGraphQLDi /// The schema options where the directive will be created. /// Name of the directive (e.g. '@myDirective'). /// IGraphQLDirectiveTemplate. - public static IGraphQLDirectiveTemplate MapDirective(this SchemaOptions schemaOptions, string directiveName) + public static IGraphQLRuntimeDirectiveTemplate MapDirective(this SchemaOptions schemaOptions, string directiveName) { return MapDirectiveInternal(schemaOptions, directiveName); } @@ -162,7 +162,7 @@ public static IGraphQLDirectiveTemplate MapDirective(this SchemaOptions schemaOp /// Name of the directive (e.g. '@myDirective'). /// The resolver that will be executed when the directive is invoked. /// IGraphQLDirectiveTemplate. - public static IGraphQLDirectiveTemplate MapDirective(this SchemaOptions schemaOptions, string directiveName, Delegate resolverMethod) + public static IGraphQLRuntimeDirectiveTemplate MapDirective(this SchemaOptions schemaOptions, string directiveName, Delegate resolverMethod) { Validation.ThrowIfNull(resolverMethod, nameof(resolverMethod)); @@ -176,7 +176,7 @@ public static IGraphQLDirectiveTemplate MapDirective(this SchemaOptions schemaOp /// The builder representing the schema being constructed. /// Name of the directive (e.g. '@myDirective'). /// IGraphQLDirectiveTemplate. - public static IGraphQLDirectiveTemplate MapDirective(this ISchemaBuilder schemaBuilder, string directiveName) + public static IGraphQLRuntimeDirectiveTemplate MapDirective(this ISchemaBuilder schemaBuilder, string directiveName) { Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); @@ -194,7 +194,7 @@ public static IGraphQLDirectiveTemplate MapDirective(this ISchemaBuilder schemaB /// Name of the directive (e.g. '@myDirective'). /// The resolver that will be executed when the directive is invoked. /// IGraphQLDirectiveTemplate. - public static IGraphQLDirectiveTemplate MapDirective(this ISchemaBuilder schemaBuilder, string directiveName, Delegate resolverMethod) + public static IGraphQLRuntimeDirectiveTemplate MapDirective(this ISchemaBuilder schemaBuilder, string directiveName, Delegate resolverMethod) { Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); Validation.ThrowIfNull(resolverMethod, nameof(resolverMethod)); diff --git a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Internals.cs b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Internals.cs index ff8334309..fe28f23b2 100644 --- a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Internals.cs +++ b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Internals.cs @@ -39,7 +39,7 @@ private static IGraphQLFieldTemplate MapGraphQLFieldInternal( return fieldTemplate; } - private static IGraphQLTypeExtensionTemplate MapTypeExtensionInternal( + private static IGraphQLRuntimeTypeExtensionTemplate MapTypeExtensionInternal( SchemaOptions schemaOptions, Type typeToExtend, string fieldName, @@ -48,7 +48,7 @@ private static IGraphQLTypeExtensionTemplate MapTypeExtensionInternal( schemaOptions = Validation.ThrowIfNullOrReturn(schemaOptions, nameof(schemaOptions)); fieldName = Validation.ThrowIfNullWhiteSpaceOrReturn(fieldName, nameof(fieldName)); - IGraphQLTypeExtensionTemplate field = new GraphQLTypeExtensionFieldTemplate( + IGraphQLRuntimeTypeExtensionTemplate field = new GraphQLTypeExtensionFieldTemplate( schemaOptions, typeToExtend, fieldName, @@ -58,7 +58,7 @@ private static IGraphQLTypeExtensionTemplate MapTypeExtensionInternal( return field; } - private static IGraphQLDirectiveTemplate MapDirectiveInternal(this SchemaOptions schemaOptions, string directiveName) + private static IGraphQLRuntimeDirectiveTemplate MapDirectiveInternal(this SchemaOptions schemaOptions, string directiveName) { var directive = new GraphQLDirectiveTemplate(schemaOptions, directiveName); diff --git a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Mutations.cs b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Mutations.cs index ddc6ead4e..fa748a9f4 100644 --- a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Mutations.cs +++ b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Mutations.cs @@ -48,7 +48,7 @@ public static IGraphQLFieldTemplate MapMutation(this SchemaOptions schemaOptions /// The resolver method to execute when /// this field is requested by a caller. /// IGraphQLResolvedFieldTemplate. - public static IGraphQLResolvedFieldTemplate MapMutation(this SchemaOptions schemaOptions, string template, Delegate resolverMethod) + public static IGraphQLRuntimeResolvedFieldTemplate MapMutation(this SchemaOptions schemaOptions, string template, Delegate resolverMethod) { Validation.ThrowIfNull(resolverMethod, nameof(resolverMethod)); @@ -89,7 +89,7 @@ public static IGraphQLFieldTemplate MapMutation(this ISchemaBuilder schemaBuilde /// The template path string for his field. (e.g. /path1/path2/path3) /// The resolver method to execute when this field is requested. /// IGraphQLFieldTemplate. - public static IGraphQLResolvedFieldTemplate MapMutation(this ISchemaBuilder schemaBuilder, string template, Delegate resolverMethod) + public static IGraphQLRuntimeResolvedFieldTemplate MapMutation(this ISchemaBuilder schemaBuilder, string template, Delegate resolverMethod) { Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); Validation.ThrowIfNull(resolverMethod, nameof(resolverMethod)); diff --git a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Queries.cs b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Queries.cs index 9936f8ae6..41b2a11be 100644 --- a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Queries.cs +++ b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Queries.cs @@ -48,7 +48,7 @@ public static IGraphQLFieldTemplate MapQuery(this SchemaOptions schemaOptions, s /// The resolver method to execute when /// this field is requested by a caller. /// IGraphQLResolvedFieldTemplate. - public static IGraphQLResolvedFieldTemplate MapQuery(this SchemaOptions schemaOptions, string template, Delegate resolverMethod) + public static IGraphQLRuntimeResolvedFieldTemplate MapQuery(this SchemaOptions schemaOptions, string template, Delegate resolverMethod) { Validation.ThrowIfNull(resolverMethod, nameof(resolverMethod)); @@ -90,7 +90,7 @@ public static IGraphQLFieldTemplate MapQuery(this ISchemaBuilder schemaBuilder, /// The resolver method to execute when this /// field is requested. /// IGraphQLFieldTemplate. - public static IGraphQLResolvedFieldTemplate MapQuery(this ISchemaBuilder schemaBuilder, string template, Delegate resolverMethod) + public static IGraphQLRuntimeResolvedFieldTemplate MapQuery(this ISchemaBuilder schemaBuilder, string template, Delegate resolverMethod) { Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); Validation.ThrowIfNull(resolverMethod, nameof(resolverMethod)); diff --git a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_ResolvedFields.cs b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_ResolvedFields.cs index f195c6c01..6fc0a55bc 100644 --- a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_ResolvedFields.cs +++ b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_ResolvedFields.cs @@ -31,8 +31,8 @@ public static partial class GraphQLMinimalApiExtensions /// The name of the policy to assign via this requirement. /// A comma-seperated list of roles to assign via this requirement. /// IGraphQLFieldBuilder. - public static IGraphQLResolvedFieldTemplate RequireAuthorization( - this IGraphQLResolvedFieldTemplate fieldBuilder, + public static IGraphQLRuntimeResolvedFieldTemplate RequireAuthorization( + this IGraphQLRuntimeResolvedFieldTemplate fieldBuilder, string policyName = null, string roles = null) { @@ -53,7 +53,7 @@ public static IGraphQLResolvedFieldTemplate RequireAuthorization( /// /// The field being built. /// IGraphQLFieldBuilder. - public static IGraphQLResolvedFieldTemplate AllowAnonymous(this IGraphQLResolvedFieldTemplate fieldBuilder) + public static IGraphQLRuntimeResolvedFieldTemplate AllowAnonymous(this IGraphQLRuntimeResolvedFieldTemplate fieldBuilder) { Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); fieldBuilder.Attributes.Add(new AllowAnonymousAttribute()); @@ -70,7 +70,7 @@ public static IGraphQLResolvedFieldTemplate AllowAnonymous(this IGraphQLResolved /// The delegate to assign as the resolver. This method will be /// parsed to determine input arguments for the field on the target schema. /// IGraphQLFieldBuilder. - public static IGraphQLResolvedFieldTemplate AddResolver(this IGraphQLResolvedFieldTemplate fieldBuilder, Delegate resolverMethod) + public static IGraphQLRuntimeResolvedFieldTemplate AddResolver(this IGraphQLRuntimeResolvedFieldTemplate fieldBuilder, Delegate resolverMethod) { fieldBuilder.Resolver = resolverMethod; fieldBuilder.ReturnType = null; @@ -90,7 +90,7 @@ public static IGraphQLResolvedFieldTemplate AddResolver(this IGraphQLResolvedFie /// The delegate to assign as the resolver. This method will be /// parsed to determine input arguments for the field on the target schema. /// IGraphQLFieldBuilder. - public static IGraphQLResolvedFieldTemplate AddResolver(this IGraphQLResolvedFieldTemplate fieldBuilder, Delegate resolverMethod) + public static IGraphQLRuntimeResolvedFieldTemplate AddResolver(this IGraphQLRuntimeResolvedFieldTemplate fieldBuilder, Delegate resolverMethod) { fieldBuilder.Resolver = resolverMethod; fieldBuilder.ReturnType = typeof(TReturnType); @@ -110,7 +110,7 @@ public static IGraphQLResolvedFieldTemplate AddResolver(this IGraph /// Any number of additional possible types that /// might be returned by this field. /// IGraphQLFieldBuilder. - public static IGraphQLResolvedFieldTemplate AddPossibleTypes(this IGraphQLResolvedFieldTemplate fieldBuilder, Type firstPossibleType, params Type[] additionalPossibleTypes) + public static IGraphQLRuntimeResolvedFieldTemplate AddPossibleTypes(this IGraphQLRuntimeResolvedFieldTemplate fieldBuilder, Type firstPossibleType, params Type[] additionalPossibleTypes) { var possibleTypes = new PossibleTypesAttribute(firstPossibleType, additionalPossibleTypes); fieldBuilder.Attributes.Add(possibleTypes); diff --git a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_TypeExtensions.cs b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_TypeExtensions.cs index 18b019097..3006fc5c9 100644 --- a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_TypeExtensions.cs +++ b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_TypeExtensions.cs @@ -33,8 +33,8 @@ public static partial class GraphQLMinimalApiExtensions /// The name of the policy to assign via this requirement. /// A comma-seperated list of roles to assign via this requirement. /// IGraphQLFieldBuilder. - public static IGraphQLTypeExtensionTemplate RequireAuthorization( - this IGraphQLTypeExtensionTemplate fieldBuilder, + public static IGraphQLRuntimeTypeExtensionTemplate RequireAuthorization( + this IGraphQLRuntimeTypeExtensionTemplate fieldBuilder, string policyName = null, string roles = null) { @@ -55,7 +55,7 @@ public static IGraphQLTypeExtensionTemplate RequireAuthorization( /// /// The field being built. /// IGraphQLFieldBuilder. - public static IGraphQLTypeExtensionTemplate AllowAnonymous(this IGraphQLTypeExtensionTemplate fieldBuilder) + public static IGraphQLRuntimeTypeExtensionTemplate AllowAnonymous(this IGraphQLRuntimeTypeExtensionTemplate fieldBuilder) { Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); fieldBuilder.Attributes.Add(new AllowAnonymousAttribute()); @@ -72,7 +72,7 @@ public static IGraphQLTypeExtensionTemplate AllowAnonymous(this IGraphQLTypeExte /// The delegate to assign as the resolver. This method will be /// parsed to determine input arguments for the field on the target schema. /// IGraphQLFieldBuilder. - public static IGraphQLTypeExtensionTemplate AddResolver(this IGraphQLTypeExtensionTemplate fieldBuilder, Delegate resolverMethod) + public static IGraphQLRuntimeTypeExtensionTemplate AddResolver(this IGraphQLRuntimeTypeExtensionTemplate fieldBuilder, Delegate resolverMethod) { fieldBuilder.Resolver = resolverMethod; fieldBuilder.ReturnType = null; @@ -92,7 +92,7 @@ public static IGraphQLTypeExtensionTemplate AddResolver(this IGraphQLTypeExtensi /// The delegate to assign as the resolver. This method will be /// parsed to determine input arguments for the field on the target schema. /// IGraphQLFieldBuilder. - public static IGraphQLTypeExtensionTemplate AddResolver(this IGraphQLTypeExtensionTemplate fieldBuilder, Delegate resolverMethod) + public static IGraphQLRuntimeTypeExtensionTemplate AddResolver(this IGraphQLRuntimeTypeExtensionTemplate fieldBuilder, Delegate resolverMethod) { fieldBuilder.Resolver = resolverMethod; fieldBuilder.ReturnType = typeof(TReturnType); @@ -116,7 +116,7 @@ public static IGraphQLTypeExtensionTemplate AddResolver(this IGraph /// Name of the field to add to the . /// The resolver method to be called when the field is requested. /// IGraphQLResolvedFieldTemplate. - public static IGraphQLTypeExtensionTemplate MapField(this SchemaOptions schemaOptions, string fieldName, Delegate resolverMethod = null) + public static IGraphQLRuntimeTypeExtensionTemplate MapField(this SchemaOptions schemaOptions, string fieldName, Delegate resolverMethod = null) { return schemaOptions.MapField( typeof(TOwnerType), @@ -125,7 +125,7 @@ public static IGraphQLTypeExtensionTemplate MapField(this SchemaOpti } /// - /// Registers a new type extension to a given type for the target schema. + /// Registers a new field to a given type on the target schema. /// /// /// @@ -137,7 +137,7 @@ public static IGraphQLTypeExtensionTemplate MapField(this SchemaOpti /// Name of the field to add to the . /// The resolver method to be called when the field is requested. /// IGraphQLResolvedFieldTemplate. - public static IGraphQLTypeExtensionTemplate MapField(this SchemaOptions schemaOptions, Type fieldOwnerType, string fieldName, Delegate resolverMethod = null) + public static IGraphQLRuntimeTypeExtensionTemplate MapField(this SchemaOptions schemaOptions, Type fieldOwnerType, string fieldName, Delegate resolverMethod = null) { var field = MapTypeExtensionInternal( schemaOptions, @@ -158,12 +158,12 @@ public static IGraphQLTypeExtensionTemplate MapField(this SchemaOptions schemaOp /// /// /// The supplied resolver must declare a parameter that is an of the same as - /// class, interface or struct that was originally extended as indicated by . + /// class, interface or struct that was originally extended as indicated by . /// /// /// The type extension to make into a batch field. /// IGraphQLTypeExtensionTemplate. - public static IGraphQLTypeExtensionTemplate WithBatchProcessing(this IGraphQLTypeExtensionTemplate typeExtension) + public static IGraphQLRuntimeTypeExtensionTemplate WithBatchProcessing(this IGraphQLRuntimeTypeExtensionTemplate typeExtension) { typeExtension.ExecutionMode = FieldResolutionMode.Batch; return typeExtension; @@ -182,7 +182,7 @@ public static IGraphQLTypeExtensionTemplate WithBatchProcessing(this IGraphQLTyp /// Any number of additional possible types that /// might be returned by this field. /// IGraphQLFieldBuilder. - public static IGraphQLTypeExtensionTemplate AddPossibleTypes(this IGraphQLTypeExtensionTemplate fieldBuilder, Type firstPossibleType, params Type[] additionalPossibleTypes) + public static IGraphQLRuntimeTypeExtensionTemplate AddPossibleTypes(this IGraphQLRuntimeTypeExtensionTemplate fieldBuilder, Type firstPossibleType, params Type[] additionalPossibleTypes) { var possibleTypes = new PossibleTypesAttribute(firstPossibleType, additionalPossibleTypes); fieldBuilder.Attributes.Add(possibleTypes); diff --git a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_VirtualFields.cs b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_VirtualFields.cs index a2bebd665..76964094a 100644 --- a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_VirtualFields.cs +++ b/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_VirtualFields.cs @@ -76,7 +76,7 @@ public static IGraphQLFieldTemplate AllowAnonymous(this IGraphQLFieldTemplate fi /// The delegate to assign as the resolver. This method will be /// parsed to determine input arguments for the field on the target schema. /// IGraphQLFieldBuilder. - public static IGraphQLResolvedFieldTemplate AddResolver(this IGraphQLFieldTemplate field, Delegate resolverMethod) + public static IGraphQLRuntimeResolvedFieldTemplate AddResolver(this IGraphQLFieldTemplate field, Delegate resolverMethod) { // convert the virtual field to a resolved field var resolvedBuilder = GraphQLResolvedFieldTemplate.FromFieldTemplate(field); @@ -100,7 +100,7 @@ public static IGraphQLResolvedFieldTemplate AddResolver(this IGraphQLFieldTempla /// The delegate to assign as the resolver. This method will be /// parsed to determine input arguments for the field on the target schema. /// IGraphQLFieldBuilder. - public static IGraphQLResolvedFieldTemplate AddResolver(this IGraphQLFieldTemplate field, Delegate resolverMethod) + public static IGraphQLRuntimeResolvedFieldTemplate AddResolver(this IGraphQLFieldTemplate field, Delegate resolverMethod) { // convert the virtual field to a resolved field var resolvedBuilder = GraphQLResolvedFieldTemplate.FromFieldTemplate(field); @@ -118,7 +118,7 @@ public static IGraphQLResolvedFieldTemplate AddResolver(this IGraph /// The template pattern to be appended to the supplied . /// The resolver method to be called when this field is requested. /// IGraphQLResolvedFieldBuilder. - public static IGraphQLResolvedFieldTemplate MapField(this IGraphQLFieldTemplate field, string subTemplate, Delegate resolverMethod) + public static IGraphQLRuntimeResolvedFieldTemplate MapField(this IGraphQLFieldTemplate field, string subTemplate, Delegate resolverMethod) { var subField = new GraphQLResolvedFieldTemplate(field, subTemplate); subField.AddResolver(resolverMethod); diff --git a/src/graphql-aspnet/Configuration/Templates/GraphQLDirectiveTemplate.cs b/src/graphql-aspnet/Configuration/Templates/GraphQLDirectiveTemplate.cs index c776e859c..ff10ec2c2 100644 --- a/src/graphql-aspnet/Configuration/Templates/GraphQLDirectiveTemplate.cs +++ b/src/graphql-aspnet/Configuration/Templates/GraphQLDirectiveTemplate.cs @@ -15,11 +15,11 @@ namespace GraphQL.AspNet.Configuration.Templates using GraphQL.AspNet.Interfaces.Configuration.Templates; /// - /// An internal implementation of the + /// An internal implementation of the /// used to generate new graphql directives via a minimal api style of coding. /// [DebuggerDisplay("{Template}")] - internal class GraphQLDirectiveTemplate : BaseGraphQLRuntimeSchemaItemTemplate, IGraphQLDirectiveTemplate + internal class GraphQLDirectiveTemplate : BaseGraphQLRuntimeSchemaItemTemplate, IGraphQLRuntimeDirectiveTemplate { /// /// Initializes a new instance of the class. diff --git a/src/graphql-aspnet/Configuration/Templates/GraphQLResolvedFieldTemplate.cs b/src/graphql-aspnet/Configuration/Templates/GraphQLResolvedFieldTemplate.cs index b2a6fcd1c..00340fba4 100644 --- a/src/graphql-aspnet/Configuration/Templates/GraphQLResolvedFieldTemplate.cs +++ b/src/graphql-aspnet/Configuration/Templates/GraphQLResolvedFieldTemplate.cs @@ -16,11 +16,11 @@ namespace GraphQL.AspNet.Configuration.Templates using GraphQL.AspNet.Interfaces.Configuration.Templates; /// - /// An internal implementation of the + /// An internal implementation of the /// used to generate new graphql fields via a minimal api style of coding. /// [DebuggerDisplay("{Template}")] - internal class GraphQLResolvedFieldTemplate : BaseGraphQLRuntimeSchemaItemTemplate, IGraphQLResolvedFieldTemplate + internal class GraphQLResolvedFieldTemplate : BaseGraphQLRuntimeSchemaItemTemplate, IGraphQLRuntimeResolvedFieldTemplate { /// /// Converts the unresolved field into a resolved field. The newly generated field @@ -28,7 +28,7 @@ internal class GraphQLResolvedFieldTemplate : BaseGraphQLRuntimeSchemaItemTempla /// /// The field template. /// IGraphQLResolvedFieldTemplate. - public static IGraphQLResolvedFieldTemplate FromFieldTemplate(IGraphQLFieldTemplate fieldTemplate) + public static IGraphQLRuntimeResolvedFieldTemplate FromFieldTemplate(IGraphQLFieldTemplate fieldTemplate) { Validation.ThrowIfNull(fieldTemplate, nameof(fieldTemplate)); var field = new GraphQLResolvedFieldTemplate(fieldTemplate.Options, fieldTemplate.Template); diff --git a/src/graphql-aspnet/Configuration/Templates/GraphQLTypeExtensionFieldTemplate.cs b/src/graphql-aspnet/Configuration/Templates/GraphQLTypeExtensionFieldTemplate.cs index d77635f41..5b49f048c 100644 --- a/src/graphql-aspnet/Configuration/Templates/GraphQLTypeExtensionFieldTemplate.cs +++ b/src/graphql-aspnet/Configuration/Templates/GraphQLTypeExtensionFieldTemplate.cs @@ -20,7 +20,7 @@ namespace GraphQL.AspNet.Configuration.Templates /// used to generate new type extensions via a minimal api style of coding. /// [DebuggerDisplay("{Template}")] - internal class GraphQLTypeExtensionFieldTemplate : GraphQLResolvedFieldTemplate, IGraphQLTypeExtensionTemplate + internal class GraphQLTypeExtensionFieldTemplate : GraphQLResolvedFieldTemplate, IGraphQLRuntimeTypeExtensionTemplate { /// /// Initializes a new instance of the class. diff --git a/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLDirectiveTemplate.cs b/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLRuntimeDirectiveTemplate.cs similarity index 82% rename from src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLDirectiveTemplate.cs rename to src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLRuntimeDirectiveTemplate.cs index c3ce8a9dc..5a7b55137 100644 --- a/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLDirectiveTemplate.cs +++ b/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLRuntimeDirectiveTemplate.cs @@ -13,7 +13,7 @@ namespace GraphQL.AspNet.Interfaces.Configuration.Templates /// An intermediate template that utilizies a key/value pair system to build up a set of component parts /// that the templating engine will use to generate a full fledged field in a schema. /// - public interface IGraphQLDirectiveTemplate : IGraphQLRuntimeSchemaItemTemplate, IGraphQLResolvableSchemaItemTemplate + public interface IGraphQLRuntimeDirectiveTemplate : IGraphQLRuntimeSchemaItemTemplate, IGraphQLResolvableSchemaItemTemplate { } } \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLResolvedFieldTemplate.cs b/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLRuntimeResolvedFieldTemplate.cs similarity index 87% rename from src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLResolvedFieldTemplate.cs rename to src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLRuntimeResolvedFieldTemplate.cs index 8a1877e81..4bb18a7f2 100644 --- a/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLResolvedFieldTemplate.cs +++ b/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLRuntimeResolvedFieldTemplate.cs @@ -21,7 +21,7 @@ namespace GraphQL.AspNet.Interfaces.Configuration.Templates /// in that it has an explicit resolver applied. The runtime will not attempt to /// autoresolve this field. /// - public interface IGraphQLResolvedFieldTemplate : IGraphQLRuntimeSchemaItemTemplate, IGraphQLResolvableSchemaItemTemplate + public interface IGraphQLRuntimeResolvedFieldTemplate : IGraphQLRuntimeSchemaItemTemplate, IGraphQLResolvableSchemaItemTemplate { } } \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLTypeExtensionTemplate.cs b/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLRuntimeTypeExtensionTemplate.cs similarity index 90% rename from src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLTypeExtensionTemplate.cs rename to src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLRuntimeTypeExtensionTemplate.cs index c5eb34267..224b7c455 100644 --- a/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLTypeExtensionTemplate.cs +++ b/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLRuntimeTypeExtensionTemplate.cs @@ -16,7 +16,7 @@ namespace GraphQL.AspNet.Interfaces.Configuration.Templates /// An intermediate template that utilizies a key/value pair system to build up a set of component parts /// that the templating engine will use to generate a full fledged type extension in a schema. /// - public interface IGraphQLTypeExtensionTemplate : IGraphQLRuntimeSchemaItemTemplate, IGraphQLResolvableSchemaItemTemplate + public interface IGraphQLRuntimeTypeExtensionTemplate : IGraphQLRuntimeSchemaItemTemplate, IGraphQLResolvableSchemaItemTemplate { /// /// Gets the concrcete type of the OBJECT or INTERFACE that will be extended. diff --git a/src/graphql-aspnet/Internal/TypeTemplates/RuntimeSchemaItemTemplate.cs b/src/graphql-aspnet/Internal/TypeTemplates/RuntimeSchemaItemTemplate.cs new file mode 100644 index 000000000..6afdd5ad2 --- /dev/null +++ b/src/graphql-aspnet/Internal/TypeTemplates/RuntimeSchemaItemTemplate.cs @@ -0,0 +1,31 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Internal.TypeTemplates +{ + using System; + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Directives; + using GraphQL.AspNet.Interfaces.Configuration.Templates; + + /// + /// A template of a directive generated at runtime rather than via a class that + /// inherits from a . + /// + internal class RuntimeSchemaItemTemplate : GraphDirectiveTemplate + { + private IGraphQLRuntimeSchemaItemTemplate _runtimeTemplate; + + public RuntimeSchemaItemTemplate(IGraphQLRuntimeSchemaItemTemplate template) + : base(typeof(RuntimeSchemaItemTypeMarker)) + { + _runtimeTemplate = Validation.ThrowIfNullOrReturn(template, nameof(template)); + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Internal/TypeTemplates/RuntimeSchemaItemTypeMarker.cs b/src/graphql-aspnet/Internal/TypeTemplates/RuntimeSchemaItemTypeMarker.cs new file mode 100644 index 000000000..4ac7fb7f0 --- /dev/null +++ b/src/graphql-aspnet/Internal/TypeTemplates/RuntimeSchemaItemTypeMarker.cs @@ -0,0 +1,20 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Internal.TypeTemplates +{ + /// + /// A marker type used internally by the templating system to mark + /// a dynamically built schema item that doesn't necessarily have a concrete + /// matching type. This class cannot be inherited. + /// + internal sealed class RuntimeSchemaItemTypeMarker + { + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedDirectiveTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedDirectiveTemplateTests.cs index 0a3d0b21b..b0f7ff53a 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedDirectiveTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedDirectiveTemplateTests.cs @@ -31,7 +31,7 @@ public void MapDirective_ByOptions_AddsDirectiveToOptions() var options = new SchemaOptions(services); var directive = options.MapDirective("@myDirective"); - Assert.IsInstanceOf(typeof(IGraphQLDirectiveTemplate), directive); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeDirectiveTemplate), directive); Assert.AreEqual(1, options.RuntimeTemplates.Count()); Assert.IsNotNull(options.RuntimeTemplates.FirstOrDefault(x => x == directive)); @@ -50,7 +50,7 @@ public void MapDirective_ByBuilder_AddsDirectiveToOptions() builderMock.Setup(x => x.Options).Returns(options); var directive = builderMock.Object.MapDirective("@myDirective"); - Assert.IsInstanceOf(typeof(IGraphQLDirectiveTemplate), directive); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeDirectiveTemplate), directive); Assert.AreEqual(1, options.RuntimeTemplates.Count()); Assert.IsNotNull(options.RuntimeTemplates.FirstOrDefault(x => x == directive)); @@ -63,7 +63,7 @@ public void MapDirective_ByOptions_WithResolver_AddsDirectiveToOptions() var options = new SchemaOptions(services); var directive = options.MapDirective("@myDirective", (string a) => 1); - Assert.IsInstanceOf(typeof(IGraphQLDirectiveTemplate), directive); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeDirectiveTemplate), directive); Assert.AreEqual(1, options.RuntimeTemplates.Count()); Assert.IsNotNull(options.RuntimeTemplates.FirstOrDefault(x => x == directive)); @@ -82,7 +82,7 @@ public void MapDirective_ByBuilder_WithResolver_AddsDirectiveToOptions() builderMock.Setup(x => x.Options).Returns(options); var directive = builderMock.Object.MapDirective("@myDirective", (string a) => 1); - Assert.IsInstanceOf(typeof(IGraphQLDirectiveTemplate), directive); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeDirectiveTemplate), directive); Assert.AreEqual(1, options.RuntimeTemplates.Count()); Assert.IsNotNull(options.RuntimeTemplates.FirstOrDefault(x => x == directive)); diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedMutationTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedMutationTemplateTests.cs index 6257c876c..bc03fa3aa 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedMutationTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedMutationTemplateTests.cs @@ -51,7 +51,7 @@ public void MapMutation_FromSchemaOptions_WithDelegate_DoesAddFieldToSchema() Assert.IsNotNull(field); Assert.AreEqual(SchemaItemCollections.Mutation, field.CreatePath().RootCollection); - Assert.IsInstanceOf(typeof(IGraphQLResolvedFieldTemplate), field); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeResolvedFieldTemplate), field); Assert.AreEqual(1, options.RuntimeTemplates.Count()); } @@ -85,7 +85,7 @@ public void MapMutation_FromBuilder_WithDelegate_DoesAddFieldToSchema() Assert.IsNotNull(field); Assert.AreEqual(SchemaItemCollections.Mutation, field.CreatePath().RootCollection); - Assert.IsInstanceOf(typeof(IGraphQLResolvedFieldTemplate), field); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeResolvedFieldTemplate), field); Assert.AreEqual(1, options.RuntimeTemplates.Count()); } } diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedQueryTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedQueryTemplateTests.cs index 15854956f..8be379ff4 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedQueryTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedQueryTemplateTests.cs @@ -52,7 +52,7 @@ public void MapQuery_FromSchemaOptions_WithDelegate_DoesAddFieldToSchema() Assert.IsNotNull(field); Assert.AreEqual(SchemaItemCollections.Query, field.CreatePath().RootCollection); - Assert.IsInstanceOf(typeof(IGraphQLResolvedFieldTemplate), field); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeResolvedFieldTemplate), field); Assert.AreEqual(1, options.RuntimeTemplates.Count()); } @@ -87,7 +87,7 @@ public void MapQuery_FromBuilder_WithDelegate_DoesAddFieldToSchema() Assert.IsNotNull(field); Assert.AreEqual(SchemaItemCollections.Query, field.CreatePath().RootCollection); - Assert.IsInstanceOf(typeof(IGraphQLResolvedFieldTemplate), field); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeResolvedFieldTemplate), field); Assert.AreEqual(1, options.RuntimeTemplates.Count()); } } diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedTypeExtensionTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedTypeExtensionTemplateTests.cs index 7f35cdc29..de4a7fea5 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedTypeExtensionTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedTypeExtensionTemplateTests.cs @@ -25,8 +25,6 @@ namespace GraphQL.AspNet.Tests.Configuration.Templates [TestFixture] public class MappedTypeExtensionTemplateTests { - public IGraphQLRuntimeSchemaItemTemplate TypeExtension { get; private set; } - [Test] public void MapTypeExtension_ByOptions_AddsTypeExtensionToOptions() { @@ -34,7 +32,7 @@ public void MapTypeExtension_ByOptions_AddsTypeExtensionToOptions() var options = new SchemaOptions(services); var typeExt = options.MapField("myField"); - Assert.IsInstanceOf(typeof(IGraphQLTypeExtensionTemplate), typeExt); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeTypeExtensionTemplate), typeExt); Assert.AreEqual(1, options.RuntimeTemplates.Count()); Assert.IsNotNull(options.RuntimeTemplates.FirstOrDefault(x => x == typeExt)); @@ -54,7 +52,7 @@ public void MapTypeExtension_ByBuilder_AddsTypeExtensionToOptions() builderMock.Setup(x => x.Options).Returns(options); var typeExt = options.MapField("myField"); - Assert.IsInstanceOf(typeof(IGraphQLTypeExtensionTemplate), typeExt); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeTypeExtensionTemplate), typeExt); Assert.AreEqual(1, options.RuntimeTemplates.Count()); Assert.IsNotNull(options.RuntimeTemplates.FirstOrDefault(x => x == typeExt)); @@ -68,7 +66,7 @@ public void MapTypeExtension_ByOptions_WithResolver_AddsTypeExtensionToOptions() var options = new SchemaOptions(services); var typeExt = options.MapField("myField", (string a) => 1); - Assert.IsInstanceOf(typeof(IGraphQLTypeExtensionTemplate), typeExt); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeTypeExtensionTemplate), typeExt); Assert.AreEqual(1, options.RuntimeTemplates.Count()); Assert.IsNotNull(options.RuntimeTemplates.FirstOrDefault(x => x == typeExt)); @@ -87,7 +85,7 @@ public void MapTypeExtension_ByBuilder_WithResolver_AddsTypeExtensionToOptions() builderMock.Setup(x => x.Options).Returns(options); var typeExt = options.MapField("myField", (string a) => 1); - Assert.IsInstanceOf(typeof(IGraphQLTypeExtensionTemplate), typeExt); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeTypeExtensionTemplate), typeExt); Assert.AreEqual(1, options.RuntimeTemplates.Count()); Assert.IsNotNull(options.RuntimeTemplates.FirstOrDefault(x => x == typeExt)); diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/UnresolvedFieldTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/UnresolvedFieldTemplateTests.cs index 503747526..eca710b4e 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/UnresolvedFieldTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/UnresolvedFieldTemplateTests.cs @@ -60,10 +60,10 @@ public void UnresolvedField_WhenResolverAdded_BecomesResolvedField() var field = options.MapQuery("/path1/path2"); Assert.IsInstanceOf(typeof(IGraphQLFieldTemplate), field); - Assert.IsNotInstanceOf(typeof(IGraphQLResolvedFieldTemplate), field); + Assert.IsNotInstanceOf(typeof(IGraphQLRuntimeResolvedFieldTemplate), field); var field1 = field.AddResolver((string a) => 1); - Assert.IsInstanceOf(typeof(IGraphQLResolvedFieldTemplate), field1); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeResolvedFieldTemplate), field1); Assert.IsNull(field1.ReturnType); } @@ -76,10 +76,10 @@ public void UnresolvedField_WhenResolverAddedWithSpecificType_BecomesResolvedFie var field = options.MapQuery("/path1/path2"); Assert.IsInstanceOf(typeof(IGraphQLFieldTemplate), field); - Assert.IsNotInstanceOf(typeof(IGraphQLResolvedFieldTemplate), field); + Assert.IsNotInstanceOf(typeof(IGraphQLRuntimeResolvedFieldTemplate), field); var field1 = field.AddResolver((string a) => 1); - Assert.IsInstanceOf(typeof(IGraphQLResolvedFieldTemplate), field1); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeResolvedFieldTemplate), field1); Assert.AreEqual(typeof(decimal), field1.ReturnType); } From fe68e46267f043eb4ea1fdaadd253c2a61fb25af Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Mon, 19 Jun 2023 07:28:01 -0700 Subject: [PATCH 08/63] WIP, renamed runtime templates to runtime definitions --- ...emaItemDefinitionExtensions_Directives.cs} | 26 +++++++++---------- ...hemaItemDefinitionExtensions_Internals.cs} | 14 +++++----- ...hemaItemDefinitionExtensions_Mutations.cs} | 10 +++---- ...SchemaItemDefinitionExtensions_Queries.cs} | 10 +++---- ...temDefinitionExtensions_ResolvedFields.cs} | 14 +++++----- ...temDefinitionExtensions_TypeExtensions.cs} | 22 ++++++++-------- ...ItemDefinitionExtensions_VirtualFields.cs} | 24 ++++++++--------- .../Configuration/SchemaOptions.cs | 8 +++--- .../Engine/IGraphTypeTemplateProvider.cs | 3 ++- ...IGraphQLResolvableSchemaItemDefinition.cs} | 2 +- .../IGraphQLRuntimeDirectiveDefinition.cs} | 2 +- .../IGraphQLRuntimeFieldDefinition.cs} | 2 +- ...IGraphQLRuntimeResolvedFieldDefinition.cs} | 2 +- .../IGraphQLRuntimeSchemaItemDefinition.cs} | 2 +- ...IGraphQLRuntimeTypeExtensionDefinition.cs} | 2 +- .../RuntimeSchemaItemTemplate.cs | 14 ++++++---- .../Schemas/GraphSchemaManager.cs | 5 ++-- .../BaseRuntimeSchemaItemDefinition.cs} | 18 ++++++------- .../RuntimeControllerDefinition.cs | 15 +++++++++++ .../RuntimeDirectiveDefinition.cs} | 8 +++--- .../RuntimeResolvedFieldDefinition.cs} | 18 ++++++------- .../RuntimeTypeExtensionFieldDefinition.cs} | 10 +++---- .../RuntimeVirtualFieldTemplate.cs} | 12 ++++----- src/graphql-aspnet/graphql-aspnet.csproj | 3 +++ .../Templates/MappedDirectiveTemplateTests.cs | 8 +++--- .../Templates/MappedMutationTemplateTests.cs | 8 +++--- .../Templates/MappedQueryTemplateTests.cs | 8 +++--- .../MappedTypeExtensionTemplateTests.cs | 8 +++--- .../Templates/UnresolvedFieldTemplateTests.cs | 12 ++++----- 29 files changed, 157 insertions(+), 133 deletions(-) rename src/graphql-aspnet/Configuration/{GraphQLMinimalApiExtensions_Directives.cs => GraphQLRuntimeSchemaItemDefinitionExtensions_Directives.cs} (84%) rename src/graphql-aspnet/Configuration/{GraphQLMinimalApiExtensions_Internals.cs => GraphQLRuntimeSchemaItemDefinitionExtensions_Internals.cs} (75%) rename src/graphql-aspnet/Configuration/{GraphQLMinimalApiExtensions_Mutations.cs => GraphQLRuntimeSchemaItemDefinitionExtensions_Mutations.cs} (87%) rename src/graphql-aspnet/Configuration/{GraphQLMinimalApiExtensions_Queries.cs => GraphQLRuntimeSchemaItemDefinitionExtensions_Queries.cs} (87%) rename src/graphql-aspnet/Configuration/{GraphQLMinimalApiExtensions_ResolvedFields.cs => GraphQLRuntimeSchemaItemDefinitionExtensions_ResolvedFields.cs} (84%) rename src/graphql-aspnet/Configuration/{GraphQLMinimalApiExtensions_TypeExtensions.cs => GraphQLRuntimeSchemaItemDefinitionExtensions_TypeExtensions.cs} (84%) rename src/graphql-aspnet/Configuration/{GraphQLMinimalApiExtensions_VirtualFields.cs => GraphQLRuntimeSchemaItemDefinitionExtensions_VirtualFields.cs} (82%) rename src/graphql-aspnet/Interfaces/{Configuration/Templates/IGraphQLResolvableSchemaItemTemplate.cs => Schema/RuntimeDefinitions/IGraphQLResolvableSchemaItemDefinition.cs} (94%) rename src/graphql-aspnet/Interfaces/{Configuration/Templates/IGraphQLRuntimeDirectiveTemplate.cs => Schema/RuntimeDefinitions/IGraphQLRuntimeDirectiveDefinition.cs} (81%) rename src/graphql-aspnet/Interfaces/{Configuration/Templates/IGraphQLFieldTemplate.cs => Schema/RuntimeDefinitions/IGraphQLRuntimeFieldDefinition.cs} (88%) rename src/graphql-aspnet/Interfaces/{Configuration/Templates/IGraphQLRuntimeResolvedFieldTemplate.cs => Schema/RuntimeDefinitions/IGraphQLRuntimeResolvedFieldDefinition.cs} (87%) rename src/graphql-aspnet/Interfaces/{Configuration/Templates/IGraphQLRuntimeSchemaItemTemplate.cs => Schema/RuntimeDefinitions/IGraphQLRuntimeSchemaItemDefinition.cs} (95%) rename src/graphql-aspnet/Interfaces/{Configuration/Templates/IGraphQLRuntimeTypeExtensionTemplate.cs => Schema/RuntimeDefinitions/IGraphQLRuntimeTypeExtensionDefinition.cs} (89%) rename src/graphql-aspnet/{Configuration/Templates/BaseGraphQLRuntimeSchemaItemTemplate.cs => Schemas/RuntimeSchemaItemDefinitions/BaseRuntimeSchemaItemDefinition.cs} (79%) create mode 100644 src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeControllerDefinition.cs rename src/graphql-aspnet/{Configuration/Templates/GraphQLDirectiveTemplate.cs => Schemas/RuntimeSchemaItemDefinitions/RuntimeDirectiveDefinition.cs} (77%) rename src/graphql-aspnet/{Configuration/Templates/GraphQLResolvedFieldTemplate.cs => Schemas/RuntimeSchemaItemDefinitions/RuntimeResolvedFieldDefinition.cs} (76%) rename src/graphql-aspnet/{Configuration/Templates/GraphQLTypeExtensionFieldTemplate.cs => Schemas/RuntimeSchemaItemDefinitions/RuntimeTypeExtensionFieldDefinition.cs} (79%) rename src/graphql-aspnet/{Configuration/Templates/GraphQLVirtualFieldTemplate.cs => Schemas/RuntimeSchemaItemDefinitions/RuntimeVirtualFieldTemplate.cs} (76%) diff --git a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Directives.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Directives.cs similarity index 84% rename from src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Directives.cs rename to src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Directives.cs index 0eeae9b48..7a54431bf 100644 --- a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Directives.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Directives.cs @@ -21,7 +21,7 @@ namespace GraphQL.AspNet.Configuration /// /// Extension methods for configuring minimal API methods as fields on the graph. /// - public static partial class GraphQLMinimalApiExtensions + public static partial class GraphQLRuntimeSchemaItemDefinitionExtensions { /// /// Adds policy-based authorization requirements to the directive. @@ -33,8 +33,8 @@ public static partial class GraphQLMinimalApiExtensions /// The name of the policy to assign via this requirement. /// A comma-seperated list of roles to assign via this requirement. /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeDirectiveTemplate RequireAuthorization( - this IGraphQLRuntimeDirectiveTemplate directiveTemplate, + public static IGraphQLRuntimeDirectiveDefinition RequireAuthorization( + this IGraphQLRuntimeDirectiveDefinition directiveTemplate, string policyName = null, string roles = null) { @@ -61,7 +61,7 @@ public static IGraphQLRuntimeDirectiveTemplate RequireAuthorization( /// /// The directive being built. /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeDirectiveTemplate AllowAnonymous(this IGraphQLRuntimeDirectiveTemplate directiveTemplate) + public static IGraphQLRuntimeDirectiveDefinition AllowAnonymous(this IGraphQLRuntimeDirectiveDefinition directiveTemplate) { Validation.ThrowIfNull(directiveTemplate, nameof(directiveTemplate)); directiveTemplate.Attributes.Add(new AllowAnonymousAttribute()); @@ -74,7 +74,7 @@ public static IGraphQLRuntimeDirectiveTemplate AllowAnonymous(this IGraphQLRunti /// /// The directive template. /// IGraphQLDirectiveTemplate. - public static IGraphQLRuntimeDirectiveTemplate IsRepeatable(this IGraphQLRuntimeDirectiveTemplate directiveTemplate) + public static IGraphQLRuntimeDirectiveDefinition IsRepeatable(this IGraphQLRuntimeDirectiveDefinition directiveTemplate) { var repeatable = new RepeatableAttribute(); directiveTemplate.Attributes.Add(repeatable); @@ -92,8 +92,8 @@ public static IGraphQLRuntimeDirectiveTemplate IsRepeatable(this IGraphQLRuntime /// The bitwise set of locations where this /// directive can be applied. /// IGraphQLDirectiveTemplate. - public static IGraphQLRuntimeDirectiveTemplate RestrictLocations( - this IGraphQLRuntimeDirectiveTemplate directiveTemplate, + public static IGraphQLRuntimeDirectiveDefinition RestrictLocations( + this IGraphQLRuntimeDirectiveDefinition directiveTemplate, DirectiveLocation locations) { var restrictions = new DirectiveLocationsAttribute(locations); @@ -117,7 +117,7 @@ public static IGraphQLRuntimeDirectiveTemplate RestrictLocations( /// The delegate to assign as the resolver. This method will be /// parsed to determine input arguments for the field on the target schema. /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeDirectiveTemplate AddResolver(this IGraphQLRuntimeDirectiveTemplate directiveTemplate, Delegate resolverMethod) + public static IGraphQLRuntimeDirectiveDefinition AddResolver(this IGraphQLRuntimeDirectiveDefinition directiveTemplate, Delegate resolverMethod) { directiveTemplate.Resolver = resolverMethod; directiveTemplate.ReturnType = null; @@ -137,7 +137,7 @@ public static IGraphQLRuntimeDirectiveTemplate AddResolver(this IGraphQLRuntimeD /// The delegate to assign as the resolver. This method will be /// parsed to determine input arguments for the directive on the target schema. /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeDirectiveTemplate AddResolver(this IGraphQLRuntimeDirectiveTemplate directiveTemplate, Delegate resolverMethod) + public static IGraphQLRuntimeDirectiveDefinition AddResolver(this IGraphQLRuntimeDirectiveDefinition directiveTemplate, Delegate resolverMethod) { directiveTemplate.Resolver = resolverMethod; directiveTemplate.ReturnType = typeof(TReturnType); @@ -150,7 +150,7 @@ public static IGraphQLRuntimeDirectiveTemplate AddResolver(this IGr /// The schema options where the directive will be created. /// Name of the directive (e.g. '@myDirective'). /// IGraphQLDirectiveTemplate. - public static IGraphQLRuntimeDirectiveTemplate MapDirective(this SchemaOptions schemaOptions, string directiveName) + public static IGraphQLRuntimeDirectiveDefinition MapDirective(this SchemaOptions schemaOptions, string directiveName) { return MapDirectiveInternal(schemaOptions, directiveName); } @@ -162,7 +162,7 @@ public static IGraphQLRuntimeDirectiveTemplate MapDirective(this SchemaOptions s /// Name of the directive (e.g. '@myDirective'). /// The resolver that will be executed when the directive is invoked. /// IGraphQLDirectiveTemplate. - public static IGraphQLRuntimeDirectiveTemplate MapDirective(this SchemaOptions schemaOptions, string directiveName, Delegate resolverMethod) + public static IGraphQLRuntimeDirectiveDefinition MapDirective(this SchemaOptions schemaOptions, string directiveName, Delegate resolverMethod) { Validation.ThrowIfNull(resolverMethod, nameof(resolverMethod)); @@ -176,7 +176,7 @@ public static IGraphQLRuntimeDirectiveTemplate MapDirective(this SchemaOptions s /// The builder representing the schema being constructed. /// Name of the directive (e.g. '@myDirective'). /// IGraphQLDirectiveTemplate. - public static IGraphQLRuntimeDirectiveTemplate MapDirective(this ISchemaBuilder schemaBuilder, string directiveName) + public static IGraphQLRuntimeDirectiveDefinition MapDirective(this ISchemaBuilder schemaBuilder, string directiveName) { Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); @@ -194,7 +194,7 @@ public static IGraphQLRuntimeDirectiveTemplate MapDirective(this ISchemaBuilder /// Name of the directive (e.g. '@myDirective'). /// The resolver that will be executed when the directive is invoked. /// IGraphQLDirectiveTemplate. - public static IGraphQLRuntimeDirectiveTemplate MapDirective(this ISchemaBuilder schemaBuilder, string directiveName, Delegate resolverMethod) + public static IGraphQLRuntimeDirectiveDefinition MapDirective(this ISchemaBuilder schemaBuilder, string directiveName, Delegate resolverMethod) { Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); Validation.ThrowIfNull(resolverMethod, nameof(resolverMethod)); diff --git a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Internals.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Internals.cs similarity index 75% rename from src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Internals.cs rename to src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Internals.cs index fe28f23b2..d9400dd4f 100644 --- a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Internals.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Internals.cs @@ -20,9 +20,9 @@ namespace GraphQL.AspNet.Configuration /// /// Extension methods for configuring minimal API methods as fields on the graph. /// - public static partial class GraphQLMinimalApiExtensions + public static partial class GraphQLRuntimeSchemaItemDefinitionExtensions { - private static IGraphQLFieldTemplate MapGraphQLFieldInternal( + private static IGraphQLRuntimeFieldDefinition MapGraphQLFieldInternal( SchemaOptions schemaOptions, GraphOperationType operationType, string pathTemplate) @@ -32,14 +32,14 @@ private static IGraphQLFieldTemplate MapGraphQLFieldInternal( var path = new SchemaItemPath((SchemaItemCollections)operationType, pathTemplate); - var fieldTemplate = new GraphQLVirtualFieldTemplate( + var fieldTemplate = new RuntimeVirtualFieldTemplate( schemaOptions, path.Path); return fieldTemplate; } - private static IGraphQLRuntimeTypeExtensionTemplate MapTypeExtensionInternal( + private static IGraphQLRuntimeTypeExtensionDefinition MapTypeExtensionInternal( SchemaOptions schemaOptions, Type typeToExtend, string fieldName, @@ -48,7 +48,7 @@ private static IGraphQLRuntimeTypeExtensionTemplate MapTypeExtensionInternal( schemaOptions = Validation.ThrowIfNullOrReturn(schemaOptions, nameof(schemaOptions)); fieldName = Validation.ThrowIfNullWhiteSpaceOrReturn(fieldName, nameof(fieldName)); - IGraphQLRuntimeTypeExtensionTemplate field = new GraphQLTypeExtensionFieldTemplate( + IGraphQLRuntimeTypeExtensionDefinition field = new RuntimeTypeExtensionFieldDefinition( schemaOptions, typeToExtend, fieldName, @@ -58,9 +58,9 @@ private static IGraphQLRuntimeTypeExtensionTemplate MapTypeExtensionInternal( return field; } - private static IGraphQLRuntimeDirectiveTemplate MapDirectiveInternal(this SchemaOptions schemaOptions, string directiveName) + private static IGraphQLRuntimeDirectiveDefinition MapDirectiveInternal(this SchemaOptions schemaOptions, string directiveName) { - var directive = new GraphQLDirectiveTemplate(schemaOptions, directiveName); + var directive = new RuntimeDirectiveDefinition(schemaOptions, directiveName); schemaOptions.AddSchemaItemTemplate(directive); return directive; diff --git a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Mutations.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Mutations.cs similarity index 87% rename from src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Mutations.cs rename to src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Mutations.cs index fa748a9f4..e835ea0f7 100644 --- a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Mutations.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Mutations.cs @@ -18,7 +18,7 @@ namespace GraphQL.AspNet.Configuration /// /// Extension methods for configuring minimal API methods as fields on the graph. /// - public static partial class GraphQLMinimalApiExtensions + public static partial class GraphQLRuntimeSchemaItemDefinitionExtensions { /// /// Creates a new field in the mutation root object with the given path. This field can act as a @@ -28,7 +28,7 @@ public static partial class GraphQLMinimalApiExtensions /// will be created. /// The template path string for his field. (e.g. /path1/path2/path3) /// IGraphQLFieldTemplate. - public static IGraphQLFieldTemplate MapMutation(this SchemaOptions schemaOptions, string template) + public static IGraphQLRuntimeFieldDefinition MapMutation(this SchemaOptions schemaOptions, string template) { var field = MapGraphQLFieldInternal( schemaOptions, @@ -48,7 +48,7 @@ public static IGraphQLFieldTemplate MapMutation(this SchemaOptions schemaOptions /// The resolver method to execute when /// this field is requested by a caller. /// IGraphQLResolvedFieldTemplate. - public static IGraphQLRuntimeResolvedFieldTemplate MapMutation(this SchemaOptions schemaOptions, string template, Delegate resolverMethod) + public static IGraphQLRuntimeResolvedFieldDefinition MapMutation(this SchemaOptions schemaOptions, string template, Delegate resolverMethod) { Validation.ThrowIfNull(resolverMethod, nameof(resolverMethod)); @@ -68,7 +68,7 @@ public static IGraphQLRuntimeResolvedFieldTemplate MapMutation(this SchemaOption /// will be created. /// The template path string for his field. (e.g. /path1/path2/path3) /// IGraphQLFieldTemplate. - public static IGraphQLFieldTemplate MapMutation(this ISchemaBuilder schemaBuilder, string template) + public static IGraphQLRuntimeFieldDefinition MapMutation(this ISchemaBuilder schemaBuilder, string template) { Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); @@ -89,7 +89,7 @@ public static IGraphQLFieldTemplate MapMutation(this ISchemaBuilder schemaBuilde /// The template path string for his field. (e.g. /path1/path2/path3) /// The resolver method to execute when this field is requested. /// IGraphQLFieldTemplate. - public static IGraphQLRuntimeResolvedFieldTemplate MapMutation(this ISchemaBuilder schemaBuilder, string template, Delegate resolverMethod) + public static IGraphQLRuntimeResolvedFieldDefinition MapMutation(this ISchemaBuilder schemaBuilder, string template, Delegate resolverMethod) { Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); Validation.ThrowIfNull(resolverMethod, nameof(resolverMethod)); diff --git a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Queries.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Queries.cs similarity index 87% rename from src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Queries.cs rename to src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Queries.cs index 41b2a11be..3cc0a9b0b 100644 --- a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_Queries.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Queries.cs @@ -18,7 +18,7 @@ namespace GraphQL.AspNet.Configuration /// /// Extension methods for configuring minimal API methods as fields on the graph. /// - public static partial class GraphQLMinimalApiExtensions + public static partial class GraphQLRuntimeSchemaItemDefinitionExtensions { /// /// Creates a new field in the query root object with the given path. This field can act as a @@ -28,7 +28,7 @@ public static partial class GraphQLMinimalApiExtensions /// will be created. /// The template path string for his field. (e.g. /path1/path2/path3) /// IGraphQLFieldTemplate. - public static IGraphQLFieldTemplate MapQuery(this SchemaOptions schemaOptions, string template) + public static IGraphQLRuntimeFieldDefinition MapQuery(this SchemaOptions schemaOptions, string template) { var field = MapGraphQLFieldInternal( schemaOptions, @@ -48,7 +48,7 @@ public static IGraphQLFieldTemplate MapQuery(this SchemaOptions schemaOptions, s /// The resolver method to execute when /// this field is requested by a caller. /// IGraphQLResolvedFieldTemplate. - public static IGraphQLRuntimeResolvedFieldTemplate MapQuery(this SchemaOptions schemaOptions, string template, Delegate resolverMethod) + public static IGraphQLRuntimeResolvedFieldDefinition MapQuery(this SchemaOptions schemaOptions, string template, Delegate resolverMethod) { Validation.ThrowIfNull(resolverMethod, nameof(resolverMethod)); @@ -68,7 +68,7 @@ public static IGraphQLRuntimeResolvedFieldTemplate MapQuery(this SchemaOptions s /// will be created. /// The template path string for his field. (e.g. /path1/path2/path3) /// IGraphQLFieldTemplate. - public static IGraphQLFieldTemplate MapQuery(this ISchemaBuilder schemaBuilder, string template) + public static IGraphQLRuntimeFieldDefinition MapQuery(this ISchemaBuilder schemaBuilder, string template) { Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); @@ -90,7 +90,7 @@ public static IGraphQLFieldTemplate MapQuery(this ISchemaBuilder schemaBuilder, /// The resolver method to execute when this /// field is requested. /// IGraphQLFieldTemplate. - public static IGraphQLRuntimeResolvedFieldTemplate MapQuery(this ISchemaBuilder schemaBuilder, string template, Delegate resolverMethod) + public static IGraphQLRuntimeResolvedFieldDefinition MapQuery(this ISchemaBuilder schemaBuilder, string template, Delegate resolverMethod) { Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); Validation.ThrowIfNull(resolverMethod, nameof(resolverMethod)); diff --git a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_ResolvedFields.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_ResolvedFields.cs similarity index 84% rename from src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_ResolvedFields.cs rename to src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_ResolvedFields.cs index 6fc0a55bc..d29519ae1 100644 --- a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_ResolvedFields.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_ResolvedFields.cs @@ -19,7 +19,7 @@ namespace GraphQL.AspNet.Configuration /// /// Extension methods for configuring minimal API methods as fields on the graph. /// - public static partial class GraphQLMinimalApiExtensions + public static partial class GraphQLRuntimeSchemaItemDefinitionExtensions { /// /// Adds policy-based authorization requirements to the field. @@ -31,8 +31,8 @@ public static partial class GraphQLMinimalApiExtensions /// The name of the policy to assign via this requirement. /// A comma-seperated list of roles to assign via this requirement. /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeResolvedFieldTemplate RequireAuthorization( - this IGraphQLRuntimeResolvedFieldTemplate fieldBuilder, + public static IGraphQLRuntimeResolvedFieldDefinition RequireAuthorization( + this IGraphQLRuntimeResolvedFieldDefinition fieldBuilder, string policyName = null, string roles = null) { @@ -53,7 +53,7 @@ public static IGraphQLRuntimeResolvedFieldTemplate RequireAuthorization( /// /// The field being built. /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeResolvedFieldTemplate AllowAnonymous(this IGraphQLRuntimeResolvedFieldTemplate fieldBuilder) + public static IGraphQLRuntimeResolvedFieldDefinition AllowAnonymous(this IGraphQLRuntimeResolvedFieldDefinition fieldBuilder) { Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); fieldBuilder.Attributes.Add(new AllowAnonymousAttribute()); @@ -70,7 +70,7 @@ public static IGraphQLRuntimeResolvedFieldTemplate AllowAnonymous(this IGraphQLR /// The delegate to assign as the resolver. This method will be /// parsed to determine input arguments for the field on the target schema. /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeResolvedFieldTemplate AddResolver(this IGraphQLRuntimeResolvedFieldTemplate fieldBuilder, Delegate resolverMethod) + public static IGraphQLRuntimeResolvedFieldDefinition AddResolver(this IGraphQLRuntimeResolvedFieldDefinition fieldBuilder, Delegate resolverMethod) { fieldBuilder.Resolver = resolverMethod; fieldBuilder.ReturnType = null; @@ -90,7 +90,7 @@ public static IGraphQLRuntimeResolvedFieldTemplate AddResolver(this IGraphQLRunt /// The delegate to assign as the resolver. This method will be /// parsed to determine input arguments for the field on the target schema. /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeResolvedFieldTemplate AddResolver(this IGraphQLRuntimeResolvedFieldTemplate fieldBuilder, Delegate resolverMethod) + public static IGraphQLRuntimeResolvedFieldDefinition AddResolver(this IGraphQLRuntimeResolvedFieldDefinition fieldBuilder, Delegate resolverMethod) { fieldBuilder.Resolver = resolverMethod; fieldBuilder.ReturnType = typeof(TReturnType); @@ -110,7 +110,7 @@ public static IGraphQLRuntimeResolvedFieldTemplate AddResolver(this /// Any number of additional possible types that /// might be returned by this field. /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeResolvedFieldTemplate AddPossibleTypes(this IGraphQLRuntimeResolvedFieldTemplate fieldBuilder, Type firstPossibleType, params Type[] additionalPossibleTypes) + public static IGraphQLRuntimeResolvedFieldDefinition AddPossibleTypes(this IGraphQLRuntimeResolvedFieldDefinition fieldBuilder, Type firstPossibleType, params Type[] additionalPossibleTypes) { var possibleTypes = new PossibleTypesAttribute(firstPossibleType, additionalPossibleTypes); fieldBuilder.Attributes.Add(possibleTypes); diff --git a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_TypeExtensions.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_TypeExtensions.cs similarity index 84% rename from src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_TypeExtensions.cs rename to src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_TypeExtensions.cs index 3006fc5c9..2f68fdd67 100644 --- a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_TypeExtensions.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_TypeExtensions.cs @@ -21,7 +21,7 @@ namespace GraphQL.AspNet.Configuration /// /// Extension methods for configuring minimal API methods as fields on the graph. /// - public static partial class GraphQLMinimalApiExtensions + public static partial class GraphQLRuntimeSchemaItemDefinitionExtensions { /// /// Adds policy-based authorization requirements to the field. @@ -33,8 +33,8 @@ public static partial class GraphQLMinimalApiExtensions /// The name of the policy to assign via this requirement. /// A comma-seperated list of roles to assign via this requirement. /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeTypeExtensionTemplate RequireAuthorization( - this IGraphQLRuntimeTypeExtensionTemplate fieldBuilder, + public static IGraphQLRuntimeTypeExtensionDefinition RequireAuthorization( + this IGraphQLRuntimeTypeExtensionDefinition fieldBuilder, string policyName = null, string roles = null) { @@ -55,7 +55,7 @@ public static IGraphQLRuntimeTypeExtensionTemplate RequireAuthorization( /// /// The field being built. /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeTypeExtensionTemplate AllowAnonymous(this IGraphQLRuntimeTypeExtensionTemplate fieldBuilder) + public static IGraphQLRuntimeTypeExtensionDefinition AllowAnonymous(this IGraphQLRuntimeTypeExtensionDefinition fieldBuilder) { Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); fieldBuilder.Attributes.Add(new AllowAnonymousAttribute()); @@ -72,7 +72,7 @@ public static IGraphQLRuntimeTypeExtensionTemplate AllowAnonymous(this IGraphQLR /// The delegate to assign as the resolver. This method will be /// parsed to determine input arguments for the field on the target schema. /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeTypeExtensionTemplate AddResolver(this IGraphQLRuntimeTypeExtensionTemplate fieldBuilder, Delegate resolverMethod) + public static IGraphQLRuntimeTypeExtensionDefinition AddResolver(this IGraphQLRuntimeTypeExtensionDefinition fieldBuilder, Delegate resolverMethod) { fieldBuilder.Resolver = resolverMethod; fieldBuilder.ReturnType = null; @@ -92,7 +92,7 @@ public static IGraphQLRuntimeTypeExtensionTemplate AddResolver(this IGraphQLRunt /// The delegate to assign as the resolver. This method will be /// parsed to determine input arguments for the field on the target schema. /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeTypeExtensionTemplate AddResolver(this IGraphQLRuntimeTypeExtensionTemplate fieldBuilder, Delegate resolverMethod) + public static IGraphQLRuntimeTypeExtensionDefinition AddResolver(this IGraphQLRuntimeTypeExtensionDefinition fieldBuilder, Delegate resolverMethod) { fieldBuilder.Resolver = resolverMethod; fieldBuilder.ReturnType = typeof(TReturnType); @@ -116,7 +116,7 @@ public static IGraphQLRuntimeTypeExtensionTemplate AddResolver(this /// Name of the field to add to the . /// The resolver method to be called when the field is requested. /// IGraphQLResolvedFieldTemplate. - public static IGraphQLRuntimeTypeExtensionTemplate MapField(this SchemaOptions schemaOptions, string fieldName, Delegate resolverMethod = null) + public static IGraphQLRuntimeTypeExtensionDefinition MapField(this SchemaOptions schemaOptions, string fieldName, Delegate resolverMethod = null) { return schemaOptions.MapField( typeof(TOwnerType), @@ -137,7 +137,7 @@ public static IGraphQLRuntimeTypeExtensionTemplate MapField(this Sch /// Name of the field to add to the . /// The resolver method to be called when the field is requested. /// IGraphQLResolvedFieldTemplate. - public static IGraphQLRuntimeTypeExtensionTemplate MapField(this SchemaOptions schemaOptions, Type fieldOwnerType, string fieldName, Delegate resolverMethod = null) + public static IGraphQLRuntimeTypeExtensionDefinition MapField(this SchemaOptions schemaOptions, Type fieldOwnerType, string fieldName, Delegate resolverMethod = null) { var field = MapTypeExtensionInternal( schemaOptions, @@ -158,12 +158,12 @@ public static IGraphQLRuntimeTypeExtensionTemplate MapField(this SchemaOptions s /// /// /// The supplied resolver must declare a parameter that is an of the same as - /// class, interface or struct that was originally extended as indicated by . + /// class, interface or struct that was originally extended as indicated by . /// /// /// The type extension to make into a batch field. /// IGraphQLTypeExtensionTemplate. - public static IGraphQLRuntimeTypeExtensionTemplate WithBatchProcessing(this IGraphQLRuntimeTypeExtensionTemplate typeExtension) + public static IGraphQLRuntimeTypeExtensionDefinition WithBatchProcessing(this IGraphQLRuntimeTypeExtensionDefinition typeExtension) { typeExtension.ExecutionMode = FieldResolutionMode.Batch; return typeExtension; @@ -182,7 +182,7 @@ public static IGraphQLRuntimeTypeExtensionTemplate WithBatchProcessing(this IGra /// Any number of additional possible types that /// might be returned by this field. /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeTypeExtensionTemplate AddPossibleTypes(this IGraphQLRuntimeTypeExtensionTemplate fieldBuilder, Type firstPossibleType, params Type[] additionalPossibleTypes) + public static IGraphQLRuntimeTypeExtensionDefinition AddPossibleTypes(this IGraphQLRuntimeTypeExtensionDefinition fieldBuilder, Type firstPossibleType, params Type[] additionalPossibleTypes) { var possibleTypes = new PossibleTypesAttribute(firstPossibleType, additionalPossibleTypes); fieldBuilder.Attributes.Add(possibleTypes); diff --git a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_VirtualFields.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_VirtualFields.cs similarity index 82% rename from src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_VirtualFields.cs rename to src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_VirtualFields.cs index 76964094a..0ee83e17d 100644 --- a/src/graphql-aspnet/Configuration/GraphQLMinimalApiExtensions_VirtualFields.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_VirtualFields.cs @@ -19,7 +19,7 @@ namespace GraphQL.AspNet.Configuration /// /// Extension methods for configuring minimal API methods as fields on the graph. /// - public static partial class GraphQLMinimalApiExtensions + public static partial class GraphQLRuntimeSchemaItemDefinitionExtensions { /// /// Adds policy-based authorization requirements to the field. @@ -31,8 +31,8 @@ public static partial class GraphQLMinimalApiExtensions /// The name of the policy to assign via this requirement. /// A comma-seperated list of roles to assign via this requirement. /// IGraphQLFieldBuilder. - public static IGraphQLFieldTemplate RequireAuthorization( - this IGraphQLFieldTemplate fieldBuilder, + public static IGraphQLRuntimeFieldDefinition RequireAuthorization( + this IGraphQLRuntimeFieldDefinition fieldBuilder, string policyName = null, string roles = null) { @@ -59,7 +59,7 @@ public static IGraphQLFieldTemplate RequireAuthorization( /// /// The field being built. /// IGraphQLFieldBuilder. - public static IGraphQLFieldTemplate AllowAnonymous(this IGraphQLFieldTemplate fieldBuilder) + public static IGraphQLRuntimeFieldDefinition AllowAnonymous(this IGraphQLRuntimeFieldDefinition fieldBuilder) { Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); fieldBuilder.Attributes.Add(new AllowAnonymousAttribute()); @@ -76,10 +76,10 @@ public static IGraphQLFieldTemplate AllowAnonymous(this IGraphQLFieldTemplate fi /// The delegate to assign as the resolver. This method will be /// parsed to determine input arguments for the field on the target schema. /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeResolvedFieldTemplate AddResolver(this IGraphQLFieldTemplate field, Delegate resolverMethod) + public static IGraphQLRuntimeResolvedFieldDefinition AddResolver(this IGraphQLRuntimeFieldDefinition field, Delegate resolverMethod) { // convert the virtual field to a resolved field - var resolvedBuilder = GraphQLResolvedFieldTemplate.FromFieldTemplate(field); + var resolvedBuilder = RuntimeResolvedFieldDefinition.FromFieldTemplate(field); resolvedBuilder.Options.AddSchemaItemTemplate(resolvedBuilder); resolvedBuilder.Resolver = resolverMethod; @@ -100,10 +100,10 @@ public static IGraphQLRuntimeResolvedFieldTemplate AddResolver(this IGraphQLFiel /// The delegate to assign as the resolver. This method will be /// parsed to determine input arguments for the field on the target schema. /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeResolvedFieldTemplate AddResolver(this IGraphQLFieldTemplate field, Delegate resolverMethod) + public static IGraphQLRuntimeResolvedFieldDefinition AddResolver(this IGraphQLRuntimeFieldDefinition field, Delegate resolverMethod) { // convert the virtual field to a resolved field - var resolvedBuilder = GraphQLResolvedFieldTemplate.FromFieldTemplate(field); + var resolvedBuilder = RuntimeResolvedFieldDefinition.FromFieldTemplate(field); resolvedBuilder.Options.AddSchemaItemTemplate(resolvedBuilder); resolvedBuilder.Resolver = resolverMethod; @@ -118,9 +118,9 @@ public static IGraphQLRuntimeResolvedFieldTemplate AddResolver(this /// The template pattern to be appended to the supplied . /// The resolver method to be called when this field is requested. /// IGraphQLResolvedFieldBuilder. - public static IGraphQLRuntimeResolvedFieldTemplate MapField(this IGraphQLFieldTemplate field, string subTemplate, Delegate resolverMethod) + public static IGraphQLRuntimeResolvedFieldDefinition MapField(this IGraphQLRuntimeFieldDefinition field, string subTemplate, Delegate resolverMethod) { - var subField = new GraphQLResolvedFieldTemplate(field, subTemplate); + var subField = new RuntimeResolvedFieldDefinition(field, subTemplate); subField.AddResolver(resolverMethod); subField.Options.AddSchemaItemTemplate(subField); @@ -134,9 +134,9 @@ public static IGraphQLRuntimeResolvedFieldTemplate MapField(this IGraphQLFieldTe /// The field under which this new field will be nested. /// The template pattern to be appended to the supplied . /// IGraphQLFieldBuilder. - public static IGraphQLFieldTemplate MapField(this IGraphQLFieldTemplate field, string subTemplate) + public static IGraphQLRuntimeFieldDefinition MapField(this IGraphQLRuntimeFieldDefinition field, string subTemplate) { - var subField = new GraphQLVirtualFieldTemplate(field, subTemplate); + var subField = new RuntimeVirtualFieldTemplate(field, subTemplate); return subField; } } diff --git a/src/graphql-aspnet/Configuration/SchemaOptions.cs b/src/graphql-aspnet/Configuration/SchemaOptions.cs index b5b95fa8e..51b77b2ce 100644 --- a/src/graphql-aspnet/Configuration/SchemaOptions.cs +++ b/src/graphql-aspnet/Configuration/SchemaOptions.cs @@ -35,7 +35,7 @@ public abstract class SchemaOptions private readonly HashSet _possibleTypes; private readonly List _registeredServices; - private readonly List _runtimeTemplates; + private readonly List _runtimeTemplates; private List _configExtensions; /// @@ -52,7 +52,7 @@ public SchemaOptions(Type schemaType, IServiceCollection serviceCollection) Validation.ThrowIfNotCastable(schemaType, nameof(schemaType)); _possibleTypes = new HashSet(SchemaTypeToRegister.DefaultEqualityComparer); - _runtimeTemplates = new List(); + _runtimeTemplates = new List(); _serverExtensions = new Dictionary(); _registeredServices = new List(); _configExtensions = new List(); @@ -355,7 +355,7 @@ internal void FinalizeServiceRegistration() /// created when the schema is set up. /// /// The template to add. - internal void AddSchemaItemTemplate(IGraphQLRuntimeSchemaItemTemplate template) + internal void AddSchemaItemTemplate(IGraphQLRuntimeSchemaItemDefinition template) { _runtimeTemplates.Add(template); } @@ -368,7 +368,7 @@ internal void AddSchemaItemTemplate(IGraphQLRuntimeSchemaItemTemplate template) /// These are the templates created via the Minimal API methods. /// /// The runtime templates. - public IEnumerable RuntimeTemplates => _runtimeTemplates; + public IEnumerable RuntimeTemplates => _runtimeTemplates; /// /// Gets the classes, enums, structs and other types that need to be diff --git a/src/graphql-aspnet/Interfaces/Engine/IGraphTypeTemplateProvider.cs b/src/graphql-aspnet/Interfaces/Engine/IGraphTypeTemplateProvider.cs index e38a269ef..5589229eb 100644 --- a/src/graphql-aspnet/Interfaces/Engine/IGraphTypeTemplateProvider.cs +++ b/src/graphql-aspnet/Interfaces/Engine/IGraphTypeTemplateProvider.cs @@ -10,6 +10,7 @@ namespace GraphQL.AspNet.Interfaces.Engine { using System; + using GraphQL.AspNet.Interfaces.Configuration.Templates; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Schemas.TypeSystem; @@ -35,7 +36,7 @@ public interface IGraphTypeTemplateProvider ISchemaItemTemplate ParseType(TypeKind? kind = null); /// - /// Parses the provided type, extracting the metadata to used in type generation for the object graph. + /// Parses the provided type, extracting the metadata used in type generation for the object graph. /// /// The type of the object to parse. /// The graph to create a template for. If not supplied the template provider diff --git a/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLResolvableSchemaItemTemplate.cs b/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLResolvableSchemaItemDefinition.cs similarity index 94% rename from src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLResolvableSchemaItemTemplate.cs rename to src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLResolvableSchemaItemDefinition.cs index 992bd2f22..591116630 100644 --- a/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLResolvableSchemaItemTemplate.cs +++ b/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLResolvableSchemaItemDefinition.cs @@ -15,7 +15,7 @@ namespace GraphQL.AspNet.Interfaces.Configuration.Templates /// A template for a runtime created schema item that has an attached resolver. Usually /// a field or a directive. /// - public interface IGraphQLResolvableSchemaItemTemplate + public interface IGraphQLResolvableSchemaItemDefinition { /// /// Gets or sets the resolver function that has been assigned to execute when this diff --git a/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLRuntimeDirectiveTemplate.cs b/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeDirectiveDefinition.cs similarity index 81% rename from src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLRuntimeDirectiveTemplate.cs rename to src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeDirectiveDefinition.cs index 5a7b55137..40be8f1b0 100644 --- a/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLRuntimeDirectiveTemplate.cs +++ b/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeDirectiveDefinition.cs @@ -13,7 +13,7 @@ namespace GraphQL.AspNet.Interfaces.Configuration.Templates /// An intermediate template that utilizies a key/value pair system to build up a set of component parts /// that the templating engine will use to generate a full fledged field in a schema. /// - public interface IGraphQLRuntimeDirectiveTemplate : IGraphQLRuntimeSchemaItemTemplate, IGraphQLResolvableSchemaItemTemplate + public interface IGraphQLRuntimeDirectiveDefinition : IGraphQLRuntimeSchemaItemDefinition, IGraphQLResolvableSchemaItemDefinition { } } \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLFieldTemplate.cs b/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeFieldDefinition.cs similarity index 88% rename from src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLFieldTemplate.cs rename to src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeFieldDefinition.cs index 6a43b61fd..d01c6ccca 100644 --- a/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLFieldTemplate.cs +++ b/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeFieldDefinition.cs @@ -17,7 +17,7 @@ namespace GraphQL.AspNet.Interfaces.Configuration.Templates /// An intermediate template that utilizies a key/value pair system to build up a set of component parts /// that the templating engine will use to generate a full fledged field in a schema. /// - public interface IGraphQLFieldTemplate : IGraphQLRuntimeSchemaItemTemplate + public interface IGraphQLRuntimeFieldDefinition : IGraphQLRuntimeSchemaItemDefinition { } } \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLRuntimeResolvedFieldTemplate.cs b/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeResolvedFieldDefinition.cs similarity index 87% rename from src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLRuntimeResolvedFieldTemplate.cs rename to src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeResolvedFieldDefinition.cs index 4bb18a7f2..2c2e07509 100644 --- a/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLRuntimeResolvedFieldTemplate.cs +++ b/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeResolvedFieldDefinition.cs @@ -21,7 +21,7 @@ namespace GraphQL.AspNet.Interfaces.Configuration.Templates /// in that it has an explicit resolver applied. The runtime will not attempt to /// autoresolve this field. /// - public interface IGraphQLRuntimeResolvedFieldTemplate : IGraphQLRuntimeSchemaItemTemplate, IGraphQLResolvableSchemaItemTemplate + public interface IGraphQLRuntimeResolvedFieldDefinition : IGraphQLRuntimeSchemaItemDefinition, IGraphQLResolvableSchemaItemDefinition { } } \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLRuntimeSchemaItemTemplate.cs b/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeSchemaItemDefinition.cs similarity index 95% rename from src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLRuntimeSchemaItemTemplate.cs rename to src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeSchemaItemDefinition.cs index 19a1c0bfd..683ba6040 100644 --- a/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLRuntimeSchemaItemTemplate.cs +++ b/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeSchemaItemDefinition.cs @@ -18,7 +18,7 @@ namespace GraphQL.AspNet.Interfaces.Configuration.Templates /// A marker templtae for any runtime-built schema item (field, directive etc.) /// being added to the schema. /// - public interface IGraphQLRuntimeSchemaItemTemplate : IDictionary + public interface IGraphQLRuntimeSchemaItemDefinition : IDictionary { /// /// Creates a path object using the current template path assigned to this template. This diff --git a/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLRuntimeTypeExtensionTemplate.cs b/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeTypeExtensionDefinition.cs similarity index 89% rename from src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLRuntimeTypeExtensionTemplate.cs rename to src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeTypeExtensionDefinition.cs index 224b7c455..29e7c72e4 100644 --- a/src/graphql-aspnet/Interfaces/Configuration/Templates/IGraphQLRuntimeTypeExtensionTemplate.cs +++ b/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeTypeExtensionDefinition.cs @@ -16,7 +16,7 @@ namespace GraphQL.AspNet.Interfaces.Configuration.Templates /// An intermediate template that utilizies a key/value pair system to build up a set of component parts /// that the templating engine will use to generate a full fledged type extension in a schema. /// - public interface IGraphQLRuntimeTypeExtensionTemplate : IGraphQLRuntimeSchemaItemTemplate, IGraphQLResolvableSchemaItemTemplate + public interface IGraphQLRuntimeTypeExtensionDefinition : IGraphQLRuntimeSchemaItemDefinition, IGraphQLResolvableSchemaItemDefinition { /// /// Gets the concrcete type of the OBJECT or INTERFACE that will be extended. diff --git a/src/graphql-aspnet/Internal/TypeTemplates/RuntimeSchemaItemTemplate.cs b/src/graphql-aspnet/Internal/TypeTemplates/RuntimeSchemaItemTemplate.cs index 6afdd5ad2..6f75eaa4f 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/RuntimeSchemaItemTemplate.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/RuntimeSchemaItemTemplate.cs @@ -15,17 +15,21 @@ namespace GraphQL.AspNet.Internal.TypeTemplates using GraphQL.AspNet.Interfaces.Configuration.Templates; /// - /// A template of a directive generated at runtime rather than via a class that - /// inherits from a . + /// A template of a schema item generated at runtime rather than via a class defined + /// at compile time. /// internal class RuntimeSchemaItemTemplate : GraphDirectiveTemplate { - private IGraphQLRuntimeSchemaItemTemplate _runtimeTemplate; + private IGraphQLRuntimeSchemaItemDefinition _runtimeDefinition; - public RuntimeSchemaItemTemplate(IGraphQLRuntimeSchemaItemTemplate template) + /// + /// Initializes a new instance of the class. + /// + /// The definition, configured at runtime to templatize. + public RuntimeSchemaItemTemplate(IGraphQLRuntimeSchemaItemDefinition definition) : base(typeof(RuntimeSchemaItemTypeMarker)) { - _runtimeTemplate = Validation.ThrowIfNullOrReturn(template, nameof(template)); + _runtimeDefinition = Validation.ThrowIfNullOrReturn(definition, nameof(definition)); } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/GraphSchemaManager.cs b/src/graphql-aspnet/Schemas/GraphSchemaManager.cs index 00d1b44ec..7bedd0c8e 100644 --- a/src/graphql-aspnet/Schemas/GraphSchemaManager.cs +++ b/src/graphql-aspnet/Schemas/GraphSchemaManager.cs @@ -18,6 +18,7 @@ namespace GraphQL.AspNet.Schemas using GraphQL.AspNet.Engine.TypeMakers; using GraphQL.AspNet.Execution; using GraphQL.AspNet.Execution.Exceptions; + using GraphQL.AspNet.Interfaces.Configuration.Templates; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Internal; @@ -377,8 +378,8 @@ public void EnsureGraphType(Type type, TypeKind? kind = null) Validation.ThrowIfNull(type, nameof(type)); if (Validation.IsCastable(type)) { - if (GraphQLProviders.TemplateProvider.ParseType(type) is IGraphControllerTemplate controllerDefinition) - this.AddController(controllerDefinition); + if (GraphQLProviders.TemplateProvider.ParseType(type) is IGraphControllerTemplate controllerTemplate) + this.AddController(controllerTemplate); return; } diff --git a/src/graphql-aspnet/Configuration/Templates/BaseGraphQLRuntimeSchemaItemTemplate.cs b/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/BaseRuntimeSchemaItemDefinition.cs similarity index 79% rename from src/graphql-aspnet/Configuration/Templates/BaseGraphQLRuntimeSchemaItemTemplate.cs rename to src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/BaseRuntimeSchemaItemDefinition.cs index 0254730af..76ba5adb4 100644 --- a/src/graphql-aspnet/Configuration/Templates/BaseGraphQLRuntimeSchemaItemTemplate.cs +++ b/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/BaseRuntimeSchemaItemDefinition.cs @@ -20,27 +20,27 @@ namespace GraphQL.AspNet.Configuration.Templates /// An abstract class containing all the common elements across minimal field builders and /// their supporting classes. /// - internal abstract class BaseGraphQLRuntimeSchemaItemTemplate : Dictionary, IGraphQLRuntimeSchemaItemTemplate + internal abstract class BaseRuntimeSchemaItemDefinition : Dictionary, IGraphQLRuntimeSchemaItemDefinition { - private IGraphQLFieldTemplate _parent; + private IGraphQLRuntimeFieldDefinition _parent; private string _partialPathTemplate; /// - /// Prevents a default instance of the class from being created. + /// Prevents a default instance of the class from being created. /// - private BaseGraphQLRuntimeSchemaItemTemplate() + private BaseRuntimeSchemaItemDefinition() { this.Attributes = new List(); } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The schema options where this field item /// is being defined. /// The partial path template defined for this /// individual entity. - protected BaseGraphQLRuntimeSchemaItemTemplate( + protected BaseRuntimeSchemaItemDefinition( SchemaOptions options, string partialPathTemplate) : this() @@ -52,13 +52,13 @@ protected BaseGraphQLRuntimeSchemaItemTemplate( } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The group builder from which this entity is being created. /// The partial path template defined for this /// individual entity. - protected BaseGraphQLRuntimeSchemaItemTemplate( - IGraphQLFieldTemplate parentVirtualFieldBuilder, + protected BaseRuntimeSchemaItemDefinition( + IGraphQLRuntimeFieldDefinition parentVirtualFieldBuilder, string partialPathTemplate) : this() { diff --git a/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeControllerDefinition.cs b/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeControllerDefinition.cs new file mode 100644 index 000000000..3c9ffd21b --- /dev/null +++ b/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeControllerDefinition.cs @@ -0,0 +1,15 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Schemas.RuntimeSchemaItemDefinitions +{ + internal class RuntimeControllerDefinition + { + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/Templates/GraphQLDirectiveTemplate.cs b/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeDirectiveDefinition.cs similarity index 77% rename from src/graphql-aspnet/Configuration/Templates/GraphQLDirectiveTemplate.cs rename to src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeDirectiveDefinition.cs index ff10ec2c2..5f817fdd9 100644 --- a/src/graphql-aspnet/Configuration/Templates/GraphQLDirectiveTemplate.cs +++ b/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeDirectiveDefinition.cs @@ -15,18 +15,18 @@ namespace GraphQL.AspNet.Configuration.Templates using GraphQL.AspNet.Interfaces.Configuration.Templates; /// - /// An internal implementation of the + /// An internal implementation of the /// used to generate new graphql directives via a minimal api style of coding. /// [DebuggerDisplay("{Template}")] - internal class GraphQLDirectiveTemplate : BaseGraphQLRuntimeSchemaItemTemplate, IGraphQLRuntimeDirectiveTemplate + internal class RuntimeDirectiveDefinition : BaseRuntimeSchemaItemDefinition, IGraphQLRuntimeDirectiveDefinition { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The schema options where this directive will be created. /// Name of the directive to use in the schema. - public GraphQLDirectiveTemplate(SchemaOptions schemaOptions, string directiveName) + public RuntimeDirectiveDefinition(SchemaOptions schemaOptions, string directiveName) : base(schemaOptions, directiveName) { } diff --git a/src/graphql-aspnet/Configuration/Templates/GraphQLResolvedFieldTemplate.cs b/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeResolvedFieldDefinition.cs similarity index 76% rename from src/graphql-aspnet/Configuration/Templates/GraphQLResolvedFieldTemplate.cs rename to src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeResolvedFieldDefinition.cs index 00340fba4..77dfe1f81 100644 --- a/src/graphql-aspnet/Configuration/Templates/GraphQLResolvedFieldTemplate.cs +++ b/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeResolvedFieldDefinition.cs @@ -16,11 +16,11 @@ namespace GraphQL.AspNet.Configuration.Templates using GraphQL.AspNet.Interfaces.Configuration.Templates; /// - /// An internal implementation of the + /// An internal implementation of the /// used to generate new graphql fields via a minimal api style of coding. /// [DebuggerDisplay("{Template}")] - internal class GraphQLResolvedFieldTemplate : BaseGraphQLRuntimeSchemaItemTemplate, IGraphQLRuntimeResolvedFieldTemplate + internal class RuntimeResolvedFieldDefinition : BaseRuntimeSchemaItemDefinition, IGraphQLRuntimeResolvedFieldDefinition { /// /// Converts the unresolved field into a resolved field. The newly generated field @@ -28,10 +28,10 @@ internal class GraphQLResolvedFieldTemplate : BaseGraphQLRuntimeSchemaItemTempla /// /// The field template. /// IGraphQLResolvedFieldTemplate. - public static IGraphQLRuntimeResolvedFieldTemplate FromFieldTemplate(IGraphQLFieldTemplate fieldTemplate) + public static IGraphQLRuntimeResolvedFieldDefinition FromFieldTemplate(IGraphQLRuntimeFieldDefinition fieldTemplate) { Validation.ThrowIfNull(fieldTemplate, nameof(fieldTemplate)); - var field = new GraphQLResolvedFieldTemplate(fieldTemplate.Options, fieldTemplate.Template); + var field = new RuntimeResolvedFieldDefinition(fieldTemplate.Options, fieldTemplate.Template); foreach (var attrib in fieldTemplate.Attributes) field.Attributes.Add(attrib); @@ -43,11 +43,11 @@ public static IGraphQLRuntimeResolvedFieldTemplate FromFieldTemplate(IGraphQLFie } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The schema options to which this field is being added. /// The full path template describing where the field will live. - public GraphQLResolvedFieldTemplate( + public RuntimeResolvedFieldDefinition( SchemaOptions schemaOptions, string fullPathTemplate) : base(schemaOptions, fullPathTemplate) @@ -55,13 +55,13 @@ public GraphQLResolvedFieldTemplate( } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The parent field builder to which this new, resolved field /// will be appended. /// The template part to append to the parent field's template. - public GraphQLResolvedFieldTemplate( - IGraphQLFieldTemplate parentFieldBuilder, + public RuntimeResolvedFieldDefinition( + IGraphQLRuntimeFieldDefinition parentFieldBuilder, string fieldSubTemplate) : base(parentFieldBuilder, fieldSubTemplate) { diff --git a/src/graphql-aspnet/Configuration/Templates/GraphQLTypeExtensionFieldTemplate.cs b/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeTypeExtensionFieldDefinition.cs similarity index 79% rename from src/graphql-aspnet/Configuration/Templates/GraphQLTypeExtensionFieldTemplate.cs rename to src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeTypeExtensionFieldDefinition.cs index 5b49f048c..07170a5c4 100644 --- a/src/graphql-aspnet/Configuration/Templates/GraphQLTypeExtensionFieldTemplate.cs +++ b/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeTypeExtensionFieldDefinition.cs @@ -16,26 +16,26 @@ namespace GraphQL.AspNet.Configuration.Templates using GraphQL.AspNet.Interfaces.Configuration.Templates; /// - /// An internal implementation of the + /// An internal implementation of the /// used to generate new type extensions via a minimal api style of coding. /// [DebuggerDisplay("{Template}")] - internal class GraphQLTypeExtensionFieldTemplate : GraphQLResolvedFieldTemplate, IGraphQLRuntimeTypeExtensionTemplate + internal class RuntimeTypeExtensionFieldDefinition : RuntimeResolvedFieldDefinition, IGraphQLRuntimeTypeExtensionDefinition { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The schema options where this type extension is being declared. /// The target OBJECT or INTERFACE type to extend. /// Name of the field to add to the . /// The resolution mode for the resolver implemented by this /// type extension. - public GraphQLTypeExtensionFieldTemplate( + public RuntimeTypeExtensionFieldDefinition( SchemaOptions schemaOptions, Type typeToExtend, string fieldName, FieldResolutionMode resolutionMode) - : base(schemaOptions, fieldName) + : base(schemaOptions, fieldName) { this.ExecutionMode = resolutionMode; this.TargetType = typeToExtend; diff --git a/src/graphql-aspnet/Configuration/Templates/GraphQLVirtualFieldTemplate.cs b/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeVirtualFieldTemplate.cs similarity index 76% rename from src/graphql-aspnet/Configuration/Templates/GraphQLVirtualFieldTemplate.cs rename to src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeVirtualFieldTemplate.cs index 1d0d2b567..9f7302322 100644 --- a/src/graphql-aspnet/Configuration/Templates/GraphQLVirtualFieldTemplate.cs +++ b/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeVirtualFieldTemplate.cs @@ -14,20 +14,20 @@ namespace GraphQL.AspNet.Configuration.Templates using GraphQL.AspNet.Interfaces.Configuration.Templates; /// - /// An internal implementation of the + /// An internal implementation of the /// used to generate new graphql fields via a minimal api style of coding. /// [DebuggerDisplay("{Template}")] - internal class GraphQLVirtualFieldTemplate : BaseGraphQLRuntimeSchemaItemTemplate, IGraphQLFieldTemplate + internal class RuntimeVirtualFieldTemplate : BaseRuntimeSchemaItemDefinition, IGraphQLRuntimeFieldDefinition { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The schema options that will own the fields created from /// this builder. /// The partial field path template /// that will be prepended to any fields or groups created from this builder. - public GraphQLVirtualFieldTemplate( + public RuntimeVirtualFieldTemplate( SchemaOptions options, string fieldTemplate) : base(options, fieldTemplate) @@ -35,13 +35,13 @@ public GraphQLVirtualFieldTemplate( } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The parent virtual field from which /// this builder will copy its settings. /// The partial path template to be appended to /// the parent's already defined template. - public GraphQLVirtualFieldTemplate(IGraphQLFieldTemplate parentFieldBuilder, string fieldSubTemplate) + public RuntimeVirtualFieldTemplate(IGraphQLRuntimeFieldDefinition parentFieldBuilder, string fieldSubTemplate) : base(parentFieldBuilder, fieldSubTemplate) { } diff --git a/src/graphql-aspnet/graphql-aspnet.csproj b/src/graphql-aspnet/graphql-aspnet.csproj index 9244449ae..8d890b54f 100644 --- a/src/graphql-aspnet/graphql-aspnet.csproj +++ b/src/graphql-aspnet/graphql-aspnet.csproj @@ -18,4 +18,7 @@ + + + \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedDirectiveTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedDirectiveTemplateTests.cs index b0f7ff53a..12db75f9f 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedDirectiveTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedDirectiveTemplateTests.cs @@ -31,7 +31,7 @@ public void MapDirective_ByOptions_AddsDirectiveToOptions() var options = new SchemaOptions(services); var directive = options.MapDirective("@myDirective"); - Assert.IsInstanceOf(typeof(IGraphQLRuntimeDirectiveTemplate), directive); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeDirectiveDefinition), directive); Assert.AreEqual(1, options.RuntimeTemplates.Count()); Assert.IsNotNull(options.RuntimeTemplates.FirstOrDefault(x => x == directive)); @@ -50,7 +50,7 @@ public void MapDirective_ByBuilder_AddsDirectiveToOptions() builderMock.Setup(x => x.Options).Returns(options); var directive = builderMock.Object.MapDirective("@myDirective"); - Assert.IsInstanceOf(typeof(IGraphQLRuntimeDirectiveTemplate), directive); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeDirectiveDefinition), directive); Assert.AreEqual(1, options.RuntimeTemplates.Count()); Assert.IsNotNull(options.RuntimeTemplates.FirstOrDefault(x => x == directive)); @@ -63,7 +63,7 @@ public void MapDirective_ByOptions_WithResolver_AddsDirectiveToOptions() var options = new SchemaOptions(services); var directive = options.MapDirective("@myDirective", (string a) => 1); - Assert.IsInstanceOf(typeof(IGraphQLRuntimeDirectiveTemplate), directive); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeDirectiveDefinition), directive); Assert.AreEqual(1, options.RuntimeTemplates.Count()); Assert.IsNotNull(options.RuntimeTemplates.FirstOrDefault(x => x == directive)); @@ -82,7 +82,7 @@ public void MapDirective_ByBuilder_WithResolver_AddsDirectiveToOptions() builderMock.Setup(x => x.Options).Returns(options); var directive = builderMock.Object.MapDirective("@myDirective", (string a) => 1); - Assert.IsInstanceOf(typeof(IGraphQLRuntimeDirectiveTemplate), directive); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeDirectiveDefinition), directive); Assert.AreEqual(1, options.RuntimeTemplates.Count()); Assert.IsNotNull(options.RuntimeTemplates.FirstOrDefault(x => x == directive)); diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedMutationTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedMutationTemplateTests.cs index bc03fa3aa..075b5166b 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedMutationTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedMutationTemplateTests.cs @@ -37,7 +37,7 @@ public void MapMutation_FromSchemaOptions_WithNoDelegate_DoesNotAddFieldToSchema Assert.IsNotNull(field); Assert.AreEqual(SchemaItemCollections.Mutation, field.CreatePath().RootCollection); - Assert.IsInstanceOf(typeof(IGraphQLFieldTemplate), field); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeFieldDefinition), field); Assert.AreEqual(0, options.RuntimeTemplates.Count()); } @@ -51,7 +51,7 @@ public void MapMutation_FromSchemaOptions_WithDelegate_DoesAddFieldToSchema() Assert.IsNotNull(field); Assert.AreEqual(SchemaItemCollections.Mutation, field.CreatePath().RootCollection); - Assert.IsInstanceOf(typeof(IGraphQLRuntimeResolvedFieldTemplate), field); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeResolvedFieldDefinition), field); Assert.AreEqual(1, options.RuntimeTemplates.Count()); } @@ -68,7 +68,7 @@ public void MapMutation_FromBuilder_WithNoDelegate_DoesNotAddFieldToSchema() Assert.IsNotNull(field); Assert.AreEqual(SchemaItemCollections.Mutation, field.CreatePath().RootCollection); - Assert.IsInstanceOf(typeof(IGraphQLFieldTemplate), field); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeFieldDefinition), field); Assert.AreEqual(0, options.RuntimeTemplates.Count()); } @@ -85,7 +85,7 @@ public void MapMutation_FromBuilder_WithDelegate_DoesAddFieldToSchema() Assert.IsNotNull(field); Assert.AreEqual(SchemaItemCollections.Mutation, field.CreatePath().RootCollection); - Assert.IsInstanceOf(typeof(IGraphQLRuntimeResolvedFieldTemplate), field); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeResolvedFieldDefinition), field); Assert.AreEqual(1, options.RuntimeTemplates.Count()); } } diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedQueryTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedQueryTemplateTests.cs index 8be379ff4..62280cf4d 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedQueryTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedQueryTemplateTests.cs @@ -38,7 +38,7 @@ public void MapQuery_FromSchemaOptions_WithNoDelegate_DoesNotAddFieldToSchema() Assert.IsNotNull(field); Assert.AreEqual(SchemaItemCollections.Query, field.CreatePath().RootCollection); - Assert.IsInstanceOf(typeof(IGraphQLFieldTemplate), field); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeFieldDefinition), field); Assert.AreEqual(0, options.RuntimeTemplates.Count()); } @@ -52,7 +52,7 @@ public void MapQuery_FromSchemaOptions_WithDelegate_DoesAddFieldToSchema() Assert.IsNotNull(field); Assert.AreEqual(SchemaItemCollections.Query, field.CreatePath().RootCollection); - Assert.IsInstanceOf(typeof(IGraphQLRuntimeResolvedFieldTemplate), field); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeResolvedFieldDefinition), field); Assert.AreEqual(1, options.RuntimeTemplates.Count()); } @@ -69,7 +69,7 @@ public void MapQuery_FromBuilder_WithNoDelegate_DoesNotAddFieldToSchema() Assert.IsNotNull(field); Assert.AreEqual(SchemaItemCollections.Query, field.CreatePath().RootCollection); - Assert.IsInstanceOf(typeof(IGraphQLFieldTemplate), field); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeFieldDefinition), field); Assert.AreEqual(0, options.RuntimeTemplates.Count()); } @@ -87,7 +87,7 @@ public void MapQuery_FromBuilder_WithDelegate_DoesAddFieldToSchema() Assert.IsNotNull(field); Assert.AreEqual(SchemaItemCollections.Query, field.CreatePath().RootCollection); - Assert.IsInstanceOf(typeof(IGraphQLRuntimeResolvedFieldTemplate), field); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeResolvedFieldDefinition), field); Assert.AreEqual(1, options.RuntimeTemplates.Count()); } } diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedTypeExtensionTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedTypeExtensionTemplateTests.cs index de4a7fea5..c2f2b46af 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedTypeExtensionTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedTypeExtensionTemplateTests.cs @@ -32,7 +32,7 @@ public void MapTypeExtension_ByOptions_AddsTypeExtensionToOptions() var options = new SchemaOptions(services); var typeExt = options.MapField("myField"); - Assert.IsInstanceOf(typeof(IGraphQLRuntimeTypeExtensionTemplate), typeExt); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeTypeExtensionDefinition), typeExt); Assert.AreEqual(1, options.RuntimeTemplates.Count()); Assert.IsNotNull(options.RuntimeTemplates.FirstOrDefault(x => x == typeExt)); @@ -52,7 +52,7 @@ public void MapTypeExtension_ByBuilder_AddsTypeExtensionToOptions() builderMock.Setup(x => x.Options).Returns(options); var typeExt = options.MapField("myField"); - Assert.IsInstanceOf(typeof(IGraphQLRuntimeTypeExtensionTemplate), typeExt); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeTypeExtensionDefinition), typeExt); Assert.AreEqual(1, options.RuntimeTemplates.Count()); Assert.IsNotNull(options.RuntimeTemplates.FirstOrDefault(x => x == typeExt)); @@ -66,7 +66,7 @@ public void MapTypeExtension_ByOptions_WithResolver_AddsTypeExtensionToOptions() var options = new SchemaOptions(services); var typeExt = options.MapField("myField", (string a) => 1); - Assert.IsInstanceOf(typeof(IGraphQLRuntimeTypeExtensionTemplate), typeExt); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeTypeExtensionDefinition), typeExt); Assert.AreEqual(1, options.RuntimeTemplates.Count()); Assert.IsNotNull(options.RuntimeTemplates.FirstOrDefault(x => x == typeExt)); @@ -85,7 +85,7 @@ public void MapTypeExtension_ByBuilder_WithResolver_AddsTypeExtensionToOptions() builderMock.Setup(x => x.Options).Returns(options); var typeExt = options.MapField("myField", (string a) => 1); - Assert.IsInstanceOf(typeof(IGraphQLRuntimeTypeExtensionTemplate), typeExt); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeTypeExtensionDefinition), typeExt); Assert.AreEqual(1, options.RuntimeTemplates.Count()); Assert.IsNotNull(options.RuntimeTemplates.FirstOrDefault(x => x == typeExt)); diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/UnresolvedFieldTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/UnresolvedFieldTemplateTests.cs index eca710b4e..a34b4ad11 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/UnresolvedFieldTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/UnresolvedFieldTemplateTests.cs @@ -59,11 +59,11 @@ public void UnresolvedField_WhenResolverAdded_BecomesResolvedField() var field = options.MapQuery("/path1/path2"); - Assert.IsInstanceOf(typeof(IGraphQLFieldTemplate), field); - Assert.IsNotInstanceOf(typeof(IGraphQLRuntimeResolvedFieldTemplate), field); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeFieldDefinition), field); + Assert.IsNotInstanceOf(typeof(IGraphQLRuntimeResolvedFieldDefinition), field); var field1 = field.AddResolver((string a) => 1); - Assert.IsInstanceOf(typeof(IGraphQLRuntimeResolvedFieldTemplate), field1); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeResolvedFieldDefinition), field1); Assert.IsNull(field1.ReturnType); } @@ -75,11 +75,11 @@ public void UnresolvedField_WhenResolverAddedWithSpecificType_BecomesResolvedFie var field = options.MapQuery("/path1/path2"); - Assert.IsInstanceOf(typeof(IGraphQLFieldTemplate), field); - Assert.IsNotInstanceOf(typeof(IGraphQLRuntimeResolvedFieldTemplate), field); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeFieldDefinition), field); + Assert.IsNotInstanceOf(typeof(IGraphQLRuntimeResolvedFieldDefinition), field); var field1 = field.AddResolver((string a) => 1); - Assert.IsInstanceOf(typeof(IGraphQLRuntimeResolvedFieldTemplate), field1); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeResolvedFieldDefinition), field1); Assert.AreEqual(typeof(decimal), field1.ReturnType); } From 80de6cde63105035c26b59d8ab95c2440cb7b254 Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Mon, 19 Jun 2023 09:03:32 -0700 Subject: [PATCH 09/63] WIP, converted top level data into attributitons --- ...hemaItemDefinitionExtensions_Directives.cs | 32 ++--- ...chemaItemDefinitionExtensions_Internals.cs | 16 ++- ...ItemDefinitionExtensions_ResolvedFields.cs | 6 +- ...ItemDefinitionExtensions_TypeExtensions.cs | 6 +- ...aItemDefinitionExtensions_VirtualFields.cs | 4 +- ...raphQLRuntimeDirectiveActionDefinition.cs} | 2 +- .../IGraphQLRuntimeSchemaItemDefinition.cs | 18 ++- .../BaseRuntimeControllerActionDefinition.cs | 126 ++++++++++++++++++ .../BaseRuntimeSchemaItemDefinition.cs | 95 ------------- ...cs => RuntimeDirectiveActionDefinition.cs} | 17 ++- .../RuntimeResolvedFieldDefinition.cs | 53 ++++++-- ...n.cs => RuntimeTypeExtensionDefinition.cs} | 35 ++++- .../RuntimeVirtualFieldTemplate.cs | 31 +++-- .../Schemas/Structural/SchemaItemPath.cs | 19 ++- .../Templates/MappedDirectiveTemplateTests.cs | 20 +-- .../Templates/MappedMutationTemplateTests.cs | 23 +++- .../Templates/MappedQueryTemplateTests.cs | 21 ++- .../MappedTypeExtensionTemplateTests.cs | 18 ++- .../Templates/ResolvedFieldTemplateTests.cs | 15 ++- .../Templates/UnresolvedFieldTemplateTests.cs | 16 +-- .../Controllers/SchemaItemPathTests.cs | 23 +++- 21 files changed, 388 insertions(+), 208 deletions(-) rename src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/{IGraphQLRuntimeDirectiveDefinition.cs => IGraphQLRuntimeDirectiveActionDefinition.cs} (80%) create mode 100644 src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/BaseRuntimeControllerActionDefinition.cs delete mode 100644 src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/BaseRuntimeSchemaItemDefinition.cs rename src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/{RuntimeDirectiveDefinition.cs => RuntimeDirectiveActionDefinition.cs} (68%) rename src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/{RuntimeTypeExtensionFieldDefinition.cs => RuntimeTypeExtensionDefinition.cs} (56%) diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Directives.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Directives.cs index 7a54431bf..67df2f90c 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Directives.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Directives.cs @@ -33,8 +33,8 @@ public static partial class GraphQLRuntimeSchemaItemDefinitionExtensions /// The name of the policy to assign via this requirement. /// A comma-seperated list of roles to assign via this requirement. /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeDirectiveDefinition RequireAuthorization( - this IGraphQLRuntimeDirectiveDefinition directiveTemplate, + public static IGraphQLRuntimeDirectiveActionDefinition RequireAuthorization( + this IGraphQLRuntimeDirectiveActionDefinition directiveTemplate, string policyName = null, string roles = null) { @@ -43,7 +43,7 @@ public static IGraphQLRuntimeDirectiveDefinition RequireAuthorization( var attrib = new AuthorizeAttribute(); attrib.Policy = policyName?.Trim(); attrib.Roles = roles?.Trim(); - directiveTemplate.Attributes.Add(attrib); + directiveTemplate.AddAttribute(attrib); return directiveTemplate; } @@ -61,10 +61,10 @@ public static IGraphQLRuntimeDirectiveDefinition RequireAuthorization( /// /// The directive being built. /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeDirectiveDefinition AllowAnonymous(this IGraphQLRuntimeDirectiveDefinition directiveTemplate) + public static IGraphQLRuntimeDirectiveActionDefinition AllowAnonymous(this IGraphQLRuntimeDirectiveActionDefinition directiveTemplate) { Validation.ThrowIfNull(directiveTemplate, nameof(directiveTemplate)); - directiveTemplate.Attributes.Add(new AllowAnonymousAttribute()); + directiveTemplate.AddAttribute(new AllowAnonymousAttribute()); return directiveTemplate; } @@ -74,10 +74,10 @@ public static IGraphQLRuntimeDirectiveDefinition AllowAnonymous(this IGraphQLRun /// /// The directive template. /// IGraphQLDirectiveTemplate. - public static IGraphQLRuntimeDirectiveDefinition IsRepeatable(this IGraphQLRuntimeDirectiveDefinition directiveTemplate) + public static IGraphQLRuntimeDirectiveActionDefinition IsRepeatable(this IGraphQLRuntimeDirectiveActionDefinition directiveTemplate) { var repeatable = new RepeatableAttribute(); - directiveTemplate.Attributes.Add(repeatable); + directiveTemplate.AddAttribute(repeatable); return directiveTemplate; } @@ -92,12 +92,12 @@ public static IGraphQLRuntimeDirectiveDefinition IsRepeatable(this IGraphQLRunti /// The bitwise set of locations where this /// directive can be applied. /// IGraphQLDirectiveTemplate. - public static IGraphQLRuntimeDirectiveDefinition RestrictLocations( - this IGraphQLRuntimeDirectiveDefinition directiveTemplate, + public static IGraphQLRuntimeDirectiveActionDefinition RestrictLocations( + this IGraphQLRuntimeDirectiveActionDefinition directiveTemplate, DirectiveLocation locations) { var restrictions = new DirectiveLocationsAttribute(locations); - directiveTemplate.Attributes.Add(restrictions); + directiveTemplate.AddAttribute(restrictions); return directiveTemplate; } @@ -117,7 +117,7 @@ public static IGraphQLRuntimeDirectiveDefinition RestrictLocations( /// The delegate to assign as the resolver. This method will be /// parsed to determine input arguments for the field on the target schema. /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeDirectiveDefinition AddResolver(this IGraphQLRuntimeDirectiveDefinition directiveTemplate, Delegate resolverMethod) + public static IGraphQLRuntimeDirectiveActionDefinition AddResolver(this IGraphQLRuntimeDirectiveActionDefinition directiveTemplate, Delegate resolverMethod) { directiveTemplate.Resolver = resolverMethod; directiveTemplate.ReturnType = null; @@ -137,7 +137,7 @@ public static IGraphQLRuntimeDirectiveDefinition AddResolver(this IGraphQLRuntim /// The delegate to assign as the resolver. This method will be /// parsed to determine input arguments for the directive on the target schema. /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeDirectiveDefinition AddResolver(this IGraphQLRuntimeDirectiveDefinition directiveTemplate, Delegate resolverMethod) + public static IGraphQLRuntimeDirectiveActionDefinition AddResolver(this IGraphQLRuntimeDirectiveActionDefinition directiveTemplate, Delegate resolverMethod) { directiveTemplate.Resolver = resolverMethod; directiveTemplate.ReturnType = typeof(TReturnType); @@ -150,7 +150,7 @@ public static IGraphQLRuntimeDirectiveDefinition AddResolver(this I /// The schema options where the directive will be created. /// Name of the directive (e.g. '@myDirective'). /// IGraphQLDirectiveTemplate. - public static IGraphQLRuntimeDirectiveDefinition MapDirective(this SchemaOptions schemaOptions, string directiveName) + public static IGraphQLRuntimeDirectiveActionDefinition MapDirective(this SchemaOptions schemaOptions, string directiveName) { return MapDirectiveInternal(schemaOptions, directiveName); } @@ -162,7 +162,7 @@ public static IGraphQLRuntimeDirectiveDefinition MapDirective(this SchemaOptions /// Name of the directive (e.g. '@myDirective'). /// The resolver that will be executed when the directive is invoked. /// IGraphQLDirectiveTemplate. - public static IGraphQLRuntimeDirectiveDefinition MapDirective(this SchemaOptions schemaOptions, string directiveName, Delegate resolverMethod) + public static IGraphQLRuntimeDirectiveActionDefinition MapDirective(this SchemaOptions schemaOptions, string directiveName, Delegate resolverMethod) { Validation.ThrowIfNull(resolverMethod, nameof(resolverMethod)); @@ -176,7 +176,7 @@ public static IGraphQLRuntimeDirectiveDefinition MapDirective(this SchemaOptions /// The builder representing the schema being constructed. /// Name of the directive (e.g. '@myDirective'). /// IGraphQLDirectiveTemplate. - public static IGraphQLRuntimeDirectiveDefinition MapDirective(this ISchemaBuilder schemaBuilder, string directiveName) + public static IGraphQLRuntimeDirectiveActionDefinition MapDirective(this ISchemaBuilder schemaBuilder, string directiveName) { Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); @@ -194,7 +194,7 @@ public static IGraphQLRuntimeDirectiveDefinition MapDirective(this ISchemaBuilde /// Name of the directive (e.g. '@myDirective'). /// The resolver that will be executed when the directive is invoked. /// IGraphQLDirectiveTemplate. - public static IGraphQLRuntimeDirectiveDefinition MapDirective(this ISchemaBuilder schemaBuilder, string directiveName, Delegate resolverMethod) + public static IGraphQLRuntimeDirectiveActionDefinition MapDirective(this ISchemaBuilder schemaBuilder, string directiveName, Delegate resolverMethod) { Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); Validation.ThrowIfNull(resolverMethod, nameof(resolverMethod)); diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Internals.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Internals.cs index d9400dd4f..6d4b35584 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Internals.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Internals.cs @@ -13,6 +13,8 @@ namespace GraphQL.AspNet.Configuration using GraphQL.AspNet.Common; using GraphQL.AspNet.Configuration.Templates; using GraphQL.AspNet.Execution; + using GraphQL.AspNet.Execution.Parsing; + using GraphQL.AspNet.Execution.Parsing.Lexing.Tokens; using GraphQL.AspNet.Interfaces.Configuration.Templates; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; @@ -30,11 +32,10 @@ private static IGraphQLRuntimeFieldDefinition MapGraphQLFieldInternal( schemaOptions = Validation.ThrowIfNullOrReturn(schemaOptions, nameof(schemaOptions)); pathTemplate = Validation.ThrowIfNullWhiteSpaceOrReturn(pathTemplate, nameof(pathTemplate)); - var path = new SchemaItemPath((SchemaItemCollections)operationType, pathTemplate); - var fieldTemplate = new RuntimeVirtualFieldTemplate( schemaOptions, - path.Path); + (SchemaItemCollections)operationType, + pathTemplate); return fieldTemplate; } @@ -48,7 +49,7 @@ private static IGraphQLRuntimeTypeExtensionDefinition MapTypeExtensionInternal( schemaOptions = Validation.ThrowIfNullOrReturn(schemaOptions, nameof(schemaOptions)); fieldName = Validation.ThrowIfNullWhiteSpaceOrReturn(fieldName, nameof(fieldName)); - IGraphQLRuntimeTypeExtensionDefinition field = new RuntimeTypeExtensionFieldDefinition( + IGraphQLRuntimeTypeExtensionDefinition field = new RuntimeTypeExtensionDefinition( schemaOptions, typeToExtend, fieldName, @@ -58,9 +59,12 @@ private static IGraphQLRuntimeTypeExtensionDefinition MapTypeExtensionInternal( return field; } - private static IGraphQLRuntimeDirectiveDefinition MapDirectiveInternal(this SchemaOptions schemaOptions, string directiveName) + private static IGraphQLRuntimeDirectiveActionDefinition MapDirectiveInternal(this SchemaOptions schemaOptions, string directiveName) { - var directive = new RuntimeDirectiveDefinition(schemaOptions, directiveName); + while (directiveName != null && directiveName.StartsWith(TokenTypeNames.STRING_AT_SYMBOL)) + directiveName = directiveName.Substring(1); + + var directive = new RuntimeDirectiveActionDefinition(schemaOptions, directiveName); schemaOptions.AddSchemaItemTemplate(directive); return directive; diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_ResolvedFields.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_ResolvedFields.cs index d29519ae1..13abff5b8 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_ResolvedFields.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_ResolvedFields.cs @@ -41,7 +41,7 @@ public static IGraphQLRuntimeResolvedFieldDefinition RequireAuthorization( var attrib = new AuthorizeAttribute(); attrib.Policy = policyName?.Trim(); attrib.Roles = roles?.Trim(); - fieldBuilder.Attributes.Add(attrib); + fieldBuilder.AddAttribute(attrib); return fieldBuilder; } @@ -56,7 +56,7 @@ public static IGraphQLRuntimeResolvedFieldDefinition RequireAuthorization( public static IGraphQLRuntimeResolvedFieldDefinition AllowAnonymous(this IGraphQLRuntimeResolvedFieldDefinition fieldBuilder) { Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); - fieldBuilder.Attributes.Add(new AllowAnonymousAttribute()); + fieldBuilder.AddAttribute(new AllowAnonymousAttribute()); return fieldBuilder; } @@ -113,7 +113,7 @@ public static IGraphQLRuntimeResolvedFieldDefinition AddResolver(th public static IGraphQLRuntimeResolvedFieldDefinition AddPossibleTypes(this IGraphQLRuntimeResolvedFieldDefinition fieldBuilder, Type firstPossibleType, params Type[] additionalPossibleTypes) { var possibleTypes = new PossibleTypesAttribute(firstPossibleType, additionalPossibleTypes); - fieldBuilder.Attributes.Add(possibleTypes); + fieldBuilder.AddAttribute(possibleTypes); return fieldBuilder; } } diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_TypeExtensions.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_TypeExtensions.cs index 2f68fdd67..ecf6e844b 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_TypeExtensions.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_TypeExtensions.cs @@ -43,7 +43,7 @@ public static IGraphQLRuntimeTypeExtensionDefinition RequireAuthorization( var attrib = new AuthorizeAttribute(); attrib.Policy = policyName?.Trim(); attrib.Roles = roles?.Trim(); - fieldBuilder.Attributes.Add(attrib); + fieldBuilder.AddAttribute(attrib); return fieldBuilder; } @@ -58,7 +58,7 @@ public static IGraphQLRuntimeTypeExtensionDefinition RequireAuthorization( public static IGraphQLRuntimeTypeExtensionDefinition AllowAnonymous(this IGraphQLRuntimeTypeExtensionDefinition fieldBuilder) { Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); - fieldBuilder.Attributes.Add(new AllowAnonymousAttribute()); + fieldBuilder.AddAttribute(new AllowAnonymousAttribute()); return fieldBuilder; } @@ -185,7 +185,7 @@ public static IGraphQLRuntimeTypeExtensionDefinition WithBatchProcessing(this IG public static IGraphQLRuntimeTypeExtensionDefinition AddPossibleTypes(this IGraphQLRuntimeTypeExtensionDefinition fieldBuilder, Type firstPossibleType, params Type[] additionalPossibleTypes) { var possibleTypes = new PossibleTypesAttribute(firstPossibleType, additionalPossibleTypes); - fieldBuilder.Attributes.Add(possibleTypes); + fieldBuilder.AddAttribute(possibleTypes); return fieldBuilder; } } diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_VirtualFields.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_VirtualFields.cs index 0ee83e17d..3ed7ea461 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_VirtualFields.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_VirtualFields.cs @@ -41,7 +41,7 @@ public static IGraphQLRuntimeFieldDefinition RequireAuthorization( var attrib = new AuthorizeAttribute(); attrib.Policy = policyName?.Trim(); attrib.Roles = roles?.Trim(); - fieldBuilder.Attributes.Add(attrib); + fieldBuilder.AddAttribute(attrib); return fieldBuilder; } @@ -62,7 +62,7 @@ public static IGraphQLRuntimeFieldDefinition RequireAuthorization( public static IGraphQLRuntimeFieldDefinition AllowAnonymous(this IGraphQLRuntimeFieldDefinition fieldBuilder) { Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); - fieldBuilder.Attributes.Add(new AllowAnonymousAttribute()); + fieldBuilder.AddAttribute(new AllowAnonymousAttribute()); return fieldBuilder; } diff --git a/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeDirectiveDefinition.cs b/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeDirectiveActionDefinition.cs similarity index 80% rename from src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeDirectiveDefinition.cs rename to src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeDirectiveActionDefinition.cs index 40be8f1b0..45d09efa9 100644 --- a/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeDirectiveDefinition.cs +++ b/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeDirectiveActionDefinition.cs @@ -13,7 +13,7 @@ namespace GraphQL.AspNet.Interfaces.Configuration.Templates /// An intermediate template that utilizies a key/value pair system to build up a set of component parts /// that the templating engine will use to generate a full fledged field in a schema. /// - public interface IGraphQLRuntimeDirectiveDefinition : IGraphQLRuntimeSchemaItemDefinition, IGraphQLResolvableSchemaItemDefinition + public interface IGraphQLRuntimeDirectiveActionDefinition : IGraphQLRuntimeSchemaItemDefinition, IGraphQLResolvableSchemaItemDefinition { } } \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeSchemaItemDefinition.cs b/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeSchemaItemDefinition.cs index 683ba6040..cf623e03a 100644 --- a/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeSchemaItemDefinition.cs +++ b/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeSchemaItemDefinition.cs @@ -18,22 +18,20 @@ namespace GraphQL.AspNet.Interfaces.Configuration.Templates /// A marker templtae for any runtime-built schema item (field, directive etc.) /// being added to the schema. /// - public interface IGraphQLRuntimeSchemaItemDefinition : IDictionary + public interface IGraphQLRuntimeSchemaItemDefinition { /// - /// Creates a path object using the current template path assigned to this template. This - /// path object is not guarunteed to be the final path when the template is rendered into - /// a schema. + /// Adds the given attribute to the collection for this schema item. /// - /// SchemaItemPath. - SchemaItemPath CreatePath(); + /// The attribute to append. + void AddAttribute(Attribute attrib); /// /// Gets the templated name that will be given to the item on the target schema. /// /// The fully qualified template for this item. - /// (e.g. '@myDirective', '/path1/path2'). - string Template { get; } + /// (e.g. '[directive]/@myDirective', '[query]/path1/path2'). + SchemaItemPath Route { get; } /// /// Gets the set of schema options under which this directive is being defined. @@ -42,10 +40,10 @@ public interface IGraphQLRuntimeSchemaItemDefinition : IDictionary - /// Gets a list of attributes that have been applied to this directive. This mimics + /// Gets a set of attributes that have been applied to this directive. This mimics /// the collection of applied attributes to a controller method. /// /// The collection of applied attributes. - IList Attributes { get; } + IEnumerable Attributes { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/BaseRuntimeControllerActionDefinition.cs b/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/BaseRuntimeControllerActionDefinition.cs new file mode 100644 index 000000000..10ab11a11 --- /dev/null +++ b/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/BaseRuntimeControllerActionDefinition.cs @@ -0,0 +1,126 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Configuration.Templates +{ + using System; + using System.Collections.Generic; + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Execution; + using GraphQL.AspNet.Interfaces.Configuration.Templates; + using GraphQL.AspNet.Schemas.Structural; + + /// + /// An abstract class containing all the common elements across minimal field builders and + /// their supporting classes. + /// + internal abstract class BaseRuntimeControllerActionDefinition : IGraphQLRuntimeSchemaItemDefinition + { + /// + /// Prevents a default instance of the class from being created. + /// + private BaseRuntimeControllerActionDefinition() + { + this.AppendedAttributes = new List(); + } + + /// + /// Initializes a new instance of the class. + /// + /// The schema options where this field item + /// is being defined. + /// The full route to use for this schema item. + protected BaseRuntimeControllerActionDefinition( + SchemaOptions options, + SchemaItemPath route) + : this() + { + this.Options = Validation.ThrowIfNullOrReturn(options, nameof(options)); + this.Route = Validation.ThrowIfNullOrReturn(route, nameof(route)); + } + + /// + /// Initializes a new instance of the class. + /// + /// The schema options where this field item + /// is being defined. + /// The schema collection this item will belong to. + /// The path template identifying this item. + protected BaseRuntimeControllerActionDefinition( + SchemaOptions options, + SchemaItemCollections collection, + string pathTemplate) + : this() + { + this.Options = Validation.ThrowIfNullOrReturn(options, nameof(options)); + pathTemplate = pathTemplate?.Trim() ?? string.Empty; + + this.Route = new SchemaItemPath(collection, pathTemplate); + } + + /// + /// Initializes a new instance of the class. + /// + /// The field from which this entity is being added. + /// The partial path template defined for this + /// individual entity. + protected BaseRuntimeControllerActionDefinition( + IGraphQLRuntimeFieldDefinition parentField, + string partialPathTemplate) + : this() + { + parentField = Validation.ThrowIfNullOrReturn(parentField, nameof(parentField)); + this.Options = Validation.ThrowIfNullOrReturn(parentField?.Options, nameof(parentField.Options)); + + partialPathTemplate = Validation.ThrowIfNullWhiteSpaceOrReturn(partialPathTemplate, nameof(partialPathTemplate)); + + this.Route = parentField.Route.CreateChild(partialPathTemplate); + } + + /// + public virtual void AddAttribute(Attribute attrib) + { + Validation.ThrowIfNull(attrib, nameof(attrib)); + this.AppendedAttributes.Add(attrib); + } + + /// + /// Creates the primary attribute that would identify this + /// + /// Attribute. + protected abstract Attribute CreatePrimaryAttribute(); + + /// + public virtual SchemaOptions Options { get; protected set; } + + /// + public IEnumerable Attributes + { + get + { + var topAttrib = this.CreatePrimaryAttribute(); + if (topAttrib != null) + yield return topAttrib; + + foreach (var attrib in this.AppendedAttributes) + yield return attrib; + } + } + + /// + /// Gets a list of attributes that were directly appended to this instance. + /// + /// The appended attributes. + protected IList AppendedAttributes { get; } + + /// + public SchemaItemPath Route { get; protected set; } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/BaseRuntimeSchemaItemDefinition.cs b/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/BaseRuntimeSchemaItemDefinition.cs deleted file mode 100644 index 76ba5adb4..000000000 --- a/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/BaseRuntimeSchemaItemDefinition.cs +++ /dev/null @@ -1,95 +0,0 @@ -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - -namespace GraphQL.AspNet.Configuration.Templates -{ - using System; - using System.Collections.Generic; - using GraphQL.AspNet.Common; - using GraphQL.AspNet.Configuration; - using GraphQL.AspNet.Interfaces.Configuration.Templates; - using GraphQL.AspNet.Schemas.Structural; - - /// - /// An abstract class containing all the common elements across minimal field builders and - /// their supporting classes. - /// - internal abstract class BaseRuntimeSchemaItemDefinition : Dictionary, IGraphQLRuntimeSchemaItemDefinition - { - private IGraphQLRuntimeFieldDefinition _parent; - private string _partialPathTemplate; - - /// - /// Prevents a default instance of the class from being created. - /// - private BaseRuntimeSchemaItemDefinition() - { - this.Attributes = new List(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The schema options where this field item - /// is being defined. - /// The partial path template defined for this - /// individual entity. - protected BaseRuntimeSchemaItemDefinition( - SchemaOptions options, - string partialPathTemplate) - : this() - { - _parent = null; - this.Options = Validation.ThrowIfNullOrReturn(options, nameof(options)); - - _partialPathTemplate = partialPathTemplate?.Trim() ?? string.Empty; - } - - /// - /// Initializes a new instance of the class. - /// - /// The group builder from which this entity is being created. - /// The partial path template defined for this - /// individual entity. - protected BaseRuntimeSchemaItemDefinition( - IGraphQLRuntimeFieldDefinition parentVirtualFieldBuilder, - string partialPathTemplate) - : this() - { - _parent = Validation.ThrowIfNullOrReturn(parentVirtualFieldBuilder, nameof(parentVirtualFieldBuilder)); - this.Options = Validation.ThrowIfNullOrReturn(parentVirtualFieldBuilder?.Options, nameof(parentVirtualFieldBuilder.Options)); - - _partialPathTemplate = Validation.ThrowIfNullWhiteSpaceOrReturn(partialPathTemplate, nameof(partialPathTemplate)); - } - - /// - public SchemaItemPath CreatePath() - { - return new SchemaItemPath(this.Template); - } - - /// - public virtual SchemaOptions Options { get; protected set; } - - /// - public IList Attributes { get; } - - /// - public string Template - { - get - { - if (_parent != null) - return SchemaItemPath.Join(_parent.Template, _partialPathTemplate); - - return _partialPathTemplate; - } - } - } -} \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeDirectiveDefinition.cs b/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeDirectiveActionDefinition.cs similarity index 68% rename from src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeDirectiveDefinition.cs rename to src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeDirectiveActionDefinition.cs index 5f817fdd9..40c5eb404 100644 --- a/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeDirectiveDefinition.cs +++ b/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeDirectiveActionDefinition.cs @@ -12,25 +12,32 @@ namespace GraphQL.AspNet.Configuration.Templates using System; using System.Diagnostics; using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Execution; using GraphQL.AspNet.Interfaces.Configuration.Templates; /// - /// An internal implementation of the + /// An internal implementation of the /// used to generate new graphql directives via a minimal api style of coding. /// [DebuggerDisplay("{Template}")] - internal class RuntimeDirectiveDefinition : BaseRuntimeSchemaItemDefinition, IGraphQLRuntimeDirectiveDefinition + internal class RuntimeDirectiveActionDefinition : BaseRuntimeControllerActionDefinition, IGraphQLRuntimeDirectiveActionDefinition { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The schema options where this directive will be created. /// Name of the directive to use in the schema. - public RuntimeDirectiveDefinition(SchemaOptions schemaOptions, string directiveName) - : base(schemaOptions, directiveName) + public RuntimeDirectiveActionDefinition(SchemaOptions schemaOptions, string directiveName) + : base(schemaOptions, SchemaItemCollections.Directives, directiveName) { } + /// + protected override Attribute CreatePrimaryAttribute() + { + return null; + } + /// public Delegate Resolver { get; set; } diff --git a/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeResolvedFieldDefinition.cs b/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeResolvedFieldDefinition.cs index 77dfe1f81..7097cf01e 100644 --- a/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeResolvedFieldDefinition.cs +++ b/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeResolvedFieldDefinition.cs @@ -11,16 +11,20 @@ namespace GraphQL.AspNet.Configuration.Templates { using System; using System.Diagnostics; + using System.Linq; + using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Common; using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Execution; using GraphQL.AspNet.Interfaces.Configuration.Templates; + using GraphQL.AspNet.Schemas.Structural; /// /// An internal implementation of the /// used to generate new graphql fields via a minimal api style of coding. /// [DebuggerDisplay("{Template}")] - internal class RuntimeResolvedFieldDefinition : BaseRuntimeSchemaItemDefinition, IGraphQLRuntimeResolvedFieldDefinition + internal class RuntimeResolvedFieldDefinition : BaseRuntimeControllerActionDefinition, IGraphQLRuntimeResolvedFieldDefinition { /// /// Converts the unresolved field into a resolved field. The newly generated field @@ -31,26 +35,39 @@ internal class RuntimeResolvedFieldDefinition : BaseRuntimeSchemaItemDefinition, public static IGraphQLRuntimeResolvedFieldDefinition FromFieldTemplate(IGraphQLRuntimeFieldDefinition fieldTemplate) { Validation.ThrowIfNull(fieldTemplate, nameof(fieldTemplate)); - var field = new RuntimeResolvedFieldDefinition(fieldTemplate.Options, fieldTemplate.Template); + var field = new RuntimeResolvedFieldDefinition( + fieldTemplate.Options, + fieldTemplate.Route); foreach (var attrib in fieldTemplate.Attributes) - field.Attributes.Add(attrib); - - foreach (var kvp in fieldTemplate) - field.Add(kvp.Key, kvp.Value); + field.AddAttribute(attrib); return field; } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The schema options to which this field is being added. - /// The full path template describing where the field will live. + /// The full route to use for this item. + private RuntimeResolvedFieldDefinition( + SchemaOptions schemaOptions, + SchemaItemPath route) + : base(schemaOptions, route) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The schema options to which this field is being added. + /// The schema collection this item will belong to. + /// The path template identifying this item. public RuntimeResolvedFieldDefinition( SchemaOptions schemaOptions, - string fullPathTemplate) - : base(schemaOptions, fullPathTemplate) + SchemaItemCollections collection, + string pathTemplate) + : base(schemaOptions, collection, pathTemplate) { } @@ -67,6 +84,22 @@ public RuntimeResolvedFieldDefinition( { } + /// + protected override Attribute CreatePrimaryAttribute() + { + var (collection, path) = this.Route; + switch (collection) + { + case SchemaItemCollections.Query: + return new QueryRootAttribute(path, this.ReturnType); + + case SchemaItemCollections.Mutation: + return new MutationRootAttribute(path, this.ReturnType); + } + + return null; + } + /// public Delegate Resolver { get; set; } diff --git a/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeTypeExtensionFieldDefinition.cs b/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeTypeExtensionDefinition.cs similarity index 56% rename from src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeTypeExtensionFieldDefinition.cs rename to src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeTypeExtensionDefinition.cs index 07170a5c4..714d1db38 100644 --- a/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeTypeExtensionFieldDefinition.cs +++ b/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeTypeExtensionDefinition.cs @@ -11,36 +11,63 @@ namespace GraphQL.AspNet.Configuration.Templates { using System; using System.Diagnostics; + using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Execution; using GraphQL.AspNet.Interfaces.Configuration.Templates; + using GraphQL.AspNet.Internal; + using GraphQL.AspNet.Schemas.Structural; + using GraphQL.AspNet.Schemas.TypeSystem; /// /// An internal implementation of the /// used to generate new type extensions via a minimal api style of coding. /// [DebuggerDisplay("{Template}")] - internal class RuntimeTypeExtensionFieldDefinition : RuntimeResolvedFieldDefinition, IGraphQLRuntimeTypeExtensionDefinition + internal class RuntimeTypeExtensionDefinition : RuntimeResolvedFieldDefinition, IGraphQLRuntimeTypeExtensionDefinition { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The schema options where this type extension is being declared. /// The target OBJECT or INTERFACE type to extend. /// Name of the field to add to the . /// The resolution mode for the resolver implemented by this /// type extension. - public RuntimeTypeExtensionFieldDefinition( + public RuntimeTypeExtensionDefinition( SchemaOptions schemaOptions, Type typeToExtend, string fieldName, FieldResolutionMode resolutionMode) - : base(schemaOptions, fieldName) + : base( + schemaOptions, + SchemaItemCollections.Types, + SchemaItemPath.Join( + GraphTypeNames.ParseName(typeToExtend, TypeKind.OBJECT), + fieldName)) { this.ExecutionMode = resolutionMode; this.TargetType = typeToExtend; } + /// + protected override Attribute CreatePrimaryAttribute() + { + switch (this.ExecutionMode) + { + case FieldResolutionMode.PerSourceItem: + return new TypeExtensionAttribute(this.TargetType, this.Route.Name, this.ReturnType); + + case FieldResolutionMode.Batch: + return new BatchTypeExtensionAttribute(this.TargetType, this.Route.Name, this.ReturnType); + + default: + throw new NotSupportedException( + $"Unknown {nameof(FieldResolutionMode)}. cannot render " + + $"primary type extension attribute."); + } + } + /// public FieldResolutionMode ExecutionMode { get; set; } diff --git a/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeVirtualFieldTemplate.cs b/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeVirtualFieldTemplate.cs index 9f7302322..bc8c1459f 100644 --- a/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeVirtualFieldTemplate.cs +++ b/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeVirtualFieldTemplate.cs @@ -9,8 +9,10 @@ namespace GraphQL.AspNet.Configuration.Templates { + using System; using System.Diagnostics; using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Execution; using GraphQL.AspNet.Interfaces.Configuration.Templates; /// @@ -18,32 +20,39 @@ namespace GraphQL.AspNet.Configuration.Templates /// used to generate new graphql fields via a minimal api style of coding. /// [DebuggerDisplay("{Template}")] - internal class RuntimeVirtualFieldTemplate : BaseRuntimeSchemaItemDefinition, IGraphQLRuntimeFieldDefinition + internal class RuntimeVirtualFieldTemplate : BaseRuntimeControllerActionDefinition, IGraphQLRuntimeFieldDefinition { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The schema options that will own the fields created from /// this builder. - /// The partial field path template - /// that will be prepended to any fields or groups created from this builder. + /// The schema collection this item will belong to. + /// The path template identifying this item. public RuntimeVirtualFieldTemplate( SchemaOptions options, - string fieldTemplate) - : base(options, fieldTemplate) + SchemaItemCollections collection, + string pathTemplate) + : base(options, collection, pathTemplate) { } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// The parent virtual field from which - /// this builder will copy its settings. + /// The field from which this entity is being added. /// The partial path template to be appended to /// the parent's already defined template. - public RuntimeVirtualFieldTemplate(IGraphQLRuntimeFieldDefinition parentFieldBuilder, string fieldSubTemplate) - : base(parentFieldBuilder, fieldSubTemplate) + public RuntimeVirtualFieldTemplate( + IGraphQLRuntimeFieldDefinition parentField, string fieldSubTemplate) + : base(parentField, fieldSubTemplate) + { + } + + /// + protected override Attribute CreatePrimaryAttribute() { + return null; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/Structural/SchemaItemPath.cs b/src/graphql-aspnet/Schemas/Structural/SchemaItemPath.cs index c3ce06bc9..8a8c9c4d2 100644 --- a/src/graphql-aspnet/Schemas/Structural/SchemaItemPath.cs +++ b/src/graphql-aspnet/Schemas/Structural/SchemaItemPath.cs @@ -44,6 +44,7 @@ static SchemaItemPath() private bool _pathInitialized; private SchemaItemCollections _rootCollection; private string _path; + private string _pathMinusCollection; private SchemaItemPath _parentField; private string _name; private bool _isTopLevelField; @@ -72,6 +73,7 @@ public SchemaItemPath(string fullPath) _parentField = null; _isTopLevelField = false; _path = string.Empty; + _pathMinusCollection = string.Empty; _name = string.Empty; _isValid = false; _rootCollection = SchemaItemCollections.Unknown; @@ -92,7 +94,6 @@ private void EnsurePathInitialized() // split the path into its fragments List pathFragments = workingPath.Split(new[] { RouteConstants.PATH_SEPERATOR }, StringSplitOptions.None).ToList(); - switch (pathFragments[0]) { case RouteConstants.QUERY_ROOT: @@ -150,6 +151,11 @@ private void EnsurePathInitialized() _isTopLevelField = pathFragments.Count == 1 || (pathFragments.Count == 2 && this.RootCollection > SchemaItemCollections.Unknown); // e.g. "[query]/name" _isValid = this.Name.Length > 0; _path = this.GeneratePathString(pathFragments); + + if (_rootCollection == SchemaItemCollections.Unknown) + _pathMinusCollection = this.GeneratePathString(pathFragments); + else + _pathMinusCollection = $"{RouteConstants.PATH_SEPERATOR}{this.GeneratePathString(pathFragments.Skip(1).ToList())}"; } } @@ -193,6 +199,17 @@ public bool HasChildRoute(SchemaItemPath route) return (route?.Path?.Length ?? 0) > 0 && route.Path.StartsWith(this.Path); } + /// + /// Deconstructs the instance into its constituent parts. + /// + /// The collection this item belongs to. + /// The path within the collection that points to this item. + public void Deconstruct(out SchemaItemCollections collection, out string path) + { + collection = this.RootCollection; + path = _pathMinusCollection; + } + /// /// Gets the raw string provided to this instance. /// diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedDirectiveTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedDirectiveTemplateTests.cs index 12db75f9f..23c6a0267 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedDirectiveTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedDirectiveTemplateTests.cs @@ -31,11 +31,11 @@ public void MapDirective_ByOptions_AddsDirectiveToOptions() var options = new SchemaOptions(services); var directive = options.MapDirective("@myDirective"); - Assert.IsInstanceOf(typeof(IGraphQLRuntimeDirectiveDefinition), directive); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeDirectiveActionDefinition), directive); Assert.AreEqual(1, options.RuntimeTemplates.Count()); Assert.IsNotNull(options.RuntimeTemplates.FirstOrDefault(x => x == directive)); - Assert.AreEqual("@myDirective", directive.Template); + Assert.AreEqual("[directive]/myDirective", directive.Route.Path); Assert.IsNull(directive.ReturnType); Assert.IsNull(directive.Resolver); } @@ -50,7 +50,7 @@ public void MapDirective_ByBuilder_AddsDirectiveToOptions() builderMock.Setup(x => x.Options).Returns(options); var directive = builderMock.Object.MapDirective("@myDirective"); - Assert.IsInstanceOf(typeof(IGraphQLRuntimeDirectiveDefinition), directive); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeDirectiveActionDefinition), directive); Assert.AreEqual(1, options.RuntimeTemplates.Count()); Assert.IsNotNull(options.RuntimeTemplates.FirstOrDefault(x => x == directive)); @@ -63,11 +63,11 @@ public void MapDirective_ByOptions_WithResolver_AddsDirectiveToOptions() var options = new SchemaOptions(services); var directive = options.MapDirective("@myDirective", (string a) => 1); - Assert.IsInstanceOf(typeof(IGraphQLRuntimeDirectiveDefinition), directive); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeDirectiveActionDefinition), directive); Assert.AreEqual(1, options.RuntimeTemplates.Count()); Assert.IsNotNull(options.RuntimeTemplates.FirstOrDefault(x => x == directive)); - Assert.AreEqual("@myDirective", directive.Template); + Assert.AreEqual("[directive]/myDirective", directive.Route.Path); Assert.IsNull(directive.ReturnType); Assert.AreEqual(typeof(int), directive.Resolver.Method.ReturnType); } @@ -82,7 +82,7 @@ public void MapDirective_ByBuilder_WithResolver_AddsDirectiveToOptions() builderMock.Setup(x => x.Options).Returns(options); var directive = builderMock.Object.MapDirective("@myDirective", (string a) => 1); - Assert.IsInstanceOf(typeof(IGraphQLRuntimeDirectiveDefinition), directive); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeDirectiveActionDefinition), directive); Assert.AreEqual(1, options.RuntimeTemplates.Count()); Assert.IsNotNull(options.RuntimeTemplates.FirstOrDefault(x => x == directive)); @@ -100,7 +100,7 @@ public void MappedDirective_WhenAllowAnonymousAdded_AddsAnonymousAttribute() directive.AllowAnonymous(); - Assert.AreEqual(1, directive.Attributes.Count); + Assert.AreEqual(1, directive.Attributes.Count()); Assert.IsNotNull(directive.Attributes.FirstOrDefault(x => x is AllowAnonymousAttribute)); } @@ -114,7 +114,7 @@ public void MappedDirective_WhenRequireAuthAdded_AddsAuthAttribute() directive.RequireAuthorization("policy1", "roles1"); - Assert.AreEqual(1, directive.Attributes.Count); + Assert.AreEqual(1, directive.Attributes.Count()); var attrib = directive.Attributes.FirstOrDefault(x => x is AuthorizeAttribute) as AuthorizeAttribute; Assert.IsNotNull(attrib); Assert.AreEqual("policy1", attrib.Policy); @@ -131,7 +131,7 @@ public void MappedDirective_WhenLocationRestricted_AddsAttribute() directive.RestrictLocations(DirectiveLocation.QUERY | DirectiveLocation.MUTATION); - Assert.AreEqual(1, directive.Attributes.Count); + Assert.AreEqual(1, directive.Attributes.Count()); var attrib = directive.Attributes.FirstOrDefault(x => x is DirectiveLocationsAttribute) as DirectiveLocationsAttribute; Assert.IsNotNull(attrib); Assert.IsTrue(attrib.Locations.HasFlag(DirectiveLocation.QUERY)); @@ -148,7 +148,7 @@ public void MappedDirective_WhenRepeatableAdded_AddsAttribute() directive.IsRepeatable(); - Assert.AreEqual(1, directive.Attributes.Count); + Assert.AreEqual(1, directive.Attributes.Count()); var attrib = directive.Attributes.FirstOrDefault(x => x is RepeatableAttribute) as RepeatableAttribute; Assert.IsNotNull(attrib); } diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedMutationTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedMutationTemplateTests.cs index 075b5166b..708c2f253 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedMutationTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedMutationTemplateTests.cs @@ -10,6 +10,7 @@ namespace GraphQL.AspNet.Tests.Configuration.Templates { using System.Linq; + using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Execution; using GraphQL.AspNet.Interfaces.Configuration; @@ -36,9 +37,12 @@ public void MapMutation_FromSchemaOptions_WithNoDelegate_DoesNotAddFieldToSchema var field = options.MapMutation("/path1/path2"); Assert.IsNotNull(field); - Assert.AreEqual(SchemaItemCollections.Mutation, field.CreatePath().RootCollection); + Assert.AreEqual("[mutation]/path1/path2", field.Route.Path); Assert.IsInstanceOf(typeof(IGraphQLRuntimeFieldDefinition), field); Assert.AreEqual(0, options.RuntimeTemplates.Count()); + + // no top level attribute should be available + Assert.AreEqual(0, field.Attributes.Count()); } [Test] @@ -50,9 +54,13 @@ public void MapMutation_FromSchemaOptions_WithDelegate_DoesAddFieldToSchema() var field = options.MapMutation("/path1/path2", TestDelegate); Assert.IsNotNull(field); - Assert.AreEqual(SchemaItemCollections.Mutation, field.CreatePath().RootCollection); + Assert.AreEqual("[mutation]/path1/path2", field.Route.Path); Assert.IsInstanceOf(typeof(IGraphQLRuntimeResolvedFieldDefinition), field); Assert.AreEqual(1, options.RuntimeTemplates.Count()); + + Assert.AreEqual(1, field.Attributes.Count()); + var mutationRootAttrib = field.Attributes.FirstOrDefault(x => x.GetType() == typeof(MutationRootAttribute)); + Assert.IsNotNull(mutationRootAttrib); } [Test] @@ -67,9 +75,12 @@ public void MapMutation_FromBuilder_WithNoDelegate_DoesNotAddFieldToSchema() var field = builderMock.Object.MapMutation("/path1/path2"); Assert.IsNotNull(field); - Assert.AreEqual(SchemaItemCollections.Mutation, field.CreatePath().RootCollection); + Assert.AreEqual("[mutation]/path1/path2", field.Route.Path); Assert.IsInstanceOf(typeof(IGraphQLRuntimeFieldDefinition), field); Assert.AreEqual(0, options.RuntimeTemplates.Count()); + + // no top level attribute should be available + Assert.AreEqual(0, field.Attributes.Count()); } [Test] @@ -84,9 +95,13 @@ public void MapMutation_FromBuilder_WithDelegate_DoesAddFieldToSchema() var field = builderMock.Object.MapMutation("/path1/path2", TestDelegate); Assert.IsNotNull(field); - Assert.AreEqual(SchemaItemCollections.Mutation, field.CreatePath().RootCollection); + Assert.AreEqual("[mutation]/path1/path2", field.Route.Path); Assert.IsInstanceOf(typeof(IGraphQLRuntimeResolvedFieldDefinition), field); Assert.AreEqual(1, options.RuntimeTemplates.Count()); + + Assert.AreEqual(1, field.Attributes.Count()); + var mutationRootAttrib = field.Attributes.FirstOrDefault(x => x.GetType() == typeof(MutationRootAttribute)); + Assert.IsNotNull(mutationRootAttrib); } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedQueryTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedQueryTemplateTests.cs index 62280cf4d..08f84d643 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedQueryTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedQueryTemplateTests.cs @@ -10,6 +10,7 @@ namespace GraphQL.AspNet.Tests.Configuration.Templates { using System.Linq; + using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Execution; using GraphQL.AspNet.Interfaces.Configuration; @@ -37,9 +38,12 @@ public void MapQuery_FromSchemaOptions_WithNoDelegate_DoesNotAddFieldToSchema() var field = options.MapQuery("/path1/path2"); Assert.IsNotNull(field); - Assert.AreEqual(SchemaItemCollections.Query, field.CreatePath().RootCollection); + Assert.AreEqual(SchemaItemCollections.Query, field.Route.RootCollection); Assert.IsInstanceOf(typeof(IGraphQLRuntimeFieldDefinition), field); Assert.AreEqual(0, options.RuntimeTemplates.Count()); + + // no top level attribute should be available + Assert.AreEqual(0, field.Attributes.Count()); } [Test] @@ -51,9 +55,12 @@ public void MapQuery_FromSchemaOptions_WithDelegate_DoesAddFieldToSchema() var field = options.MapQuery("/path1/path2", TestDelegate); Assert.IsNotNull(field); - Assert.AreEqual(SchemaItemCollections.Query, field.CreatePath().RootCollection); + Assert.AreEqual(SchemaItemCollections.Query, field.Route.RootCollection); Assert.IsInstanceOf(typeof(IGraphQLRuntimeResolvedFieldDefinition), field); Assert.AreEqual(1, options.RuntimeTemplates.Count()); + + var queryRootAttrib = field.Attributes.FirstOrDefault(x => x.GetType() == typeof(QueryRootAttribute)); + Assert.IsNotNull(queryRootAttrib); } [Test] @@ -68,9 +75,12 @@ public void MapQuery_FromBuilder_WithNoDelegate_DoesNotAddFieldToSchema() var field = builderMock.Object.MapQuery("/path1/path2"); Assert.IsNotNull(field); - Assert.AreEqual(SchemaItemCollections.Query, field.CreatePath().RootCollection); + Assert.AreEqual(SchemaItemCollections.Query, field.Route.RootCollection); Assert.IsInstanceOf(typeof(IGraphQLRuntimeFieldDefinition), field); Assert.AreEqual(0, options.RuntimeTemplates.Count()); + + // no top level attribute should be available + Assert.AreEqual(0, field.Attributes.Count()); } [Test] @@ -85,10 +95,13 @@ public void MapQuery_FromBuilder_WithDelegate_DoesAddFieldToSchema() var field = builderMock.Object.MapQuery("/path1/path2", TestDelegate); Assert.IsNotNull(field); - Assert.AreEqual(SchemaItemCollections.Query, field.CreatePath().RootCollection); + Assert.AreEqual(SchemaItemCollections.Query, field.Route.RootCollection); Assert.IsInstanceOf(typeof(IGraphQLRuntimeResolvedFieldDefinition), field); Assert.AreEqual(1, options.RuntimeTemplates.Count()); + + var queryRootAttrib = field.Attributes.FirstOrDefault(x => x.GetType() == typeof(QueryRootAttribute)); + Assert.IsNotNull(queryRootAttrib); } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedTypeExtensionTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedTypeExtensionTemplateTests.cs index c2f2b46af..0760fd2d5 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedTypeExtensionTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedTypeExtensionTemplateTests.cs @@ -36,10 +36,15 @@ public void MapTypeExtension_ByOptions_AddsTypeExtensionToOptions() Assert.AreEqual(1, options.RuntimeTemplates.Count()); Assert.IsNotNull(options.RuntimeTemplates.FirstOrDefault(x => x == typeExt)); - Assert.AreEqual("myField", typeExt.Template); + Assert.AreEqual("[type]/TwoPropertyObject/myField", typeExt.Route.Path); Assert.IsNull(typeExt.ReturnType); Assert.IsNull(typeExt.Resolver); Assert.AreEqual(FieldResolutionMode.PerSourceItem, typeExt.ExecutionMode); + + Assert.AreEqual(1, typeExt.Attributes.Count()); + + var typeExtensionAttrib = typeExt.Attributes.FirstOrDefault(x => x.GetType() == typeof(TypeExtensionAttribute)); + Assert.IsNotNull(typeExtensionAttrib); } [Test] @@ -70,7 +75,7 @@ public void MapTypeExtension_ByOptions_WithResolver_AddsTypeExtensionToOptions() Assert.AreEqual(1, options.RuntimeTemplates.Count()); Assert.IsNotNull(options.RuntimeTemplates.FirstOrDefault(x => x == typeExt)); - Assert.AreEqual("myField", typeExt.Template); + Assert.AreEqual("[type]/TwoPropertyObject/myField", typeExt.Route.Path); Assert.IsNull(typeExt.ReturnType); Assert.AreEqual(typeof(int), typeExt.Resolver.Method.ReturnType); } @@ -103,7 +108,7 @@ public void MappedTypeExtension_WhenAllowAnonymousAdded_AddsAnonymousAttribute() typeExt.AllowAnonymous(); - Assert.AreEqual(1, typeExt.Attributes.Count); + Assert.AreEqual(2, typeExt.Attributes.Count()); Assert.IsNotNull(typeExt.Attributes.FirstOrDefault(x => x is AllowAnonymousAttribute)); } @@ -117,7 +122,7 @@ public void MappedTypeExtension_WhenRequireAuthAdded_AddsAuthAttribute() typeExt.RequireAuthorization("policy1", "roles1"); - Assert.AreEqual(1, typeExt.Attributes.Count); + Assert.AreEqual(2, typeExt.Attributes.Count()); var attrib = typeExt.Attributes.FirstOrDefault(x => x is AuthorizeAttribute) as AuthorizeAttribute; Assert.IsNotNull(attrib); Assert.AreEqual("policy1", attrib.Policy); @@ -149,6 +154,9 @@ public void MappedTypeExtension_WithBatchProcessing_ChangesExecutionMode() typeExt.WithBatchProcessing(); Assert.AreEqual(FieldResolutionMode.Batch, typeExt.ExecutionMode); + + var typeExtensionAttrib = typeExt.Attributes.FirstOrDefault(x => x.GetType() == typeof(BatchTypeExtensionAttribute)); + Assert.IsNotNull(typeExtensionAttrib); } [Test] @@ -160,7 +168,7 @@ public void MappedTypeExtension_AddPossibleTypes_AddsAppropriateAttribute() var typeExt = options.MapField("myField", (string a) => 1); typeExt.AddPossibleTypes(typeof(TwoPropertyObjectV2), typeof(TwoPropertyObjectV3)); - Assert.AreEqual(1, typeExt.Attributes.Count); + Assert.AreEqual(2, typeExt.Attributes.Count()); var attrib = typeExt.Attributes.FirstOrDefault(x => x is PossibleTypesAttribute) as PossibleTypesAttribute; Assert.AreEqual(2, attrib.PossibleTypes.Count); diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/ResolvedFieldTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/ResolvedFieldTemplateTests.cs index a672aaf49..98800d705 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/ResolvedFieldTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/ResolvedFieldTemplateTests.cs @@ -32,7 +32,7 @@ public void ResolvedField_WhenAllowAnonymousAdded_AddsAnonymousAttribute() field.AllowAnonymous(); - Assert.AreEqual(1, field.Attributes.Count); + Assert.AreEqual(2, field.Attributes.Count()); Assert.IsNotNull(field.Attributes.FirstOrDefault(x => x is AllowAnonymousAttribute)); } @@ -46,7 +46,8 @@ public void ResolvedField_WhenRequireAuthAdded_AddsAuthAttribute() field.RequireAuthorization("policy1", "roles1"); - Assert.AreEqual(1, field.Attributes.Count); + Assert.AreEqual(2, field.Attributes.Count()); + var attrib = field.Attributes.FirstOrDefault(x => x is AuthorizeAttribute) as AuthorizeAttribute; Assert.IsNotNull(attrib); Assert.AreEqual("policy1", attrib.Policy); @@ -90,12 +91,12 @@ public void ResolvedField_AddPossibleTypes_AddsAppropriateAttribute() var field = options.MapMutation("/path1/path2", (string a) => 1); field.AddPossibleTypes(typeof(TwoPropertyObject), typeof(TwoPropertyObjectV2)); - Assert.AreEqual(1, field.Attributes.Count); - var attrib = field.Attributes.FirstOrDefault(x => x is PossibleTypesAttribute) as PossibleTypesAttribute; + Assert.AreEqual(2, field.Attributes.Count()); + var possibleTypesAttrib = field.Attributes.FirstOrDefault(x => x is PossibleTypesAttribute) as PossibleTypesAttribute; - Assert.AreEqual(2, attrib.PossibleTypes.Count); - Assert.IsNotNull(attrib.PossibleTypes.FirstOrDefault(x => x == typeof(TwoPropertyObject))); - Assert.IsNotNull(attrib.PossibleTypes.FirstOrDefault(x => x == typeof(TwoPropertyObjectV2))); + Assert.AreEqual(2, possibleTypesAttrib.PossibleTypes.Count); + Assert.IsNotNull(possibleTypesAttrib.PossibleTypes.FirstOrDefault(x => x == typeof(TwoPropertyObject))); + Assert.IsNotNull(possibleTypesAttrib.PossibleTypes.FirstOrDefault(x => x == typeof(TwoPropertyObjectV2))); } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/UnresolvedFieldTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/UnresolvedFieldTemplateTests.cs index a34b4ad11..fa964cd01 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/UnresolvedFieldTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/UnresolvedFieldTemplateTests.cs @@ -30,7 +30,7 @@ public void UnresolvedField_WhenAllowAnonymousAdded_AddsAnonymousAttribute() field.AllowAnonymous(); - Assert.AreEqual(1, field.Attributes.Count); + Assert.AreEqual(1, field.Attributes.Count()); Assert.IsNotNull(field.Attributes.FirstOrDefault(x => x is AllowAnonymousAttribute)); } @@ -44,7 +44,7 @@ public void UnresolvedField_WhenRequireAuthAdded_AddsAuthAttribute() field.RequireAuthorization("policy1", "roles1"); - Assert.AreEqual(1, field.Attributes.Count); + Assert.AreEqual(1, field.Attributes.Count()); var attrib = field.Attributes.FirstOrDefault(x => x is AuthorizeAttribute) as AuthorizeAttribute; Assert.IsNotNull(attrib); Assert.AreEqual("policy1", attrib.Policy); @@ -93,8 +93,7 @@ public void UnresolvedField_WhenUnresolvedChildFieldIsAdded_PathIsCorrect() var childField = field.MapField("/path3/path4"); - var path = childField.CreatePath(); - Assert.AreEqual("[query]/path1/path2/path3/path4", path.Path); + Assert.AreEqual("[query]/path1/path2/path3/path4", childField.Route.Path); } [Test] @@ -107,8 +106,7 @@ public void UnresolvedField_WhenResolvedChildFieldIsAdded_PathIsCorrect() var childField = field.MapField("/path3/path4", (string a) => 1); - var path = childField.CreatePath(); - Assert.AreEqual("[query]/path1/path2/path3/path4", path.Path); + Assert.AreEqual("[query]/path1/path2/path3/path4", childField.Route.Path); } [Test] @@ -121,8 +119,7 @@ public void UnresolvedField_WhenResolvedChildFieldIsAddedToUnresolvedChildField_ var childField = field.MapField("/path3/path4"); var resolvedField = childField.MapField("/path5/path6", (string a) => 1); - var path = resolvedField.CreatePath(); - Assert.AreEqual("[query]/path1/path2/path3/path4/path5/path6", path.Path); + Assert.AreEqual("[query]/path1/path2/path3/path4/path5/path6", resolvedField.Route.Path); Assert.IsNotNull(resolvedField.Resolver); } @@ -136,8 +133,7 @@ public void UnresolvedField_WhenResolvedChildFieldIsAdded_AndParentPathIsChanged var childField = field.MapField("/path3/path4", (string a) => 1); - var path = childField.CreatePath(); - Assert.AreEqual("[query]/path1/path2/path3/path4", path.Path); + Assert.AreEqual("[query]/path1/path2/path3/path4", childField.Route.Path); } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Controllers/SchemaItemPathTests.cs b/src/unit-tests/graphql-aspnet-tests/Controllers/SchemaItemPathTests.cs index d10597929..1ec96f840 100644 --- a/src/unit-tests/graphql-aspnet-tests/Controllers/SchemaItemPathTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Controllers/SchemaItemPathTests.cs @@ -65,7 +65,7 @@ public void IsTopLevelField(string input, bool isTopField) } [Test] - public void Destructuring_Query_TwoFragmentPathHasADefinedParent() + public void Query_TwoFragmentPathHasADefinedParent() { var fragment = "[query]/path1/path2"; var route = new SchemaItemPath(fragment); @@ -202,5 +202,26 @@ public void GraphRouteArgumentPath_YieldsAlternatePathString() var route = new GraphArgumentFieldPath(parent, "arg1"); Assert.AreEqual($"{Constants.Routing.TYPE_ROOT}/typeName/fieldName[arg1]", route.Path); } + + [TestCase("[query]/path1/path2", SchemaItemCollections.Query, "/path1/path2")] + [TestCase("[query]", SchemaItemCollections.Query, "/")] + [TestCase("[mutation]/path1/path2", SchemaItemCollections.Mutation, "/path1/path2")] + [TestCase("[subscription]/path1/path2", SchemaItemCollections.Subscription, "/path1/path2")] + [TestCase("[wrong]/path1/path2", SchemaItemCollections.Unknown, "")] + [TestCase("[query]/path1", SchemaItemCollections.Query, "/path1")] + [TestCase("[mutation]/path1", SchemaItemCollections.Mutation, "/path1")] + [TestCase("[subscription]/path1", SchemaItemCollections.Subscription, "/path1")] + [TestCase("[wrong]/path1", SchemaItemCollections.Unknown, "")] + public void Destructuring_ToCollectionAndPath( + string input, + SchemaItemCollections expectedCollection, + string expectedPath) + { + var route = new SchemaItemPath(input); + var (col, path) = route; + + Assert.AreEqual(expectedCollection, col); + Assert.AreEqual(expectedPath, path); + } } } \ No newline at end of file From fdd42b675f6bfd129cb6fbca1492f5378a0cae07 Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Mon, 19 Jun 2023 13:01:40 -0700 Subject: [PATCH 10/63] WIP --- .../RuntimeControllerDefinition.cs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeControllerDefinition.cs b/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeControllerDefinition.cs index 3c9ffd21b..ce7b51ebe 100644 --- a/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeControllerDefinition.cs +++ b/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeControllerDefinition.cs @@ -9,7 +9,25 @@ namespace GraphQL.AspNet.Schemas.RuntimeSchemaItemDefinitions { + using System.Collections.Generic; + using System.Linq; + using GraphQL.AspNet.Interfaces.Configuration.Templates; + + /// + /// Represents a single controller that contains ALL of the runtime configured + /// fields. (e.g. all the fields created via minimal api calls). + /// internal class RuntimeControllerDefinition { + private List _fields; + + /// + /// Initializes a new instance of the class. + /// + /// The fields that are to be a part of this controller. + public RuntimeControllerDefinition(IEnumerable fields) + { + _fields = new List(fields ?? Enumerable.Empty()); + } } } \ No newline at end of file From 11a7a6d8a02e60c325373c3de5b09919fa588c18 Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Sun, 25 Jun 2023 12:56:02 -0700 Subject: [PATCH 11/63] WIP, basic invocation sequence complete --- ...ptionControllerActionGraphFieldTemplate.cs | 20 ++++- .../SubscriptionGraphControllerTemplate.cs | 21 +++-- .../Common/Generics/InstanceFactory.cs | 2 +- ...chemaItemDefinitionExtensions_Internals.cs | 4 +- ...aItemDefinitionExtensions_VirtualFields.cs | 6 +- .../Configuration/SchemaOptions.cs | 12 ++- .../ServiceCollectionExtensions.cs | 36 ++++++++ .../Controllers/GraphControllerBase.cs | 35 +++++--- .../RuntimeFieldExecutionController.cs | 34 ++++++++ .../Execution/GraphSchemaInitializer.cs | 14 +++- .../Internal/IFieldMemberInfoProvider.cs | 33 ++++++++ .../IGraphQLResolvableSchemaItemDefinition.cs | 2 +- ...tionGraphFieldResolver{TSource,TReturn}.cs | 3 +- .../ControllerActionGraphFieldTemplate.cs | 16 +++- .../TypeTemplates/GraphControllerTemplate.cs | 31 +++---- .../GraphTypeExtensionFieldTemplate.cs | 12 +++ .../InterfaceGraphTypeTemplate.cs | 5 +- .../TypeTemplates/MemberInfoProvider.cs | 51 ++++++++++++ .../TypeTemplates/MethodGraphFieldTemplate.cs | 15 ++++ .../MethodGraphFieldTemplateBase.cs | 15 ++++ .../NonLeafGraphTypeTemplateBase.cs | 67 +++++---------- .../TypeTemplates/ObjectGraphTypeTemplate.cs | 7 +- .../PropertyGraphFieldTemplate.cs | 21 ++++- .../RuntimeGraphControllerTemplate.cs | 64 ++++++++++++++ .../RuntimeSchemaItemAttributeProvider.cs | 83 +++++++++++++++++++ .../RuntimeSchemaItemTemplate.cs | 35 -------- .../RuntimeSchemaItemTypeMarker.cs | 20 ----- .../Schemas/GraphSchemaManager.cs | 19 ++++- .../RuntimeControllerDefinition.cs | 33 -------- .../SingleMethodGraphControllerTemplate.cs | 6 +- .../GeneralQueryExecutionRuntimeFieldTests.cs | 51 ++++++++++++ 31 files changed, 570 insertions(+), 203 deletions(-) create mode 100644 src/graphql-aspnet/Configuration/ServiceCollectionExtensions.cs create mode 100644 src/graphql-aspnet/Controllers/RuntimeFieldExecutionController.cs create mode 100644 src/graphql-aspnet/Interfaces/Internal/IFieldMemberInfoProvider.cs create mode 100644 src/graphql-aspnet/Internal/TypeTemplates/MemberInfoProvider.cs create mode 100644 src/graphql-aspnet/Internal/TypeTemplates/RuntimeGraphControllerTemplate.cs create mode 100644 src/graphql-aspnet/Internal/TypeTemplates/RuntimeSchemaItemAttributeProvider.cs delete mode 100644 src/graphql-aspnet/Internal/TypeTemplates/RuntimeSchemaItemTemplate.cs delete mode 100644 src/graphql-aspnet/Internal/TypeTemplates/RuntimeSchemaItemTypeMarker.cs delete mode 100644 src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeControllerDefinition.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionRuntimeFieldTests.cs diff --git a/src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionControllerActionGraphFieldTemplate.cs b/src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionControllerActionGraphFieldTemplate.cs index 654086091..02fa75842 100644 --- a/src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionControllerActionGraphFieldTemplate.cs +++ b/src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionControllerActionGraphFieldTemplate.cs @@ -32,8 +32,8 @@ public class SubscriptionControllerActionGraphFieldTemplate : ControllerActionGr /// /// Initializes a new instance of the class. /// - /// The parent. - /// The method information. + /// The controller that owns this action. + /// The method information to be templatized. public SubscriptionControllerActionGraphFieldTemplate( IGraphControllerTemplate parent, MethodInfo methodInfo) @@ -42,6 +42,22 @@ public SubscriptionControllerActionGraphFieldTemplate( this.EventName = null; } + /// + /// Initializes a new instance of the class. + /// + /// The controller that owns this action. + /// The method information to be templatized. + /// A custom, external attribute provider to use instead for extracting + /// configuration attributes instead of the provider on . + public SubscriptionControllerActionGraphFieldTemplate( + IGraphControllerTemplate parent, + MethodInfo methodInfo, + ICustomAttributeProvider attributeProvider) + : base(parent, methodInfo, attributeProvider) + { + this.EventName = null; + } + /// protected override void ParseTemplateDefinition() { diff --git a/src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionGraphControllerTemplate.cs b/src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionGraphControllerTemplate.cs index 624df3f99..9a020c225 100644 --- a/src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionGraphControllerTemplate.cs +++ b/src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionGraphControllerTemplate.cs @@ -33,21 +33,20 @@ public SubscriptionGraphControllerTemplate(Type controllerType) { } - /// - /// When overridden in a child, allows the class to create custom template that inherit from - /// to provide additional functionality or garuntee a certian type structure for all methods on this object template. - /// - /// The method information. - /// IGraphFieldTemplate. - protected override IGraphFieldTemplate CreateMethodFieldTemplate(MethodInfo methodInfo) + /// + protected override IGraphFieldTemplate CreateFieldTemplate(IFieldMemberInfoProvider member) { - if (methodInfo == null) + if (member?.MemberInfo == null || !(member.MemberInfo is MethodInfo)) return null; - if (methodInfo.HasAttribute() || methodInfo.HasAttribute()) - return new SubscriptionControllerActionGraphFieldTemplate(this, methodInfo); + if (member?.MemberInfo != null && + member.MemberInfo is MethodInfo methodInfo && + (member.AttributeProvider.HasAttribute() || member.AttributeProvider.HasAttribute())) + { + return new SubscriptionControllerActionGraphFieldTemplate(this, methodInfo, member.AttributeProvider); + } - return base.CreateMethodFieldTemplate(methodInfo); + return base.CreateFieldTemplate(member); } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Common/Generics/InstanceFactory.cs b/src/graphql-aspnet/Common/Generics/InstanceFactory.cs index b6891c270..5f1fc85c6 100644 --- a/src/graphql-aspnet/Common/Generics/InstanceFactory.cs +++ b/src/graphql-aspnet/Common/Generics/InstanceFactory.cs @@ -304,7 +304,7 @@ public static object CreateInstance(Type type, params object[] args) // in combination with Roger Johanson: https://rogerjohansson.blog/2008/02/28/linq-expressions-creating-objects/ . // ----------------------------- if (args == null) - return CreateInstance(type); + return CreateInstance(type, new object[0]); if ((args.Length > 3) || (args.Length > 0 && args[0] == null) diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Internals.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Internals.cs index 6d4b35584..c7f2409e4 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Internals.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Internals.cs @@ -55,7 +55,7 @@ private static IGraphQLRuntimeTypeExtensionDefinition MapTypeExtensionInternal( fieldName, resolutionMode); - schemaOptions.AddSchemaItemTemplate(field); + schemaOptions.AddRuntimeSchemaItem(field); return field; } @@ -66,7 +66,7 @@ private static IGraphQLRuntimeDirectiveActionDefinition MapDirectiveInternal(thi var directive = new RuntimeDirectiveActionDefinition(schemaOptions, directiveName); - schemaOptions.AddSchemaItemTemplate(directive); + schemaOptions.AddRuntimeSchemaItem(directive); return directive; } } diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_VirtualFields.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_VirtualFields.cs index 3ed7ea461..367897e5a 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_VirtualFields.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_VirtualFields.cs @@ -80,7 +80,7 @@ public static IGraphQLRuntimeResolvedFieldDefinition AddResolver(this IGraphQLRu { // convert the virtual field to a resolved field var resolvedBuilder = RuntimeResolvedFieldDefinition.FromFieldTemplate(field); - resolvedBuilder.Options.AddSchemaItemTemplate(resolvedBuilder); + resolvedBuilder.Options.AddRuntimeSchemaItem(resolvedBuilder); resolvedBuilder.Resolver = resolverMethod; resolvedBuilder.ReturnType = null; @@ -104,7 +104,7 @@ public static IGraphQLRuntimeResolvedFieldDefinition AddResolver(th { // convert the virtual field to a resolved field var resolvedBuilder = RuntimeResolvedFieldDefinition.FromFieldTemplate(field); - resolvedBuilder.Options.AddSchemaItemTemplate(resolvedBuilder); + resolvedBuilder.Options.AddRuntimeSchemaItem(resolvedBuilder); resolvedBuilder.Resolver = resolverMethod; resolvedBuilder.ReturnType = typeof(TReturnType); @@ -123,7 +123,7 @@ public static IGraphQLRuntimeResolvedFieldDefinition MapField(this IGraphQLRunti var subField = new RuntimeResolvedFieldDefinition(field, subTemplate); subField.AddResolver(resolverMethod); - subField.Options.AddSchemaItemTemplate(subField); + subField.Options.AddRuntimeSchemaItem(subField); return subField; } diff --git a/src/graphql-aspnet/Configuration/SchemaOptions.cs b/src/graphql-aspnet/Configuration/SchemaOptions.cs index 51b77b2ce..9118e9b10 100644 --- a/src/graphql-aspnet/Configuration/SchemaOptions.cs +++ b/src/graphql-aspnet/Configuration/SchemaOptions.cs @@ -351,12 +351,16 @@ internal void FinalizeServiceRegistration() } /// - /// Adds the runtime schema item template to the schema options so that it can be - /// created when the schema is set up. + /// Adds "runtime declared" schema item to this instance so that it can be + /// created and registered when the schema is set up. /// - /// The template to add. - internal void AddSchemaItemTemplate(IGraphQLRuntimeSchemaItemDefinition template) + /// + /// "Runtime declared" schema items are synonymous with minimal api defined fields. + /// + /// The schema item to include. + internal void AddRuntimeSchemaItem(IGraphQLRuntimeSchemaItemDefinition template) { + this.ServiceCollection.AddRuntimeFieldExecutionSupport(); _runtimeTemplates.Add(template); } diff --git a/src/graphql-aspnet/Configuration/ServiceCollectionExtensions.cs b/src/graphql-aspnet/Configuration/ServiceCollectionExtensions.cs new file mode 100644 index 000000000..579280279 --- /dev/null +++ b/src/graphql-aspnet/Configuration/ServiceCollectionExtensions.cs @@ -0,0 +1,36 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Configuration +{ + using GraphQL.AspNet.Controllers; + using Microsoft.Extensions.DependencyInjection; + using Microsoft.Extensions.DependencyInjection.Extensions; + + /// + /// Helper methods for configuring an + /// during startup. + /// + public static class ServiceCollectionExtensions + { + /// + /// Adds support for the execution of runtime field declarations (e.g. minimal api + /// defined fields). + /// + /// The service collection. + /// IServiceCollection. + public static IServiceCollection AddRuntimeFieldExecutionSupport(this IServiceCollection serviceCollection) + { + if (serviceCollection != null) + serviceCollection.TryAddTransient(); + + return serviceCollection; + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Controllers/GraphControllerBase.cs b/src/graphql-aspnet/Controllers/GraphControllerBase.cs index 509a91623..42f5209ce 100644 --- a/src/graphql-aspnet/Controllers/GraphControllerBase.cs +++ b/src/graphql-aspnet/Controllers/GraphControllerBase.cs @@ -74,17 +74,8 @@ internal virtual async Task InvokeActionAsync( _schemaItemContext.Logger?.ActionMethodModelStateValidated(_action, this.Request, this.ModelState); - if (_action.Method.DeclaringType != this.GetType()) - { - throw new TargetException($"Unable to invoke action '{_action.Route.Path}' on controller '{this.GetType().FriendlyName()}'. The controller " + - "does not own the method."); - } - - var invoker = InstanceFactory.CreateInstanceMethodInvoker(_action.Method); - var invocationParameters = schemaItemContext.Arguments.PrepareArguments(_action); - - var controllerRef = this as object; - var invokeReturn = invoker(ref controllerRef, invocationParameters); + var invocationParameters = _schemaItemContext.Arguments.PrepareArguments(_action); + var invokeReturn = this.CreateAndInvokeAction(_action, invocationParameters); if (_action.IsAsyncField) { if (invokeReturn is Task task) @@ -135,6 +126,28 @@ internal virtual async Task InvokeActionAsync( } } + /// + /// Invoke the actual C# method declared by the + /// using this controller instance as the target object of the invocation. + /// + /// The resolver declaration that needs to be executed. + /// The realized set of arguments that need + /// to be passed to the invocable method instance. + /// Task. + protected virtual object CreateAndInvokeAction(IGraphFieldResolverMethod resolver, object[] invocationArguments) + { + if (resolver.Method.DeclaringType != this.GetType()) + { + throw new TargetException($"Unable to invoke action '{_action.Route.Path}' on controller '{this.GetType().FriendlyName()}'. The controller " + + "does not own the method."); + } + + var invoker = InstanceFactory.CreateInstanceMethodInvoker(resolver.Method); + + var controllerRef = this as object; + return invoker(ref controllerRef, invocationArguments); + } + /// /// Gets the state of the model being represented on this controller action invocation. /// diff --git a/src/graphql-aspnet/Controllers/RuntimeFieldExecutionController.cs b/src/graphql-aspnet/Controllers/RuntimeFieldExecutionController.cs new file mode 100644 index 000000000..b09fb2139 --- /dev/null +++ b/src/graphql-aspnet/Controllers/RuntimeFieldExecutionController.cs @@ -0,0 +1,34 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Controllers +{ + using GraphQL.AspNet.Attributes; + using GraphQL.AspNet.Common.Generics; + using GraphQL.AspNet.Interfaces.Execution; + + /// + /// A special controller instance for executing runtime configured controller + /// actions (e.g. minimal api defined fields). + /// + [GraphRoot] + internal sealed class RuntimeFieldExecutionController : GraphController + { + /// + protected override object CreateAndInvokeAction(IGraphFieldResolverMethod resolver, object[] invocationArguments) + { + // for minimal api resolvers create an instance of the + // "runtime declared owner type" and invoke using it + var instance = InstanceFactory.CreateInstance(resolver.Method.DeclaringType); + var invoker = InstanceFactory.CreateInstanceMethodInvoker(resolver.Method); + + return invoker(ref instance, invocationArguments); + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Execution/GraphSchemaInitializer.cs b/src/graphql-aspnet/Execution/GraphSchemaInitializer.cs index d41865444..a74b6691b 100644 --- a/src/graphql-aspnet/Execution/GraphSchemaInitializer.cs +++ b/src/graphql-aspnet/Execution/GraphSchemaInitializer.cs @@ -10,10 +10,12 @@ namespace GraphQL.AspNet.Execution { using System; + using System.Linq; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Common; using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Interfaces.Configuration.Templates; using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Schemas; @@ -66,6 +68,7 @@ public void Initialize(TSchema schema) manager.AddBuiltInDirectives(); // add any configured types to this instance + // -------------------------------------- foreach (var registration in _options.SchemaTypesToRegister) { var typeDeclaration = registration.Type.SingleAttributeOrDefault(); @@ -75,8 +78,17 @@ public void Initialize(TSchema schema) manager.EnsureGraphType(registration.Type, registration.TypeKind); } + // add in any runtime configured fields and directives (minimal api) + // -------------------------------------- + var runtimeFields = _options.RuntimeTemplates + .Where(x => x is IGraphQLRuntimeResolvedFieldDefinition) + .Cast(); + + foreach (var field in runtimeFields) + manager.AddRuntimeFieldDeclaration(field); + // execute any assigned schema configuration extensions - // + // ----------------------- // this includes any late bound directives added to the type // system via .ApplyDirective() foreach (var extension in _options.ConfigurationExtensions) diff --git a/src/graphql-aspnet/Interfaces/Internal/IFieldMemberInfoProvider.cs b/src/graphql-aspnet/Interfaces/Internal/IFieldMemberInfoProvider.cs new file mode 100644 index 000000000..e3b206774 --- /dev/null +++ b/src/graphql-aspnet/Interfaces/Internal/IFieldMemberInfoProvider.cs @@ -0,0 +1,33 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Interfaces.Internal +{ + using System.Reflection; + + /// + /// A common interface that exposes the various attributes of a + /// and to the templating system. + /// + public interface IFieldMemberInfoProvider + { + /// + /// Gets the member info object that defines a field. + /// + /// The member information. + public MemberInfo MemberInfo { get; } + + /// + /// Gets the attribute provider that serves up the various control and + /// configuration attributes for generating a graph field from the . + /// + /// The attribute provider. + public ICustomAttributeProvider AttributeProvider { get; } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLResolvableSchemaItemDefinition.cs b/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLResolvableSchemaItemDefinition.cs index 591116630..2db7788e3 100644 --- a/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLResolvableSchemaItemDefinition.cs +++ b/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLResolvableSchemaItemDefinition.cs @@ -15,7 +15,7 @@ namespace GraphQL.AspNet.Interfaces.Configuration.Templates /// A template for a runtime created schema item that has an attached resolver. Usually /// a field or a directive. /// - public interface IGraphQLResolvableSchemaItemDefinition + public interface IGraphQLResolvableSchemaItemDefinition : IGraphQLRuntimeSchemaItemDefinition { /// /// Gets or sets the resolver function that has been assigned to execute when this diff --git a/src/graphql-aspnet/Internal/Resolvers/FunctionGraphFieldResolver{TSource,TReturn}.cs b/src/graphql-aspnet/Internal/Resolvers/FunctionGraphFieldResolver{TSource,TReturn}.cs index 27294b640..af07d3efe 100644 --- a/src/graphql-aspnet/Internal/Resolvers/FunctionGraphFieldResolver{TSource,TReturn}.cs +++ b/src/graphql-aspnet/Internal/Resolvers/FunctionGraphFieldResolver{TSource,TReturn}.cs @@ -23,7 +23,8 @@ namespace GraphQL.AspNet.Internal.Resolvers /// The expected type of the source data. /// The expected type of the returned data. /// - /// This resolver is used heavily by the introspection system. + /// This resolver is used heavily by the introspection system for simple, static data resolution + /// and extending other more involved resolvers with simple add-on functionality. /// internal class FunctionGraphFieldResolver : IGraphFieldResolver where TSource : class diff --git a/src/graphql-aspnet/Internal/TypeTemplates/ControllerActionGraphFieldTemplate.cs b/src/graphql-aspnet/Internal/TypeTemplates/ControllerActionGraphFieldTemplate.cs index 9fab94754..39b5f76a8 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/ControllerActionGraphFieldTemplate.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/ControllerActionGraphFieldTemplate.cs @@ -32,13 +32,25 @@ public class ControllerActionGraphFieldTemplate : MethodGraphFieldTemplateBase /// /// Initializes a new instance of the class. /// - /// The parent. - /// The method information. + /// The controller that owns this action. + /// The method information to be templatized. public ControllerActionGraphFieldTemplate(IGraphControllerTemplate parent, MethodInfo methodInfo) : base(parent, methodInfo) { } + /// + /// Initializes a new instance of the class. + /// + /// The controller that owns this action. + /// The method information to be templatized. + /// A custom, external attribute provider to use instead for extracting + /// configuration attributes instead of the provider on . + public ControllerActionGraphFieldTemplate(IGraphControllerTemplate parent, MethodInfo methodInfo, ICustomAttributeProvider attributeProvider) + : base(parent, methodInfo, attributeProvider) + { + } + /// /// When overridden in a child class, this metyhod builds the route that will be assigned to this method /// using the implementation rules of the concrete type. diff --git a/src/graphql-aspnet/Internal/TypeTemplates/GraphControllerTemplate.cs b/src/graphql-aspnet/Internal/TypeTemplates/GraphControllerTemplate.cs index 90ed036a4..9a2410136 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/GraphControllerTemplate.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/GraphControllerTemplate.cs @@ -47,11 +47,12 @@ public GraphControllerTemplate(Type controllerType) } /// - protected override IEnumerable GatherPossibleTemplateMembers() + protected override IEnumerable GatherPossibleFieldTemplates() { return this.ObjectType.GetMethods(BindingFlags.Public | BindingFlags.Instance) .Where(x => !x.IsAbstract && !x.IsGenericMethod && !x.IsSpecialName).Cast() - .Concat(this.ObjectType.GetProperties(BindingFlags.Public | BindingFlags.Instance)); + .Concat(this.ObjectType.GetProperties(BindingFlags.Public | BindingFlags.Instance)) + .Select(x => new MemberInfoProvider(x)); } /// @@ -107,35 +108,29 @@ public override void ValidateOrThrow() } /// - protected override bool CouldBeGraphField(MemberInfo memberInfo) + protected override bool CouldBeGraphField(IFieldMemberInfoProvider fieldProvider) { - if (memberInfo == null || memberInfo is PropertyInfo) + if (fieldProvider?.MemberInfo == null || !(fieldProvider.MemberInfo is MethodInfo)) return false; - if (!base.CouldBeGraphField(memberInfo)) + if (!base.CouldBeGraphField(fieldProvider)) return false; // always require explicit attribution from controller action methods - return memberInfo.SingleAttributeOfTypeOrDefault() != null; + return fieldProvider.AttributeProvider.SingleAttributeOfTypeOrDefault() != null; } /// - protected override IGraphFieldTemplate CreateMethodFieldTemplate(MethodInfo methodInfo) + protected override IGraphFieldTemplate CreateFieldTemplate(IFieldMemberInfoProvider member) { - if (methodInfo == null) + // safety check to ensure properites on controllers can never be parsed as fields + if (member?.MemberInfo == null || !(member.MemberInfo is MethodInfo)) return null; - if (methodInfo.HasAttribute()) - return new GraphTypeExtensionFieldTemplate(this, methodInfo); + if (member.AttributeProvider.HasAttribute()) + return new GraphTypeExtensionFieldTemplate(this, (MethodInfo)member.MemberInfo, member.AttributeProvider); else - return new ControllerActionGraphFieldTemplate(this, methodInfo); - } - - /// - protected override IGraphFieldTemplate CreatePropertyFieldTemplate(PropertyInfo prop) - { - // safety check to ensure properites on controllers can never be parsed as fields - return null; + return new ControllerActionGraphFieldTemplate(this, (MethodInfo)member.MemberInfo, member.AttributeProvider); } /// diff --git a/src/graphql-aspnet/Internal/TypeTemplates/GraphTypeExtensionFieldTemplate.cs b/src/graphql-aspnet/Internal/TypeTemplates/GraphTypeExtensionFieldTemplate.cs index 91443bf86..0c0059f51 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/GraphTypeExtensionFieldTemplate.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/GraphTypeExtensionFieldTemplate.cs @@ -42,6 +42,18 @@ public GraphTypeExtensionFieldTemplate(IGraphTypeTemplate parent, MethodInfo met { } + /// + /// Initializes a new instance of the class. + /// + /// The parent object template that owns this method. + /// The method information. + /// A custom, external attribute provider to use instead for extracting + /// configuration attributes instead of the provider on . + public GraphTypeExtensionFieldTemplate(IGraphTypeTemplate parent, MethodInfo methodInfo, ICustomAttributeProvider attributeProvider) + : base(parent, methodInfo, attributeProvider) + { + } + /// /// Builds out this field template parsing out the required type declarations unions, nameing scheme etc. This method should be /// overridden in any child classes for additional decalration requirements. diff --git a/src/graphql-aspnet/Internal/TypeTemplates/InterfaceGraphTypeTemplate.cs b/src/graphql-aspnet/Internal/TypeTemplates/InterfaceGraphTypeTemplate.cs index 90fcb56eb..91f069df4 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/InterfaceGraphTypeTemplate.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/InterfaceGraphTypeTemplate.cs @@ -41,11 +41,12 @@ public InterfaceGraphTypeTemplate(Type interfaceType) } /// - protected override IEnumerable GatherPossibleTemplateMembers() + protected override IEnumerable GatherPossibleFieldTemplates() { return this.ObjectType.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly) .Where(x => !x.IsGenericMethod && !x.IsSpecialName).Cast() - .Concat(this.ObjectType.GetProperties(BindingFlags.Public | BindingFlags.Instance)); + .Concat(this.ObjectType.GetProperties(BindingFlags.Public | BindingFlags.Instance)) + .Select(x => new MemberInfoProvider(x)); } /// diff --git a/src/graphql-aspnet/Internal/TypeTemplates/MemberInfoProvider.cs b/src/graphql-aspnet/Internal/TypeTemplates/MemberInfoProvider.cs new file mode 100644 index 000000000..11f88a47e --- /dev/null +++ b/src/graphql-aspnet/Internal/TypeTemplates/MemberInfoProvider.cs @@ -0,0 +1,51 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Internal.TypeTemplates +{ + using System.Reflection; + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Interfaces.Internal; + + /// + /// A for to abstract out appropriate pieces + /// of that are exposed to the templating system. + /// + public class MemberInfoProvider : IFieldMemberInfoProvider + { + /// + /// Initializes a new instance of the class. + /// + /// The primary member information used in this instance. + /// This object will be used as the primary member info as well as the attribute provider for this instance. + public MemberInfoProvider(MemberInfo memberInfo) + { + this.MemberInfo = Validation.ThrowIfNullOrReturn(memberInfo, nameof(memberInfo)); + this.AttributeProvider = this.MemberInfo; + } + + /// + /// Initializes a new instance of the class. + /// + /// The primary member information used in this instance. + /// The an alternate attribute source + /// to use for determining configuration and control attributes for this instance. + public MemberInfoProvider(MemberInfo memberInfo, ICustomAttributeProvider attributeProvider) + { + this.MemberInfo = Validation.ThrowIfNullOrReturn(memberInfo, nameof(memberInfo)); + this.AttributeProvider = Validation.ThrowIfNullOrReturn(attributeProvider, nameof(attributeProvider)); + } + + /// + public MemberInfo MemberInfo { get; } + + /// + public ICustomAttributeProvider AttributeProvider { get; } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Internal/TypeTemplates/MethodGraphFieldTemplate.cs b/src/graphql-aspnet/Internal/TypeTemplates/MethodGraphFieldTemplate.cs index fbf077ff0..35692ee32 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/MethodGraphFieldTemplate.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/MethodGraphFieldTemplate.cs @@ -9,6 +9,7 @@ namespace GraphQL.AspNet.Internal.TypeTemplates { + using System; using System.Reflection; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Common.Extensions; @@ -35,6 +36,20 @@ public MethodGraphFieldTemplate(IGraphTypeTemplate parent, MethodInfo methodInfo this.OwnerTypeKind = ownerTypeKind; } + /// + /// Initializes a new instance of the class. + /// + /// The parent object template that owns this method. + /// The method information. + /// A custom, external attribute provider to use instead for extracting + /// configuration attributes instead of the provider on . + /// The kind of object that will own this field. + public MethodGraphFieldTemplate(IGraphTypeTemplate parent, MethodInfo methodInfo, ICustomAttributeProvider attributeProvider, TypeKind ownerTypeKind) + : base(parent, methodInfo, attributeProvider) + { + this.OwnerTypeKind = ownerTypeKind; + } + /// protected override SchemaItemPath GenerateFieldPath() { diff --git a/src/graphql-aspnet/Internal/TypeTemplates/MethodGraphFieldTemplateBase.cs b/src/graphql-aspnet/Internal/TypeTemplates/MethodGraphFieldTemplateBase.cs index e61a9c2ec..b9352e0f7 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/MethodGraphFieldTemplateBase.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/MethodGraphFieldTemplateBase.cs @@ -29,6 +29,21 @@ public abstract class MethodGraphFieldTemplateBase : GraphFieldTemplateBase, IGr { private readonly List _arguments; + /// + /// Initializes a new instance of the class. + /// + /// The parent object template that owns this method. + /// The method information. + /// A custom, external attribute provider to use instead for extracting + /// configuration attributes instead of the provider on . + protected MethodGraphFieldTemplateBase(IGraphTypeTemplate parent, MethodInfo methodInfo, ICustomAttributeProvider attributeProvider) + : base(parent, attributeProvider) + { + this.Method = Validation.ThrowIfNullOrReturn(methodInfo, nameof(methodInfo)); + this.Parameters = this.Method.GetParameters().ToList(); + _arguments = new List(); + } + /// /// Initializes a new instance of the class. /// diff --git a/src/graphql-aspnet/Internal/TypeTemplates/NonLeafGraphTypeTemplateBase.cs b/src/graphql-aspnet/Internal/TypeTemplates/NonLeafGraphTypeTemplateBase.cs index 12a302b3f..4f9fa8f8d 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/NonLeafGraphTypeTemplateBase.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/NonLeafGraphTypeTemplateBase.cs @@ -14,6 +14,7 @@ namespace GraphQL.AspNet.Internal.TypeTemplates using System.ComponentModel; using System.Diagnostics; using System.Linq; + using System.Linq.Expressions; using System.Reflection; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Common; @@ -106,7 +107,7 @@ protected override void ParseTemplateDefinition() // ------------------------------------ var parsedItems = new List(); - var templateMembers = this.GatherPossibleTemplateMembers(); + var templateMembers = this.GatherPossibleFieldTemplates(); foreach (var member in templateMembers) { @@ -160,25 +161,27 @@ protected override void ParseTemplateDefinition() /// Extract the possible template members of /// that might be includable in this template. /// - /// IEnumerable<MemberInfo>. - protected abstract IEnumerable GatherPossibleTemplateMembers(); + /// IEnumerable<IFieldMemberInfoProvider>. + protected abstract IEnumerable GatherPossibleFieldTemplates(); /// - /// Creates the member template from the given info. If overriden in a child class methods and - /// may no longer be called. This method gives you a point of inflection to override how all - /// field templates are created or just those for a given member type. + /// Creates the member template from the given info. If a provided + /// should not be templatized, return null. /// - /// The member. + /// The member to templatize. /// GraphQL.AspNet.Internal.Interfaces.IGraphFieldTemplate. - protected virtual IGraphFieldTemplate CreateFieldTemplate(MemberInfo member) + protected virtual IGraphFieldTemplate CreateFieldTemplate(IFieldMemberInfoProvider fieldProvider) { - switch (member) + if (fieldProvider?.MemberInfo == null) + return null; + + switch (fieldProvider.MemberInfo) { case PropertyInfo pi: - return this.CreatePropertyFieldTemplate(pi); + return new PropertyGraphFieldTemplate(this, pi, fieldProvider.AttributeProvider, this.Kind); case MethodInfo mi: - return this.CreateMethodFieldTemplate(mi); + return new MethodGraphFieldTemplate(this, mi, fieldProvider.AttributeProvider, this.Kind); } return null; @@ -189,24 +192,24 @@ protected virtual IGraphFieldTemplate CreateFieldTemplate(MemberInfo member) /// explictly declared as such or that it conformed to the required parameters of being /// a field. /// - /// The member information to check. + /// The member information to check. /// /// true if the info represents a possible graph field; otherwise, false. - protected virtual bool CouldBeGraphField(MemberInfo memberInfo) + protected virtual bool CouldBeGraphField(IFieldMemberInfoProvider fieldProvider) { // always skip those marked as such regardless of anything else - if (memberInfo.HasAttribute()) + if (fieldProvider.AttributeProvider.HasAttribute()) return false; - if (Constants.IgnoredFieldNames.Contains(memberInfo.Name)) + if (Constants.IgnoredFieldNames.Contains(fieldProvider.MemberInfo.Name)) return false; // when the member declares any known attribute in the library include it // and allow it to generate validation failures if its not properly constructed - if (memberInfo.SingleAttributeOfTypeOrDefault() != null) + if (fieldProvider.AttributeProvider.SingleAttributeOfTypeOrDefault() != null) return true; - switch (memberInfo) + switch (fieldProvider.MemberInfo) { case MethodInfo mi: if (!GraphValidation.IsValidGraphType(mi.ReturnType, false)) @@ -230,7 +233,7 @@ protected virtual bool CouldBeGraphField(MemberInfo memberInfo) } /// - /// When overridden in a child class, this metyhod builds the route that will be assigned to this method + /// When overridden in a child class, this method builds the route that will be assigned to this method /// using the implementation rules of the concrete type. /// /// GraphRoutePath. @@ -271,34 +274,6 @@ public override void ValidateOrThrow() field.ValidateOrThrow(); } - /// - /// When overridden in a child, allows the class to create custom templates that inherit from - /// to provide additional functionality or guarantee a certian type structure for all methods on this object template. - /// - /// The method information to templatize. - /// IGraphFieldTemplate. - protected virtual IGraphFieldTemplate CreateMethodFieldTemplate(MethodInfo methodInfo) - { - if (methodInfo == null) - return null; - - return new MethodGraphFieldTemplate(this, methodInfo, this.Kind); - } - - /// - /// When overridden in a child, allows the class to create custom templates to provide additional functionality or - /// guarantee a certian type structure for all properties on this object template. - /// - /// The property information to templatize. - /// IGraphFieldTemplate. - protected virtual IGraphFieldTemplate CreatePropertyFieldTemplate(PropertyInfo propInfo) - { - if (propInfo == null) - return null; - - return new PropertyGraphFieldTemplate(this, propInfo, this.Kind); - } - /// public override AppliedSecurityPolicyGroup SecurityPolicies => _securityPolicies; diff --git a/src/graphql-aspnet/Internal/TypeTemplates/ObjectGraphTypeTemplate.cs b/src/graphql-aspnet/Internal/TypeTemplates/ObjectGraphTypeTemplate.cs index 40df58f1d..8208fb022 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/ObjectGraphTypeTemplate.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/ObjectGraphTypeTemplate.cs @@ -18,7 +18,7 @@ namespace GraphQL.AspNet.Internal.TypeTemplates using GraphQL.AspNet.Schemas.TypeSystem; /// - /// An graph type template describing an OBJECT graph type. + /// A graph type template describing an OBJECT graph type. /// [DebuggerDisplay("Object: {InternalName}")] public class ObjectGraphTypeTemplate : NonLeafGraphTypeTemplateBase, IObjectGraphTypeTemplate @@ -33,11 +33,12 @@ public ObjectGraphTypeTemplate(Type objectType) } /// - protected override IEnumerable GatherPossibleTemplateMembers() + protected override IEnumerable GatherPossibleFieldTemplates() { return this.ObjectType.GetMethods(BindingFlags.Public | BindingFlags.Instance) .Where(x => !x.IsAbstract && !x.IsGenericMethod && !x.IsSpecialName).Cast() - .Concat(this.ObjectType.GetProperties(BindingFlags.Public | BindingFlags.Instance)); + .Concat(this.ObjectType.GetProperties(BindingFlags.Public | BindingFlags.Instance)) + .Select(x => new MemberInfoProvider(x)); } /// diff --git a/src/graphql-aspnet/Internal/TypeTemplates/PropertyGraphFieldTemplate.cs b/src/graphql-aspnet/Internal/TypeTemplates/PropertyGraphFieldTemplate.cs index bf5e35884..b55ac29f5 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/PropertyGraphFieldTemplate.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/PropertyGraphFieldTemplate.cs @@ -34,8 +34,25 @@ public class PropertyGraphFieldTemplate : GraphFieldTemplateBase, IGraphFieldRes /// /// Initializes a new instance of the class. /// - /// The parent. - /// The property information. + /// The owner of this field template. + /// The property information that will be used to create the field. + /// A custom, external attribute provider to use instead for extracting + /// configuration attributes instead of the provider on . + /// The kind of graph type that will own this field. + public PropertyGraphFieldTemplate(IGraphTypeTemplate parent, PropertyInfo propInfo, ICustomAttributeProvider attributeProvider, TypeKind ownerKind) + : base(parent, attributeProvider) + { + this.Property = Validation.ThrowIfNullOrReturn(propInfo, nameof(propInfo)); + this.Method = this.Property.GetGetMethod(); + this.Parameters = this.Method?.GetParameters().ToList() ?? new List(); + this.OwnerTypeKind = ownerKind; + } + + /// + /// Initializes a new instance of the class. + /// + /// The owner of this field template. + /// The property information that will be used to create the field. /// The kind of graph type that will own this field. public PropertyGraphFieldTemplate(IGraphTypeTemplate parent, PropertyInfo propInfo, TypeKind ownerKind) : base(parent, propInfo) diff --git a/src/graphql-aspnet/Internal/TypeTemplates/RuntimeGraphControllerTemplate.cs b/src/graphql-aspnet/Internal/TypeTemplates/RuntimeGraphControllerTemplate.cs new file mode 100644 index 000000000..74729d20d --- /dev/null +++ b/src/graphql-aspnet/Internal/TypeTemplates/RuntimeGraphControllerTemplate.cs @@ -0,0 +1,64 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Internal.TypeTemplates +{ + using System.Collections.Generic; + using System.Reflection; + using GraphQL.AspNet.Attributes; + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Common.Extensions; + using GraphQL.AspNet.Controllers; + using GraphQL.AspNet.Execution.Exceptions; + using GraphQL.AspNet.Interfaces.Configuration.Templates; + using GraphQL.AspNet.Interfaces.Internal; + using GraphQL.AspNet.Schemas.Structural; + + /// + /// A "controller template" representing a single runtime configured field (e.g. minimal api). + /// This template is never cached. + /// + internal class RuntimeGraphControllerTemplate : GraphControllerTemplate + { + private readonly IFieldMemberInfoProvider _fieldProvider; + private readonly IGraphQLResolvableSchemaItemDefinition _fieldDefinition; + + /// + /// Initializes a new instance of the class. + /// + /// A single, runtime configured, field definition + /// to templatize for a specfic schema. + public RuntimeGraphControllerTemplate(IGraphQLResolvableSchemaItemDefinition fieldDefinition) + : base(typeof(RuntimeFieldExecutionController)) + { + if (fieldDefinition.Resolver?.Method == null) + { + throw new GraphTypeDeclarationException( + $"Unable to templatize the runtime field definition of '{fieldDefinition.Route}' the resolver " + + $"is not properly configured."); + } + + _fieldProvider = new MemberInfoProvider( + fieldDefinition.Resolver.Method, + new RuntimeSchemaItemAttributeProvider(fieldDefinition)); + } + + /// + protected override IEnumerable GatherPossibleFieldTemplates() + { + yield return _fieldProvider; + } + + /// + protected override bool CouldBeGraphField(IFieldMemberInfoProvider fieldProvider) + { + return fieldProvider != null && fieldProvider == _fieldProvider; + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Internal/TypeTemplates/RuntimeSchemaItemAttributeProvider.cs b/src/graphql-aspnet/Internal/TypeTemplates/RuntimeSchemaItemAttributeProvider.cs new file mode 100644 index 000000000..bb70caf85 --- /dev/null +++ b/src/graphql-aspnet/Internal/TypeTemplates/RuntimeSchemaItemAttributeProvider.cs @@ -0,0 +1,83 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Internal.TypeTemplates +{ + using System; + using System.Collections.Generic; + using System.Reflection; + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Interfaces.Configuration.Templates; + + /// + /// A custom that can provide runtime declared attributes + /// to the templating engine, instead of them being provided at design time on a method. + /// + public class RuntimeSchemaItemAttributeProvider : ICustomAttributeProvider + { + private readonly IGraphQLResolvableSchemaItemDefinition _fieldDef; + private readonly object[] _onlyDefinedAttributes; + private readonly object[] _allAttributes; + + /// + /// Initializes a new instance of the class. + /// + /// The field definition created at runtime + /// that contains the attributes to be provided. + public RuntimeSchemaItemAttributeProvider(IGraphQLResolvableSchemaItemDefinition fieldDefinition) + { + _fieldDef = Validation.ThrowIfNullOrReturn(fieldDefinition, nameof(fieldDefinition)); + + var all = new List(); + var onlyDefined = new List(); + + all.AddRange(_fieldDef.Attributes); + all.AddRange(_fieldDef.Resolver.Method.GetCustomAttributes(true)); + + onlyDefined.AddRange(_fieldDef.Attributes); + + _onlyDefinedAttributes = onlyDefined.ToArray(); + _allAttributes = all.ToArray(); + } + + /// + public object[] GetCustomAttributes(bool inherit) + { + return inherit ? _allAttributes : _onlyDefinedAttributes; + } + + /// + public object[] GetCustomAttributes(Type attributeType, bool inherit) + { + var attribs = this.GetCustomAttributes(inherit); + + var outList = new List(); + foreach (var attrib in attribs) + { + if (Validation.IsCastable(attrib?.GetType(), attributeType)) + outList.Add(attrib); + } + + return outList.ToArray(); + } + + /// + public bool IsDefined(Type attributeType, bool inherit) + { + var attribs = this.GetCustomAttributes(inherit); + foreach (var attrib in attribs) + { + if (attrib?.GetType() == attributeType) + return true; + } + + return false; + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Internal/TypeTemplates/RuntimeSchemaItemTemplate.cs b/src/graphql-aspnet/Internal/TypeTemplates/RuntimeSchemaItemTemplate.cs deleted file mode 100644 index 6f75eaa4f..000000000 --- a/src/graphql-aspnet/Internal/TypeTemplates/RuntimeSchemaItemTemplate.cs +++ /dev/null @@ -1,35 +0,0 @@ -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - -namespace GraphQL.AspNet.Internal.TypeTemplates -{ - using System; - using GraphQL.AspNet.Common; - using GraphQL.AspNet.Directives; - using GraphQL.AspNet.Interfaces.Configuration.Templates; - - /// - /// A template of a schema item generated at runtime rather than via a class defined - /// at compile time. - /// - internal class RuntimeSchemaItemTemplate : GraphDirectiveTemplate - { - private IGraphQLRuntimeSchemaItemDefinition _runtimeDefinition; - - /// - /// Initializes a new instance of the class. - /// - /// The definition, configured at runtime to templatize. - public RuntimeSchemaItemTemplate(IGraphQLRuntimeSchemaItemDefinition definition) - : base(typeof(RuntimeSchemaItemTypeMarker)) - { - _runtimeDefinition = Validation.ThrowIfNullOrReturn(definition, nameof(definition)); - } - } -} \ No newline at end of file diff --git a/src/graphql-aspnet/Internal/TypeTemplates/RuntimeSchemaItemTypeMarker.cs b/src/graphql-aspnet/Internal/TypeTemplates/RuntimeSchemaItemTypeMarker.cs deleted file mode 100644 index 4ac7fb7f0..000000000 --- a/src/graphql-aspnet/Internal/TypeTemplates/RuntimeSchemaItemTypeMarker.cs +++ /dev/null @@ -1,20 +0,0 @@ -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - -namespace GraphQL.AspNet.Internal.TypeTemplates -{ - /// - /// A marker type used internally by the templating system to mark - /// a dynamically built schema item that doesn't necessarily have a concrete - /// matching type. This class cannot be inherited. - /// - internal sealed class RuntimeSchemaItemTypeMarker - { - } -} \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/GraphSchemaManager.cs b/src/graphql-aspnet/Schemas/GraphSchemaManager.cs index 7bedd0c8e..1279a12b1 100644 --- a/src/graphql-aspnet/Schemas/GraphSchemaManager.cs +++ b/src/graphql-aspnet/Schemas/GraphSchemaManager.cs @@ -344,6 +344,21 @@ private void AddActionAsField(IObjectGraphType parentType, IGraphFieldTemplate a } } + /// + /// Adds a runtime declared field (with its assigned resolver) as a field in the schema. + /// + /// The field definition to add to the schema. + public void AddRuntimeFieldDeclaration(IGraphQLRuntimeResolvedFieldDefinition fieldDefinition) + { + Validation.ThrowIfNull(fieldDefinition, nameof(fieldDefinition)); + var template = new RuntimeGraphControllerTemplate(fieldDefinition); + + template.Parse(); + template.ValidateOrThrow(); + + this.AddController(template); + } + /// /// Inspects and adds the given type to the schema as a graph type or a registered controller depending /// on the type. The type kind will be automatically inferred or an error will be thrown. @@ -436,9 +451,9 @@ private void EnsureDependents(IGraphItemDependencies dependencySet) } /// - /// Clears, builds and caches the introspection metadata to describe this schema. If introspection + /// Clears, builds and caches the introspection metadata used to describe this schema. If introspection /// fields have not been added to the schema this method does nothing. No changes to the schema - /// items themselves happens during this method. + /// items themselves happens during this method call. /// public void RebuildIntrospectionData() { diff --git a/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeControllerDefinition.cs b/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeControllerDefinition.cs deleted file mode 100644 index ce7b51ebe..000000000 --- a/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeControllerDefinition.cs +++ /dev/null @@ -1,33 +0,0 @@ -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - -namespace GraphQL.AspNet.Schemas.RuntimeSchemaItemDefinitions -{ - using System.Collections.Generic; - using System.Linq; - using GraphQL.AspNet.Interfaces.Configuration.Templates; - - /// - /// Represents a single controller that contains ALL of the runtime configured - /// fields. (e.g. all the fields created via minimal api calls). - /// - internal class RuntimeControllerDefinition - { - private List _fields; - - /// - /// Initializes a new instance of the class. - /// - /// The fields that are to be a part of this controller. - public RuntimeControllerDefinition(IEnumerable fields) - { - _fields = new List(fields ?? Enumerable.Empty()); - } - } -} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/SingleMethodGraphControllerTemplate.cs b/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/SingleMethodGraphControllerTemplate.cs index feaa2f4f0..cc16e52bb 100644 --- a/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/SingleMethodGraphControllerTemplate.cs +++ b/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/SingleMethodGraphControllerTemplate.cs @@ -9,8 +9,8 @@ namespace GraphQL.AspNet.Tests.Framework.PipelineContextBuilders { - using System.Reflection; using GraphQL.AspNet.Controllers; + using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Internal.TypeTemplates; /// @@ -41,9 +41,9 @@ public SingleMethodGraphControllerTemplate(string methodName = null) /// /// The member information to check. /// true if the info represents a possible graph field; otherwise, false. - protected override bool CouldBeGraphField(MemberInfo memberInfo) + protected override bool CouldBeGraphField(IFieldMemberInfoProvider memberInfo) { - if (_methodName != null && memberInfo.Name != _methodName) + if (_methodName != null && memberInfo.MemberInfo.Name != _methodName) return false; return base.CouldBeGraphField(memberInfo); diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionRuntimeFieldTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionRuntimeFieldTests.cs new file mode 100644 index 000000000..58f44c7fa --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionRuntimeFieldTests.cs @@ -0,0 +1,51 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Execution +{ + using System.Threading.Tasks; + using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Tests.Framework; + using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using NUnit.Framework; + + [TestFixture] + public class GeneralQueryExecutionRuntimeFieldTests + { + [Test] + public async Task BasicMappedQuery_ExecutesMethod() + { + var ServerBuilder = new TestServerBuilder() + .AddGraphQL(o => + { + o.MapQuery("/field1/field2", (int a, int b) => + { + return a + b; + }); + }); + + var server = ServerBuilder.Build(); + var builder = server.CreateQueryContextBuilder(); + builder.AddQueryText(@"query { field1 { field2(a: 5, b: 33 } } }"); + + // supply no values, allowing the defaults to take overand returning the single + // requested "Property1" with the default string defined on the method. + var result = await server.RenderResult(builder); + CommonAssertions.AreEqualJsonStrings( + @"{ + ""data"": { + ""field1"": { + ""field2"" : 38 + } + } + }", + result); + } + } +} \ No newline at end of file From d38cc8fd7ecf6a1ad68b02d75563329e2447e7ac Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Mon, 26 Jun 2023 18:14:47 -0700 Subject: [PATCH 12/63] WIP, added support for static minimal api resolvers --- .../Common/Generics/InstanceFactory.cs | 143 +++++++++++++++--- .../Common/Generics/MethodInvoker.cs | 11 +- .../Controllers/GraphControllerBase.cs | 6 + .../RuntimeFieldExecutionController.cs | 19 ++- .../TypeTemplates/GraphControllerTemplate.cs | 2 +- .../MethodGraphFieldTemplateBase.cs | 7 - .../NonLeafGraphTypeTemplateBase.cs | 4 + .../RuntimeGraphControllerTemplate.cs | 6 - .../Common/InstanceFactoryTests.cs | 79 ++++++++-- .../GeneralQueryExecutionRuntimeFieldTests.cs | 86 ++++++++++- .../SampleDelegatesForMinimalApi.cs | 27 ++++ .../Templating/ControllerTemplateTests.cs | 13 ++ .../ControllerWithStaticMethod.cs | 29 ++++ .../ObjectGraphTypeTemplateTests.cs | 13 ++ .../ObjectTypeTests/ObjectWithStatics.cs | 34 +++++ 15 files changed, 428 insertions(+), 51 deletions(-) create mode 100644 src/unit-tests/graphql-aspnet-tests/Execution/TestData/RuntimeFieldTest/SampleDelegatesForMinimalApi.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Internal/Templating/ControllerTestData/ControllerWithStaticMethod.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/ObjectWithStatics.cs diff --git a/src/graphql-aspnet/Common/Generics/InstanceFactory.cs b/src/graphql-aspnet/Common/Generics/InstanceFactory.cs index 5f1fc85c6..a4ca2d443 100644 --- a/src/graphql-aspnet/Common/Generics/InstanceFactory.cs +++ b/src/graphql-aspnet/Common/Generics/InstanceFactory.cs @@ -24,7 +24,8 @@ namespace GraphQL.AspNet.Common.Generics internal static class InstanceFactory { private static readonly ConcurrentDictionary, ObjectActivator> CACHED_OBJECT_CREATORS; - private static readonly ConcurrentDictionary CACHED_METHOD_INVOKERS; + private static readonly ConcurrentDictionary CACHED_INSTANCE_METHOD_INVOKERS; + private static readonly ConcurrentDictionary CACHED_STATIC_METHOD_INVOKERS; private static readonly ConcurrentDictionary CACHED_PROPERTY_SETTER_INVOKERS; private static readonly ConcurrentDictionary CACHED_PROPERTY_GETTER_INVOKERS; @@ -34,7 +35,8 @@ internal static class InstanceFactory static InstanceFactory() { CACHED_OBJECT_CREATORS = new ConcurrentDictionary, ObjectActivator>(); - CACHED_METHOD_INVOKERS = new ConcurrentDictionary(); + CACHED_INSTANCE_METHOD_INVOKERS = new ConcurrentDictionary(); + CACHED_STATIC_METHOD_INVOKERS = new ConcurrentDictionary(); CACHED_PROPERTY_SETTER_INVOKERS = new ConcurrentDictionary(); CACHED_PROPERTY_GETTER_INVOKERS = new ConcurrentDictionary(); } @@ -45,7 +47,8 @@ static InstanceFactory() public static void Clear() { CACHED_OBJECT_CREATORS.Clear(); - CACHED_METHOD_INVOKERS.Clear(); + CACHED_INSTANCE_METHOD_INVOKERS.Clear(); + CACHED_STATIC_METHOD_INVOKERS.Clear(); CACHED_PROPERTY_SETTER_INVOKERS.Clear(); CACHED_PROPERTY_GETTER_INVOKERS.Clear(); } @@ -169,17 +172,17 @@ public static PropertyGetterCollection CreatePropertyGetterInvokerCollection(Typ } /// - /// Creates a compiled lamda expression to invoke an arbitrary method via a common set of parameters. This lamda is cached for any future use greatly speeding up - /// the invocation. + /// Creates a compiled lamda expression to invoke an arbitrary method via a common set of parameters on an object instance. + /// This lamda is cached for any future use greatly speeding up the invocation. /// /// The method information. /// Func<System.Object, System.Object[], System.Object>. - public static MethodInvoker CreateInstanceMethodInvoker(MethodInfo methodInfo) + public static InstanceMethodInvoker CreateInstanceMethodInvoker(MethodInfo methodInfo) { if (methodInfo == null) return null; - if (CACHED_METHOD_INVOKERS.TryGetValue(methodInfo, out var invoker)) + if (CACHED_INSTANCE_METHOD_INVOKERS.TryGetValue(methodInfo, out var invoker)) return invoker; if (methodInfo.IsStatic) @@ -194,17 +197,114 @@ public static MethodInvoker CreateInstanceMethodInvoker(MethodInfo methodInfo) "This instance creator only supports methods with a return value."); } - invoker = CreateMethodInvoker(methodInfo); - CACHED_METHOD_INVOKERS.TryAdd(methodInfo, invoker); + invoker = CompileInstanceMethodInvoker(methodInfo); + CACHED_INSTANCE_METHOD_INVOKERS.TryAdd(methodInfo, invoker); return invoker; } /// - /// Creates the method invoker expression and compiles the resultant lambda. + /// Creates a compiled lamda expression to invoke an arbitrary static method via a common set of parameters. + /// This lamda is cached for any future use greatly speeding up the invocation. + /// + /// The method to create an expression for. + /// StaticMethodInvoker. + public static StaticMethodInvoker CreateStaticMethodInvoker(MethodInfo methodInfo) + { + if (methodInfo == null) + return null; + + if (CACHED_STATIC_METHOD_INVOKERS.TryGetValue(methodInfo, out var invoker)) + return invoker; + + if (!methodInfo.IsStatic) + { + throw new ArgumentException($"The method '{methodInfo.Name}' on type '{methodInfo.DeclaringType.FriendlyName()}' is NOT static " + + "and cannot be used to create a static method reference."); + } + + if (methodInfo.ReturnType == typeof(void)) + { + throw new ArgumentException($"The method '{methodInfo.Name}' on type '{methodInfo.DeclaringType.FriendlyName()}' does not return a value. " + + "This instance creator only supports methods with a return value."); + } + + invoker = CompileStaticMethodInvoker(methodInfo); + CACHED_STATIC_METHOD_INVOKERS.TryAdd(methodInfo, invoker); + return invoker; + } + + /// + /// Compiles the method invoker expression for a static method and compiles the resultant lambda. /// /// The method to create an expression for. /// MethodInvoker. - private static MethodInvoker CreateMethodInvoker(MethodInfo methodInfo) + private static StaticMethodInvoker CompileStaticMethodInvoker(MethodInfo methodInfo) + { + Validation.ThrowIfNull(methodInfo, nameof(methodInfo)); + + // ------------------------------------------- + // Function call parameters + // ------------------------------------------- + // e.g. + // object[] paramSet = new object[]; + // "var returnValue = invoke(paramSet); + // + // create a single param of type object[] tha will hold the variable length of method arguments being passed in + ParameterExpression inputArguments = Expression.Parameter(typeof(object[]), "args"); + + // ------------------------------------------- + // method body + // ------------------------------------------- + + // invocation parameters to pass to the method + ParameterInfo[] paramsInfo = methodInfo.GetParameters(); + + // a set of expressions that represents + // a casting of each supplied object to its specific type for invocation + Expression[] argsAssignments = new Expression[paramsInfo.Length]; + + // pick each arg from the supplied method parameters and create a expression + // that casts them into the required type for the parameter position on the method + for (var i = 0; i < paramsInfo.Length; i++) + { + Expression index = Expression.Constant(i); + Type paramType = paramsInfo[i].ParameterType; + Expression paramAccessorExp = Expression.ArrayIndex(inputArguments, index); + if (paramType.IsValueType) + argsAssignments[i] = Expression.Unbox(paramAccessorExp, paramType); + else + argsAssignments[i] = Expression.Convert(paramAccessorExp, paramType); + } + + // a direct call to the method on the invokable object with the supplied parameters + var methodCall = Expression.Call(methodInfo, argsAssignments); + + // Execute the method call and assign its output to returnedVariable + var returnedVariable = Expression.Variable(methodInfo.ReturnType); + var methodCallResultAssigned = Expression.Assign(returnedVariable, methodCall); + + // box the method result into an object + var boxedResult = Expression.Variable(typeof(object)); + var boxedResultAssignment = Expression.Assign(boxedResult, Expression.Convert(returnedVariable, typeof(object))); + + // assembly the method body + var methodBody = Expression.Block( + new ParameterExpression[] { returnedVariable, boxedResult }, + methodCallResultAssigned, + boxedResultAssignment, + boxedResult); + + // Create lambda expression that accepts the "this" parameter and the args from the user. + var lambda = Expression.Lambda(methodBody, new ParameterExpression[] { inputArguments }); + return lambda.Compile(); + } + + /// + /// Compiles the method invoker expression for an instance based method and compiles the resultant lambda. + /// + /// The method to create an expression for. + /// InstanceMethodInvoker. + private static InstanceMethodInvoker CompileInstanceMethodInvoker(MethodInfo methodInfo) { Validation.ThrowIfNull(methodInfo, nameof(methodInfo)); @@ -224,7 +324,7 @@ private static MethodInvoker CreateMethodInvoker(MethodInfo methodInfo) // ------------------------------------------- // cast the input object to its required Type var castedObjectToInvokeOn = Expression.Variable(declaredType); - var castOperation = Expression.Assign(castedObjectToInvokeOn, Expression.Convert(objectToInvokeOn, declaredType)); + var castingOperation = Expression.Assign(castedObjectToInvokeOn, Expression.Convert(objectToInvokeOn, declaredType)); // invocation parameters to pass to the method ParameterInfo[] paramsInfo = methodInfo.GetParameters(); @@ -265,14 +365,14 @@ private static MethodInvoker CreateMethodInvoker(MethodInfo methodInfo) var methodBody = Expression.Block( new ParameterExpression[] { castedObjectToInvokeOn, returnedVariable, boxedResult }, - castOperation, + castingOperation, methodCallResultAssigned, boxedResultAssignment, reassignReffedValue, boxedResult); // Create lambda expression that accepts the "this" parameter and the args from the user. - var lambda = Expression.Lambda(methodBody, new ParameterExpression[] { objectToInvokeOn, inputArguments }); + var lambda = Expression.Lambda(methodBody, new ParameterExpression[] { objectToInvokeOn, inputArguments }); return lambda.Compile(); } @@ -458,19 +558,26 @@ private static IReadOnlyList CreateConstructorTypeList(params Type[] types /// Gets the creators cached to this application instance. /// /// The cached creators. - public static IReadOnlyDictionary, ObjectActivator> ObjectCreators => CACHED_OBJECT_CREATORS; + public static IReadOnlyDictionary, ObjectActivator> ObjectCreators => CACHED_OBJECT_CREATORS; + + /// + /// Gets the collection of cached method invokers for fast invocation of methods on target + /// objects in this app instance. + /// + /// The method invokers. + public static IReadOnlyDictionary InstanceMethodInvokers => CACHED_INSTANCE_METHOD_INVOKERS; /// - /// Gets the collection of cached method invokers for fast invocation in this app instance. + /// Gets the collection of cached static method invokers for fast invocation in this app instance. /// /// The method invokers. - public static IReadOnlyDictionary MethodInvokers => CACHED_METHOD_INVOKERS; + public static IReadOnlyDictionary StaticMethodInvokers => CACHED_STATIC_METHOD_INVOKERS; /// /// Gets the collection of cached property setter invokers for fast invocation in this app instance. /// /// The cached collection of property "setter" invokers. - public static IReadOnlyDictionary PropertySetterInvokers => CACHED_PROPERTY_SETTER_INVOKERS; + public static IReadOnlyDictionary PropertySetterInvokers => CACHED_PROPERTY_SETTER_INVOKERS; /// /// Gets the collection of cached property getter invokers for fast invocation in this app instance. diff --git a/src/graphql-aspnet/Common/Generics/MethodInvoker.cs b/src/graphql-aspnet/Common/Generics/MethodInvoker.cs index 6a2ae172c..001a5c4c9 100644 --- a/src/graphql-aspnet/Common/Generics/MethodInvoker.cs +++ b/src/graphql-aspnet/Common/Generics/MethodInvoker.cs @@ -6,6 +6,7 @@ // -- // License: MIT // ************************************************************* + namespace GraphQL.AspNet.Common.Generics { /// @@ -14,5 +15,13 @@ namespace GraphQL.AspNet.Common.Generics /// The object instance to invoke on. /// The parameters to pass the method call. /// The result of the call. - internal delegate object MethodInvoker(ref object instanceToInvokeOn, params object[] methodParameters); + internal delegate object InstanceMethodInvoker(ref object instanceToInvokeOn, params object[] methodParameters); + + /// + /// A representation of a compiled lamda to invoke a static method not attached to a specific + /// object instance. + /// + /// The parameters to pass the method call. + /// The result of the call. + internal delegate object StaticMethodInvoker(params object[] methodParameters); } \ No newline at end of file diff --git a/src/graphql-aspnet/Controllers/GraphControllerBase.cs b/src/graphql-aspnet/Controllers/GraphControllerBase.cs index 42f5209ce..576889073 100644 --- a/src/graphql-aspnet/Controllers/GraphControllerBase.cs +++ b/src/graphql-aspnet/Controllers/GraphControllerBase.cs @@ -142,6 +142,12 @@ protected virtual object CreateAndInvokeAction(IGraphFieldResolverMethod resolve "does not own the method."); } + if (resolver.Method.IsStatic) + { + throw new TargetException($"Unable to invoke action '{_action.Route.Path}' on controller '{this.GetType().FriendlyName()}'. The method " + + "is static and cannot be directly invoked on this controller instance."); + } + var invoker = InstanceFactory.CreateInstanceMethodInvoker(resolver.Method); var controllerRef = this as object; diff --git a/src/graphql-aspnet/Controllers/RuntimeFieldExecutionController.cs b/src/graphql-aspnet/Controllers/RuntimeFieldExecutionController.cs index b09fb2139..9b2618ca8 100644 --- a/src/graphql-aspnet/Controllers/RuntimeFieldExecutionController.cs +++ b/src/graphql-aspnet/Controllers/RuntimeFieldExecutionController.cs @@ -23,12 +23,19 @@ internal sealed class RuntimeFieldExecutionController : GraphController /// protected override object CreateAndInvokeAction(IGraphFieldResolverMethod resolver, object[] invocationArguments) { - // for minimal api resolvers create an instance of the - // "runtime declared owner type" and invoke using it - var instance = InstanceFactory.CreateInstance(resolver.Method.DeclaringType); - var invoker = InstanceFactory.CreateInstanceMethodInvoker(resolver.Method); - - return invoker(ref instance, invocationArguments); + // minimal api resolvers are allowed to be static since there is no + // extra context to setup or make available such as 'this.User' etc. + if (resolver.Method.IsStatic) + { + var invoker = InstanceFactory.CreateStaticMethodInvoker(resolver.Method); + return invoker(invocationArguments); + } + else + { + var invoker = InstanceFactory.CreateInstanceMethodInvoker(resolver.Method); + var instance = InstanceFactory.CreateInstance(resolver.Method.DeclaringType); + return invoker(ref instance, invocationArguments); + } } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Internal/TypeTemplates/GraphControllerTemplate.cs b/src/graphql-aspnet/Internal/TypeTemplates/GraphControllerTemplate.cs index 9a2410136..ce462ebae 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/GraphControllerTemplate.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/GraphControllerTemplate.cs @@ -110,7 +110,7 @@ public override void ValidateOrThrow() /// protected override bool CouldBeGraphField(IFieldMemberInfoProvider fieldProvider) { - if (fieldProvider?.MemberInfo == null || !(fieldProvider.MemberInfo is MethodInfo)) + if (fieldProvider?.MemberInfo == null || !(fieldProvider.MemberInfo is MethodInfo methodInfo)) return false; if (!base.CouldBeGraphField(fieldProvider)) diff --git a/src/graphql-aspnet/Internal/TypeTemplates/MethodGraphFieldTemplateBase.cs b/src/graphql-aspnet/Internal/TypeTemplates/MethodGraphFieldTemplateBase.cs index b9352e0f7..3ae1f6a62 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/MethodGraphFieldTemplateBase.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/MethodGraphFieldTemplateBase.cs @@ -92,13 +92,6 @@ public override void ValidateOrThrow() { base.ValidateOrThrow(); - if (this.Method.IsStatic) - { - throw new GraphTypeDeclarationException( - $"Invalid graph method declaration. The method '{this.InternalFullName}' is static. Only " + - "instance members can be registered as field."); - } - if (this.ExpectedReturnType == null) { throw new GraphTypeDeclarationException( diff --git a/src/graphql-aspnet/Internal/TypeTemplates/NonLeafGraphTypeTemplateBase.cs b/src/graphql-aspnet/Internal/TypeTemplates/NonLeafGraphTypeTemplateBase.cs index 4f9fa8f8d..d7e87bcce 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/NonLeafGraphTypeTemplateBase.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/NonLeafGraphTypeTemplateBase.cs @@ -212,6 +212,8 @@ protected virtual bool CouldBeGraphField(IFieldMemberInfoProvider fieldProvider) switch (fieldProvider.MemberInfo) { case MethodInfo mi: + if (mi.IsStatic) + return false; if (!GraphValidation.IsValidGraphType(mi.ReturnType, false)) return false; if (mi.GetParameters().Any(x => !GraphValidation.IsValidGraphType(x.ParameterType, false))) @@ -221,6 +223,8 @@ protected virtual bool CouldBeGraphField(IFieldMemberInfoProvider fieldProvider) case PropertyInfo pi: if (pi.GetGetMethod() == null) return false; + if (pi.GetGetMethod().IsStatic) + return false; if (pi.GetIndexParameters().Length > 0) return false; diff --git a/src/graphql-aspnet/Internal/TypeTemplates/RuntimeGraphControllerTemplate.cs b/src/graphql-aspnet/Internal/TypeTemplates/RuntimeGraphControllerTemplate.cs index 74729d20d..91f85b2a3 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/RuntimeGraphControllerTemplate.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/RuntimeGraphControllerTemplate.cs @@ -10,15 +10,10 @@ namespace GraphQL.AspNet.Internal.TypeTemplates { using System.Collections.Generic; - using System.Reflection; - using GraphQL.AspNet.Attributes; - using GraphQL.AspNet.Common; - using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Interfaces.Configuration.Templates; using GraphQL.AspNet.Interfaces.Internal; - using GraphQL.AspNet.Schemas.Structural; /// /// A "controller template" representing a single runtime configured field (e.g. minimal api). @@ -27,7 +22,6 @@ namespace GraphQL.AspNet.Internal.TypeTemplates internal class RuntimeGraphControllerTemplate : GraphControllerTemplate { private readonly IFieldMemberInfoProvider _fieldProvider; - private readonly IGraphQLResolvableSchemaItemDefinition _fieldDefinition; /// /// Initializes a new instance of the class. diff --git a/src/unit-tests/graphql-aspnet-tests/Common/InstanceFactoryTests.cs b/src/unit-tests/graphql-aspnet-tests/Common/InstanceFactoryTests.cs index c945ad88c..db499607e 100644 --- a/src/unit-tests/graphql-aspnet-tests/Common/InstanceFactoryTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Common/InstanceFactoryTests.cs @@ -32,6 +32,10 @@ public void DivideNumbers(int arg1, int arg2) { } + public static void DivideNumbersAsStaticMethod(int arg1, int arg2) + { + } + public static int SubtractNumbers(int arg1, int arg2) { return arg1 - arg2; @@ -139,14 +143,14 @@ public void ObjectActivator_Struct_NonParameterizedConstructorOfStructWithParame } [Test] - public void MethodInvoker_NullMethodInfo_ReturnsNull() + public void InstanceMethodInvoker_NullMethodInfo_ReturnsNull() { var invoker = InstanceFactory.CreateInstanceMethodInvoker(null); Assert.IsNull(invoker); } [Test] - public void MethodInvoker_StaticMethodInfo_ThrowsException() + public void InstanceMethodInvoker_StaticMethodInfo_ThrowsException() { InstanceFactory.Clear(); var methodInfo = typeof(InstanceFactoryTests).GetMethod(nameof(InstanceFactoryTests.SubtractNumbers)); @@ -158,7 +162,7 @@ public void MethodInvoker_StaticMethodInfo_ThrowsException() } [Test] - public void MethodInvoker_VoidReturn_ThrowsException() + public void InstanceMethodInvoker_VoidReturn_ThrowsException() { InstanceFactory.Clear(); var methodInfo = typeof(InstanceFactoryTests).GetMethod(nameof(InstanceFactoryTests.DivideNumbers)); @@ -170,7 +174,7 @@ public void MethodInvoker_VoidReturn_ThrowsException() } [Test] - public void MethodInvoker_StandardInvoke_ReturnsValue() + public void InstanceMethodInvoker_StandardInvoke_ReturnsValue() { InstanceFactory.Clear(); var methodInfo = typeof(InstanceFactoryTests).GetMethod(nameof(InstanceFactoryTests.AddNumbers)); @@ -183,12 +187,12 @@ public void MethodInvoker_StandardInvoke_ReturnsValue() Assert.AreEqual(8, result); // ensure it was cached. - Assert.AreEqual(1, InstanceFactory.MethodInvokers.Count); + Assert.AreEqual(1, InstanceFactory.InstanceMethodInvokers.Count); InstanceFactory.Clear(); } [Test] - public void MethodInvoker_StandardInvoke_CachesAndReturnsValue() + public void InstanceMethodInvoker_StandardInvoke_CachesAndReturnsValue() { InstanceFactory.Clear(); var methodInfo = typeof(InstanceFactoryTests).GetMethod(nameof(InstanceFactoryTests.AddNumbers)); @@ -208,12 +212,12 @@ public void MethodInvoker_StandardInvoke_CachesAndReturnsValue() // ensure it was cached. Assert.AreSame(invoker, secondInvoker); - Assert.AreEqual(1, InstanceFactory.MethodInvokers.Count); + Assert.AreEqual(1, InstanceFactory.InstanceMethodInvokers.Count); InstanceFactory.Clear(); } [Test] - public void MethodInvoker_Struct_StandardInvoke_ReturnsValue_StructIsModified() + public void InstanceMethodInvoker_Struct_StandardInvoke_ReturnsValue_StructIsModified() { InstanceFactory.Clear(); var methodInfo = typeof(StructWithMethod).GetMethod(nameof(StructWithMethod.AddAndSet)); @@ -230,7 +234,7 @@ public void MethodInvoker_Struct_StandardInvoke_ReturnsValue_StructIsModified() Assert.AreEqual("propValue1", resultCast.Property1); // ensure it was cached. - Assert.AreEqual(1, InstanceFactory.MethodInvokers.Count); + Assert.AreEqual(1, InstanceFactory.InstanceMethodInvokers.Count); InstanceFactory.Clear(); } @@ -316,5 +320,62 @@ public void PropertyGetterInvoker_StandardInvoke_ReturnsValue() InstanceFactory.Clear(); } + + [Test] + public void StaticMethodInvoker_NullMethodInfo_ReturnsNull() + { + var invoker = InstanceFactory.CreateStaticMethodInvoker(null); + Assert.IsNull(invoker); + } + + [Test] + public void StaticMethodInvoker_VoidReturn_ThrowsException() + { + InstanceFactory.Clear(); + var methodInfo = typeof(InstanceFactoryTests).GetMethod(nameof(InstanceFactoryTests.DivideNumbersAsStaticMethod)); + + Assert.Throws(() => + { + var invoker = InstanceFactory.CreateStaticMethodInvoker(methodInfo); + }); + } + + [Test] + public void StaticMethodInvoker_StandardInvoke_ReturnsValue() + { + InstanceFactory.Clear(); + var methodInfo = typeof(InstanceFactoryTests).GetMethod(nameof(InstanceFactoryTests.SubtractNumbers)); + + var invoker = InstanceFactory.CreateStaticMethodInvoker(methodInfo); + + var result = invoker(5, 3); + Assert.AreEqual(2, result); + + // ensure it was cached. + Assert.AreEqual(1, InstanceFactory.StaticMethodInvokers.Count); + InstanceFactory.Clear(); + } + + [Test] + public void StaticMethodInvoker_StandardInvoke_CachesAndReturnsValue() + { + InstanceFactory.Clear(); + var methodInfo = typeof(InstanceFactoryTests).GetMethod(nameof(InstanceFactoryTests.SubtractNumbers)); + + var invoker = InstanceFactory.CreateStaticMethodInvoker(methodInfo); + + var result = invoker(5, 3); + Assert.AreEqual(2, result); + + var secondInvoker = InstanceFactory.CreateStaticMethodInvoker(methodInfo); + + result = secondInvoker(9, 1); + Assert.AreEqual(8, result); + + // ensure it was cached. + Assert.AreSame(invoker, secondInvoker); + Assert.AreEqual(1, InstanceFactory.StaticMethodInvokers.Count); + InstanceFactory.Clear(); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionRuntimeFieldTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionRuntimeFieldTests.cs index 58f44c7fa..2441d1bf6 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionRuntimeFieldTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionRuntimeFieldTests.cs @@ -11,6 +11,7 @@ namespace GraphQL.AspNet.Tests.Execution { using System.Threading.Tasks; using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Tests.Execution.TestData.RuntimeFieldTest; using GraphQL.AspNet.Tests.Framework; using GraphQL.AspNet.Tests.Framework.CommonHelpers; using NUnit.Framework; @@ -21,7 +22,7 @@ public class GeneralQueryExecutionRuntimeFieldTests [Test] public async Task BasicMappedQuery_ExecutesMethod() { - var ServerBuilder = new TestServerBuilder() + var serverBuilder = new TestServerBuilder() .AddGraphQL(o => { o.MapQuery("/field1/field2", (int a, int b) => @@ -30,10 +31,89 @@ public async Task BasicMappedQuery_ExecutesMethod() }); }); - var server = ServerBuilder.Build(); + var server = serverBuilder.Build(); var builder = server.CreateQueryContextBuilder(); builder.AddQueryText(@"query { field1 { field2(a: 5, b: 33 } } }"); + var result = await server.RenderResult(builder); + CommonAssertions.AreEqualJsonStrings( + @"{ + ""data"": { + ""field1"": { + ""field2"" : 38 + } + } + }", + result); + } + + [Test] + public async Task BasicMappedMutation_ExecutesMethod() + { + var serverBuilder = new TestServerBuilder() + .AddGraphQL(o => + { + o.MapMutation("/field1/field2", (int a, int b) => + { + return a + b; + }); + }); + + var server = serverBuilder.Build(); + var builder = server.CreateQueryContextBuilder(); + builder.AddQueryText(@"mutation { field1 { field2(a: 4, b: 33 } } }"); + + var result = await server.RenderResult(builder); + CommonAssertions.AreEqualJsonStrings( + @"{ + ""data"": { + ""field1"": { + ""field2"" : 37 + } + } + }", + result); + } + + [Test] + public async Task StaticMethodMappedDelegate_ThrowsValidationException() + { + var serverBuilder = new TestServerBuilder() + .AddGraphQL(o => + { + o.MapQuery("/field1/field2", SampleDelegatesForMinimalApi.StaticMethod); + }); + + var server = serverBuilder.Build(); + var builder = server.CreateQueryContextBuilder(); + builder.AddQueryText(@"query { field1 { field2(a: 4, b: 37 } } }"); + + var result = await server.RenderResult(builder); + CommonAssertions.AreEqualJsonStrings( + @"{ + ""data"": { + ""field1"": { + ""field2"" : 41 + } + } + }", + result); + } + + [Test] + public async Task InstanceMethodMappedDelegate_ExecutesMethod() + { + var data = new SampleDelegatesForMinimalApi(); + var serverBuilder = new TestServerBuilder() + .AddGraphQL(o => + { + o.MapQuery("/field1/field2", data.InstanceMethod); + }); + + var server = serverBuilder.Build(); + var builder = server.CreateQueryContextBuilder(); + builder.AddQueryText(@"query { field1 { field2(a: 4, b: 37 } } }"); + // supply no values, allowing the defaults to take overand returning the single // requested "Property1" with the default string defined on the method. var result = await server.RenderResult(builder); @@ -41,7 +121,7 @@ public async Task BasicMappedQuery_ExecutesMethod() @"{ ""data"": { ""field1"": { - ""field2"" : 38 + ""field2"" : 41 } } }", diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/RuntimeFieldTest/SampleDelegatesForMinimalApi.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/RuntimeFieldTest/SampleDelegatesForMinimalApi.cs new file mode 100644 index 000000000..61209a2d5 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/RuntimeFieldTest/SampleDelegatesForMinimalApi.cs @@ -0,0 +1,27 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Execution.TestData.RuntimeFieldTest +{ + public class SampleDelegatesForMinimalApi + { + public static int StaticMethod(int a, int b) + { + return a + b; + } + + public int InstanceMethod(int a, int b) + { + this.InstanceMethodCalls += 1; + return a + b; + } + + public int InstanceMethodCalls { get; set; } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ControllerTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ControllerTemplateTests.cs index 97de5b6b4..8f63a30d5 100644 --- a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ControllerTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ControllerTemplateTests.cs @@ -111,5 +111,18 @@ public void Parse_AssignedDirective_IsTemplatized() Assert.AreEqual(typeof(DirectiveWithArgs), appliedDirective.DirectiveType); Assert.AreEqual(new object[] { 101, "controller arg" }, appliedDirective.Arguments); } + + [Test] + public void Parse_StaticMethodsWithProperGraphFieldDeclarations_AreSkipped() + { + var template = new GraphControllerTemplate(typeof(ControllerWithStaticMethod)); + template.Parse(); + template.ValidateOrThrow(); + + Assert.AreEqual(1, template.Actions.Count()); + + var action = template.Actions.First(); + Assert.AreEqual(nameof(ControllerWithStaticMethod.InstanceMethod), action.Name); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ControllerTestData/ControllerWithStaticMethod.cs b/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ControllerTestData/ControllerWithStaticMethod.cs new file mode 100644 index 000000000..3572c138a --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ControllerTestData/ControllerWithStaticMethod.cs @@ -0,0 +1,29 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Internal.Templating.ControllerTestData +{ + using GraphQL.AspNet.Attributes; + using GraphQL.AspNet.Controllers; + + public class ControllerWithStaticMethod : GraphController + { + [Query] + public static int StaticMethod(int a, int b) + { + return a - b; + } + + [Query] + public int InstanceMethod(int a, int b) + { + return a + b; + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectGraphTypeTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectGraphTypeTemplateTests.cs index 52c09bd31..cef64bcb3 100644 --- a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectGraphTypeTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectGraphTypeTemplateTests.cs @@ -421,5 +421,18 @@ public void Parse_NonExplicitMethodBasedField_IsSeenAsTemplatefield() Assert.IsTrue(template.FieldTemplates.Any(x => x.Value.InternalName == nameof(ObjectThatInheritsNonExplicitMethodField.FieldOnObject))); Assert.IsTrue(template.FieldTemplates.Any(x => x.Value.InternalName == nameof(ObjectWithNonExplicitMethodField.FieldOnBaseObject))); } + + [Test] + public void Parse_StaticMethodsWithProperGraphFieldDeclarations_AreSkipped() + { + var template = new ObjectGraphTypeTemplate(typeof(ObjectWithStatics)); + template.Parse(); + template.ValidateOrThrow(); + + Assert.AreEqual(2, template.FieldTemplates.Count()); + + Assert.IsNotNull(template.FieldTemplates.Values.SingleOrDefault(x => x.Route.Name == nameof(ObjectWithStatics.InstanceProperty))); + Assert.IsNotNull(template.FieldTemplates.Values.SingleOrDefault(x => x.Route.Name == nameof(ObjectWithStatics.InstanceMethod))); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/ObjectWithStatics.cs b/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/ObjectWithStatics.cs new file mode 100644 index 000000000..b685010a0 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/ObjectWithStatics.cs @@ -0,0 +1,34 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests +{ + using GraphQL.AspNet.Attributes; + + public class ObjectWithStatics + { + [GraphField] + public static int StaticMethod(int a, int b) + { + return a - b; + } + + [GraphField] + public static int StaticProperty { get; set; } + + [GraphField] + public int InstanceMethod(int a, int b) + { + return a + b; + } + + [GraphField] + public int InstanceProperty { get; } + } +} \ No newline at end of file From b690d28bd3d39e93bc3c6ac3e745584cd668731b Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Tue, 27 Jun 2023 16:14:45 -0700 Subject: [PATCH 13/63] WIP, added support for graph actions in minimal api --- .../Common/Generics/MethodInvoker.cs | 2 +- ...chemaItemDefinitionExtensions_Internals.cs | 19 +++ ...chemaItemDefinitionExtensions_Mutations.cs | 8 +- ...eSchemaItemDefinitionExtensions_Queries.cs | 8 +- ...aItemDefinitionExtensions_VirtualFields.cs | 97 ++++++------ .../ActionResults/GraphActionResult.cs | 148 ++++++++++++++++++ .../Controllers/GraphControllerBase.cs | 2 +- .../GraphController_ActionResults.cs | 21 ++- .../TypeTemplates/GraphFieldTemplateBase.cs | 2 +- .../BaseRuntimeControllerActionDefinition.cs | 12 +- .../Templates/MappedMutationGroupTests.cs | 124 +++++++++++++++ .../Templates/MappedMutationTemplateTests.cs | 38 ----- ...plateTests.cs => MappedQueryGroupTests.cs} | 66 +++----- .../Templates/MappedQueryTemplateTests.cs | 37 ----- .../GeneralQueryExecutionRuntimeFieldTests.cs | 118 ++++++++++++++ 15 files changed, 518 insertions(+), 184 deletions(-) create mode 100644 src/graphql-aspnet/Controllers/ActionResults/GraphActionResult.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedMutationGroupTests.cs rename src/unit-tests/graphql-aspnet-tests/Configuration/Templates/{UnresolvedFieldTemplateTests.cs => MappedQueryGroupTests.cs} (57%) diff --git a/src/graphql-aspnet/Common/Generics/MethodInvoker.cs b/src/graphql-aspnet/Common/Generics/MethodInvoker.cs index 001a5c4c9..61a0c1cdc 100644 --- a/src/graphql-aspnet/Common/Generics/MethodInvoker.cs +++ b/src/graphql-aspnet/Common/Generics/MethodInvoker.cs @@ -12,7 +12,7 @@ namespace GraphQL.AspNet.Common.Generics /// /// A representation of a compiled lamda to invoke a method on an instance of an object. /// - /// The object instance to invoke on. + /// The object instance to invoke the delegated method on. /// The parameters to pass the method call. /// The result of the call. internal delegate object InstanceMethodInvoker(ref object instanceToInvokeOn, params object[] methodParameters); diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Internals.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Internals.cs index c7f2409e4..3bf9a16e0 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Internals.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Internals.cs @@ -69,5 +69,24 @@ private static IGraphQLRuntimeDirectiveActionDefinition MapDirectiveInternal(thi schemaOptions.AddRuntimeSchemaItem(directive); return directive; } + + /// + /// Convert a virtual field to a resolvable fields and assigns the given resolver. + /// + /// The field being built. + /// The delegate to assign as the resolver. This method will be + /// parsed to determine input arguments for the field on the target schema. + /// IGraphQLFieldBuilder. + private static IGraphQLRuntimeResolvedFieldDefinition AddResolver(this IGraphQLRuntimeFieldDefinition field, Delegate resolverMethod) + { + // convert the virtual field to a resolved field + var resolvedBuilder = RuntimeResolvedFieldDefinition.FromFieldTemplate(field); + resolvedBuilder.Options.AddRuntimeSchemaItem(resolvedBuilder); + + resolvedBuilder.Resolver = resolverMethod; + resolvedBuilder.ReturnType = null; + + return resolvedBuilder; + } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Mutations.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Mutations.cs index e835ea0f7..b9c76bf7d 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Mutations.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Mutations.cs @@ -28,14 +28,14 @@ public static partial class GraphQLRuntimeSchemaItemDefinitionExtensions /// will be created. /// The template path string for his field. (e.g. /path1/path2/path3) /// IGraphQLFieldTemplate. - public static IGraphQLRuntimeFieldDefinition MapMutation(this SchemaOptions schemaOptions, string template) + public static IGraphQLRuntimeResolvedFieldDefinition MapMutation(this SchemaOptions schemaOptions, string template) { var field = MapGraphQLFieldInternal( schemaOptions, GraphOperationType.Mutation, template); - return field; + return field.AddResolver(null); } /// @@ -68,7 +68,7 @@ public static IGraphQLRuntimeResolvedFieldDefinition MapMutation(this SchemaOpti /// will be created. /// The template path string for his field. (e.g. /path1/path2/path3) /// IGraphQLFieldTemplate. - public static IGraphQLRuntimeFieldDefinition MapMutation(this ISchemaBuilder schemaBuilder, string template) + public static IGraphQLRuntimeResolvedFieldDefinition MapMutation(this ISchemaBuilder schemaBuilder, string template) { Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); @@ -77,7 +77,7 @@ public static IGraphQLRuntimeFieldDefinition MapMutation(this ISchemaBuilder sch GraphOperationType.Mutation, template); - return field; + return field.AddResolver(null); } /// diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Queries.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Queries.cs index 3cc0a9b0b..caa50a341 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Queries.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Queries.cs @@ -28,14 +28,14 @@ public static partial class GraphQLRuntimeSchemaItemDefinitionExtensions /// will be created. /// The template path string for his field. (e.g. /path1/path2/path3) /// IGraphQLFieldTemplate. - public static IGraphQLRuntimeFieldDefinition MapQuery(this SchemaOptions schemaOptions, string template) + public static IGraphQLRuntimeResolvedFieldDefinition MapQuery(this SchemaOptions schemaOptions, string template) { var field = MapGraphQLFieldInternal( schemaOptions, GraphOperationType.Query, template); - return field; + return field.AddResolver(null); } /// @@ -68,7 +68,7 @@ public static IGraphQLRuntimeResolvedFieldDefinition MapQuery(this SchemaOptions /// will be created. /// The template path string for his field. (e.g. /path1/path2/path3) /// IGraphQLFieldTemplate. - public static IGraphQLRuntimeFieldDefinition MapQuery(this ISchemaBuilder schemaBuilder, string template) + public static IGraphQLRuntimeResolvedFieldDefinition MapQuery(this ISchemaBuilder schemaBuilder, string template) { Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); @@ -77,7 +77,7 @@ public static IGraphQLRuntimeFieldDefinition MapQuery(this ISchemaBuilder schema GraphOperationType.Query, template); - return field; + return field.AddResolver(null); } /// diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_VirtualFields.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_VirtualFields.cs index 367897e5a..d052d7b85 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_VirtualFields.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_VirtualFields.cs @@ -10,8 +10,11 @@ namespace GraphQL.AspNet.Configuration { using System; + using System.Runtime.CompilerServices; using GraphQL.AspNet.Common; using GraphQL.AspNet.Configuration.Templates; + using GraphQL.AspNet.Execution; + using GraphQL.AspNet.Interfaces.Configuration; using GraphQL.AspNet.Interfaces.Configuration.Templates; using GraphQL.AspNet.Interfaces.Controllers; using Microsoft.AspNetCore.Authorization; @@ -67,48 +70,65 @@ public static IGraphQLRuntimeFieldDefinition AllowAnonymous(this IGraphQLRuntime } /// - /// Sets the resolver to be used when this field is requested at runtime. + /// Begins a new field group for the query schema object. All fields created using + /// against this group will be nested underneath it and inherit any set parameters such as authorization requirements. /// - /// - /// If this method is called more than once the previously set resolver will be replaced. - /// - /// The field being built. - /// The delegate to assign as the resolver. This method will be - /// parsed to determine input arguments for the field on the target schema. - /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeResolvedFieldDefinition AddResolver(this IGraphQLRuntimeFieldDefinition field, Delegate resolverMethod) + /// The builder to append the query group to. + /// The template path for this group. + /// IGraphQLRuntimeFieldDefinition. + public static IGraphQLRuntimeFieldDefinition MapQueryGroup(this ISchemaBuilder schemaBuilder, string template) { - // convert the virtual field to a resolved field - var resolvedBuilder = RuntimeResolvedFieldDefinition.FromFieldTemplate(field); - resolvedBuilder.Options.AddRuntimeSchemaItem(resolvedBuilder); + return MapQueryGroup(schemaBuilder?.Options, template); + } - resolvedBuilder.Resolver = resolverMethod; - resolvedBuilder.ReturnType = null; + /// + /// Begins a new field group for the query schema object. All fields created using + /// against this group will be nested underneath it and inherit any set parameters such as authorization requirements. + /// + /// The schema options to append the query group to. + /// The template path for this group. + /// IGraphQLRuntimeFieldDefinition. + public static IGraphQLRuntimeFieldDefinition MapQueryGroup(this SchemaOptions schemaOptions, string template) + { + var virtualField = new RuntimeVirtualFieldTemplate(schemaOptions, SchemaItemCollections.Query, template); + return virtualField; + } - return resolvedBuilder; + /// + /// Begins a new field group for the mutation schema object. All fields created using + /// against this group will be nested underneath it and inherit any set parameters such as authorization requirements. + /// + /// The builder to append the mutation group to. + /// The template path for this group. + /// IGraphQLRuntimeFieldDefinition. + public static IGraphQLRuntimeFieldDefinition MapMutationGroup(this ISchemaBuilder schemaBuilder, string template) + { + return MapMutationGroup(schemaBuilder?.Options, template); } /// - /// Sets the resolver to be used when this field is requested at runtime. + /// Begins a new field group for the mutation schema object. All fields created using + /// against this group will be nested underneath it and inherit any set parameters such as authorization requirements. /// - /// - /// If this method is called more than once the previously set resolver will be replaced. - /// - /// The expected, primary return type of the field. Must be provided - /// if the supplied delegate returns an . - /// The field being built. - /// The delegate to assign as the resolver. This method will be - /// parsed to determine input arguments for the field on the target schema. - /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeResolvedFieldDefinition AddResolver(this IGraphQLRuntimeFieldDefinition field, Delegate resolverMethod) + /// The schema options to append the mutation group to. + /// The template path for this group. + /// IGraphQLRuntimeFieldDefinition. + public static IGraphQLRuntimeFieldDefinition MapMutationGroup(this SchemaOptions schemaOptions, string template) { - // convert the virtual field to a resolved field - var resolvedBuilder = RuntimeResolvedFieldDefinition.FromFieldTemplate(field); - resolvedBuilder.Options.AddRuntimeSchemaItem(resolvedBuilder); + var virtualField = new RuntimeVirtualFieldTemplate(schemaOptions, SchemaItemCollections.Mutation, template); + return virtualField; + } - resolvedBuilder.Resolver = resolverMethod; - resolvedBuilder.ReturnType = typeof(TReturnType); - return resolvedBuilder; + /// + /// Maps an intermediate child field into the schema. This field will inherit any parameters set from its parent (including the template path). + /// Any fields created from this new group will inherit any parameters set on the group AND the parent group. + /// + /// The field under which this new field will be nested. + /// The template pattern to be appended to the supplied . + /// IGraphQLRuntimeFieldDefinition. + public static IGraphQLRuntimeFieldDefinition MapSubGroup(this IGraphQLRuntimeFieldDefinition field, string subTemplate) + { + return new RuntimeVirtualFieldTemplate(field, subTemplate); } /// @@ -126,18 +146,5 @@ public static IGraphQLRuntimeResolvedFieldDefinition MapField(this IGraphQLRunti subField.Options.AddRuntimeSchemaItem(subField); return subField; } - - /// - /// Maps a child field into the schema underneath the supplied field. This field can be - /// further extended. - /// - /// The field under which this new field will be nested. - /// The template pattern to be appended to the supplied . - /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeFieldDefinition MapField(this IGraphQLRuntimeFieldDefinition field, string subTemplate) - { - var subField = new RuntimeVirtualFieldTemplate(field, subTemplate); - return subField; - } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Controllers/ActionResults/GraphActionResult.cs b/src/graphql-aspnet/Controllers/ActionResults/GraphActionResult.cs new file mode 100644 index 000000000..a6ebf2ce6 --- /dev/null +++ b/src/graphql-aspnet/Controllers/ActionResults/GraphActionResult.cs @@ -0,0 +1,148 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Controllers.ActionResults +{ + using System; + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Controllers.ActionResults.Batching; + using GraphQL.AspNet.Execution; + using GraphQL.AspNet.Interfaces.Controllers; + using GraphQL.AspNet.Interfaces.Execution; + using GraphQL.AspNet.Interfaces.Schema; + + /// + /// A helper class to allow the use of common methods + /// with non-controller based resolvers. + /// + public static class GraphActionResult + { + /// + /// Returns an result with the given item as the resolved value for the field. + /// + /// The object to resolve the field with. + /// IGraphActionResult<TResult>. + public static IGraphActionResult Ok(object item) + { + return new ObjectReturnedGraphActionResult(item); + } + + /// + /// Returns a result indicating that null is the resolved value + /// for the field. + /// + /// IGraphActionResult<TResult>. + public static IGraphActionResult Ok() + { + return Ok(null); + } + + /// + /// Returns an error indicating that the issue indicated by occured. + /// + /// The human-friendly error message to assign ot the reported error in the graph result. + /// The code to assign to the error entry in the graph result. + /// An optional exception that generated this error. + /// IGraphActionResult. + public static IGraphActionResult Error( + string message, + string code = null, + Exception exception = null) + { + return new GraphFieldErrorActionResult(message, code, exception); + } + + /// + /// Returns an error indicating that the issue indicated by occured. + /// + /// The severity of the message. + /// The human-friendly error message to assign ot the reported error in the graph result. + /// The error code to assign to the reported error in the graph result. + /// An optional exception to be published if the query is configured to allow exposing exceptions. + /// IGraphActionResult. + public static IGraphActionResult Error( + GraphMessageSeverity severity, + string message, + string code = null, + Exception exception = null) + { + var errorMessage = new GraphExecutionMessage(severity, message, code, exception: exception); + return Error(errorMessage); + } + + /// + /// Returns an error indicating that the given issue occured. + /// + /// A custom generated error message. + /// IGraphActionResult. + public static IGraphActionResult Error(IGraphMessage message) + { + return new GraphFieldErrorActionResult(message); + } + + /// + /// Returns an error result indicating that processing failed due to some internal process. An exception + /// will be injected into the graph result and processing will be terminated. + /// + /// The error message. + /// IGraphActionResult. + public static IGraphActionResult InternalServerError(string errorMessage) + { + return new InternalServerErrorGraphActionResult(errorMessage); + } + + /// + /// Returns an error indicating that something could not be resolved correctly + /// with the information provided. + /// + /// The message indicating what was not found. + /// IGraphActionResult. + public static IGraphActionResult NotFound(string message) + { + return new RouteNotFoundGraphActionResult(message); + } + + /// + /// Returns an negative result, indicating the data supplied on the request was bad or + /// otherwise not usable by the controller method. + /// + /// The message. + /// IGraphActionResult. + public static IGraphActionResult BadRequest(string message) + { + return new BadRequestGraphActionResult(message); + } + + /// + /// Returns a negative result, indicating that the action requested was unauthorized for the current context. + /// + /// The message to return to the client. + /// The error code to apply to the error returned to the client. + /// IGraphActionResult. + public static IGraphActionResult Unauthorized(string message = null, string errorCode = null) + { + return new UnauthorizedGraphActionResult(message, errorCode); + } + + /// + /// Begings building a result capable of mapping a batch result to the original source items to correctly resolve + /// the field. (e.g. it will create a single item reference or a collection of children as the field + /// requires). An will be + /// generated indicating an issue if the batch produced cannot fulfill the requirements of the field. + /// This method will not throw an exception. + /// + /// The graph field the batch will be built for. + /// IGraphActionResult. + public static BatchBuilder StartBatch(IGraphField targetField) + { + Validation.ThrowIfNull(targetField, nameof(targetField)); + return new BatchBuilder(targetField); + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Controllers/GraphControllerBase.cs b/src/graphql-aspnet/Controllers/GraphControllerBase.cs index 576889073..0c643e433 100644 --- a/src/graphql-aspnet/Controllers/GraphControllerBase.cs +++ b/src/graphql-aspnet/Controllers/GraphControllerBase.cs @@ -133,7 +133,7 @@ internal virtual async Task InvokeActionAsync( /// The resolver declaration that needs to be executed. /// The realized set of arguments that need /// to be passed to the invocable method instance. - /// Task. + /// The exact return value from the invoked resolver. protected virtual object CreateAndInvokeAction(IGraphFieldResolverMethod resolver, object[] invocationArguments) { if (resolver.Method.DeclaringType != this.GetType()) diff --git a/src/graphql-aspnet/Controllers/GraphController_ActionResults.cs b/src/graphql-aspnet/Controllers/GraphController_ActionResults.cs index 70aeaf043..d76a88f04 100644 --- a/src/graphql-aspnet/Controllers/GraphController_ActionResults.cs +++ b/src/graphql-aspnet/Controllers/GraphController_ActionResults.cs @@ -29,7 +29,7 @@ public abstract partial class GraphController /// IGraphActionResult<TResult>. protected virtual IGraphActionResult Ok(object item) { - return new ObjectReturnedGraphActionResult(item); + return GraphActionResult.Ok(item); } /// @@ -39,7 +39,7 @@ protected virtual IGraphActionResult Ok(object item) /// IGraphActionResult<TResult>. protected virtual IGraphActionResult Ok() { - return this.Ok(null); + return GraphActionResult.Ok(); } /// @@ -54,7 +54,7 @@ protected virtual IGraphActionResult Error( string code = null, Exception exception = null) { - return new GraphFieldErrorActionResult(message, code, exception); + return GraphActionResult.Error(message, code, exception); } /// @@ -71,8 +71,7 @@ protected virtual IGraphActionResult Error( string code = null, Exception exception = null) { - var errorMessage = new GraphExecutionMessage(severity, message, code, exception: exception); - return this.Error(errorMessage); + return GraphActionResult.Error(severity, message, code, exception: exception); } /// @@ -82,7 +81,7 @@ protected virtual IGraphActionResult Error( /// IGraphActionResult. protected virtual IGraphActionResult Error(IGraphMessage message) { - return new GraphFieldErrorActionResult(message); + return GraphActionResult.Error(message); } /// @@ -93,7 +92,7 @@ protected virtual IGraphActionResult Error(IGraphMessage message) /// IGraphActionResult. protected virtual IGraphActionResult InternalServerError(string errorMessage) { - return new InternalServerErrorGraphActionResult(errorMessage); + return GraphActionResult.InternalServerError(errorMessage); } /// @@ -104,7 +103,7 @@ protected virtual IGraphActionResult InternalServerError(string errorMessage) /// IGraphActionResult. protected virtual IGraphActionResult NotFound(string message) { - return new RouteNotFoundGraphActionResult(message); + return GraphActionResult.NotFound(message); } /// @@ -115,7 +114,7 @@ protected virtual IGraphActionResult NotFound(string message) /// IGraphActionResult. protected virtual IGraphActionResult BadRequest(string message) { - return new BadRequestGraphActionResult(message); + return GraphActionResult.BadRequest(message); } /// @@ -137,7 +136,7 @@ protected virtual IGraphActionResult BadRequest(InputModelStateDictionary modelS /// IGraphActionResult. protected virtual IGraphActionResult Unauthorized(string message = null, string errorCode = null) { - return new UnauthorizedGraphActionResult(message, errorCode); + return GraphActionResult.Unauthorized(message, errorCode); } /// @@ -150,7 +149,7 @@ protected virtual IGraphActionResult Unauthorized(string message = null, string /// IGraphActionResult. protected virtual BatchBuilder StartBatch() { - return new BatchBuilder(this.Request.InvocationContext.Field); + return GraphActionResult.StartBatch(this.Request.InvocationContext.Field); } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Internal/TypeTemplates/GraphFieldTemplateBase.cs b/src/graphql-aspnet/Internal/TypeTemplates/GraphFieldTemplateBase.cs index fa1416ac5..a72d48133 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/GraphFieldTemplateBase.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/GraphFieldTemplateBase.cs @@ -228,7 +228,7 @@ public override void ValidateOrThrow() if (this.PossibleTypes.Count == 0) { throw new GraphTypeDeclarationException( - $"The field '{this.InternalFullName}' declared no possible return types either on its attribute declarations or as the " + + $"The field '{this.InternalFullName}' declared no possible return types either as part of its specification or as the " + "declared return type for the field. GraphQL requires the type information be known " + $"to setup the schema and client tooling properly. If this field returns a '{nameof(IGraphActionResult)}' you must " + "provide a graph field declaration attribute and add at least one type; be that a concrete type, an interface or a union."); diff --git a/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/BaseRuntimeControllerActionDefinition.cs b/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/BaseRuntimeControllerActionDefinition.cs index 10ab11a11..70c326fd7 100644 --- a/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/BaseRuntimeControllerActionDefinition.cs +++ b/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/BaseRuntimeControllerActionDefinition.cs @@ -76,12 +76,12 @@ protected BaseRuntimeControllerActionDefinition( string partialPathTemplate) : this() { - parentField = Validation.ThrowIfNullOrReturn(parentField, nameof(parentField)); + _parentField = Validation.ThrowIfNullOrReturn(parentField, nameof(parentField)); this.Options = Validation.ThrowIfNullOrReturn(parentField?.Options, nameof(parentField.Options)); partialPathTemplate = Validation.ThrowIfNullWhiteSpaceOrReturn(partialPathTemplate, nameof(partialPathTemplate)); - this.Route = parentField.Route.CreateChild(partialPathTemplate); + this.Route = _parentField.Route.CreateChild(partialPathTemplate); } /// @@ -97,6 +97,8 @@ public virtual void AddAttribute(Attribute attrib) /// Attribute. protected abstract Attribute CreatePrimaryAttribute(); + private readonly IGraphQLRuntimeFieldDefinition _parentField; + /// public virtual SchemaOptions Options { get; protected set; } @@ -109,6 +111,12 @@ public IEnumerable Attributes if (topAttrib != null) yield return topAttrib; + if (_parentField != null) + { + foreach (var attrib in _parentField.Attributes) + yield return attrib; + } + foreach (var attrib in this.AppendedAttributes) yield return attrib; } diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedMutationGroupTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedMutationGroupTests.cs new file mode 100644 index 000000000..20f3ac138 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedMutationGroupTests.cs @@ -0,0 +1,124 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Configuration.Templates +{ + using System.Linq; + using GraphQL.AspNet.Attributes; + using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Schemas; + using Microsoft.AspNetCore.Authorization; + using Microsoft.Extensions.DependencyInjection; + using NUnit.Framework; + + [TestFixture] + public class MappedMutationGroupTests + { + [Test] + public void MapMutationGroup_WhenAllowAnonymousAdded_AddsAnonymousAttribute() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapMutationGroup("/path1/path2"); + + field.AllowAnonymous(); + + Assert.AreEqual(1, field.Attributes.Count()); + Assert.IsNotNull(field.Attributes.FirstOrDefault(x => x is AllowAnonymousAttribute)); + } + + [Test] + public void MapMutationGroup_WhenRequireAuthAdded_AddsAuthAttribute() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapMutationGroup("/path1/path2"); + + field.RequireAuthorization("policy1", "roles1"); + + Assert.AreEqual(1, field.Attributes.Count()); + var attrib = field.Attributes.FirstOrDefault(x => x is AuthorizeAttribute) as AuthorizeAttribute; + Assert.IsNotNull(attrib); + Assert.AreEqual("policy1", attrib.Policy); + Assert.AreEqual("roles1", attrib.Roles); + } + + [Test] + public void MapMutationGroup_WhenUnresolvedChildFieldIsAdded_PathIsCorrect() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapMutationGroup("/path1/path2"); + + var childField = field.MapSubGroup("/path3/path4"); + + Assert.AreEqual("[mutation]/path1/path2/path3/path4", childField.Route.Path); + } + + [Test] + public void MapMutationGroup_WhenAllowAnonymousAdded_ThenResolvedField_AddsAnonymousAttributeToField() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapMutationGroup("/path1/path2"); + + field.AllowAnonymous(); + + var chidlField = field.MapField("/path3/path4", (string a) => 1); + + Assert.AreEqual(2, chidlField.Attributes.Count()); + Assert.IsNotNull(chidlField.Attributes.FirstOrDefault(x => x is AllowAnonymousAttribute)); + Assert.IsNotNull(chidlField.Attributes.FirstOrDefault(x => x is MutationRootAttribute)); + } + + [Test] + public void MapMutationGroup_WhenResolvedChildFieldIsAdded_PathIsCorrect() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapMutationGroup("/path1/path2"); + + var childField = field.MapField("/path3/path4", (string a) => 1); + + Assert.AreEqual("[mutation]/path1/path2/path3/path4", childField.Route.Path); + } + + [Test] + public void MapMutationGroup_WhenResolvedChildFieldIsAddedToUnresolvedChildField_PathIsCorrect() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapMutationGroup("/path1/path2"); + var childField = field.MapSubGroup("/path3/path4"); + var resolvedField = childField.MapField("/path5/path6", (string a) => 1); + + Assert.AreEqual("[mutation]/path1/path2/path3/path4/path5/path6", resolvedField.Route.Path); + Assert.IsNotNull(resolvedField.Resolver); + } + + [Test] + public void MapMutationGroup_WhenResolvedChildFieldIsAdded_AndParentPathIsChanged_PathIsCorrect() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapMutationGroup("/path1/path2"); + + var childField = field.MapField("/path3/path4", (string a) => 1); + + Assert.AreEqual("[mutation]/path1/path2/path3/path4", childField.Route.Path); + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedMutationTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedMutationTemplateTests.cs index 708c2f253..ab62ae5f4 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedMutationTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedMutationTemplateTests.cs @@ -12,7 +12,6 @@ namespace GraphQL.AspNet.Tests.Configuration.Templates using System.Linq; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Configuration; - using GraphQL.AspNet.Execution; using GraphQL.AspNet.Interfaces.Configuration; using GraphQL.AspNet.Interfaces.Configuration.Templates; using GraphQL.AspNet.Schemas; @@ -28,23 +27,6 @@ public int TestDelegate(string a) return 0; } - [Test] - public void MapMutation_FromSchemaOptions_WithNoDelegate_DoesNotAddFieldToSchema() - { - var services = new ServiceCollection(); - var options = new SchemaOptions(services); - - var field = options.MapMutation("/path1/path2"); - - Assert.IsNotNull(field); - Assert.AreEqual("[mutation]/path1/path2", field.Route.Path); - Assert.IsInstanceOf(typeof(IGraphQLRuntimeFieldDefinition), field); - Assert.AreEqual(0, options.RuntimeTemplates.Count()); - - // no top level attribute should be available - Assert.AreEqual(0, field.Attributes.Count()); - } - [Test] public void MapMutation_FromSchemaOptions_WithDelegate_DoesAddFieldToSchema() { @@ -63,26 +45,6 @@ public void MapMutation_FromSchemaOptions_WithDelegate_DoesAddFieldToSchema() Assert.IsNotNull(mutationRootAttrib); } - [Test] - public void MapMutation_FromBuilder_WithNoDelegate_DoesNotAddFieldToSchema() - { - var services = new ServiceCollection(); - var options = new SchemaOptions(services); - - var builderMock = new Mock(); - builderMock.Setup(x => x.Options).Returns(options); - - var field = builderMock.Object.MapMutation("/path1/path2"); - - Assert.IsNotNull(field); - Assert.AreEqual("[mutation]/path1/path2", field.Route.Path); - Assert.IsInstanceOf(typeof(IGraphQLRuntimeFieldDefinition), field); - Assert.AreEqual(0, options.RuntimeTemplates.Count()); - - // no top level attribute should be available - Assert.AreEqual(0, field.Attributes.Count()); - } - [Test] public void MapMutation_FromBuilder_WithDelegate_DoesAddFieldToSchema() { diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/UnresolvedFieldTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedQueryGroupTests.cs similarity index 57% rename from src/unit-tests/graphql-aspnet-tests/Configuration/Templates/UnresolvedFieldTemplateTests.cs rename to src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedQueryGroupTests.cs index fa964cd01..553672188 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/UnresolvedFieldTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedQueryGroupTests.cs @@ -10,6 +10,7 @@ namespace GraphQL.AspNet.Tests.Configuration.Templates { using System.Linq; + using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Interfaces.Configuration.Templates; using GraphQL.AspNet.Schemas; @@ -18,15 +19,15 @@ namespace GraphQL.AspNet.Tests.Configuration.Templates using NUnit.Framework; [TestFixture] - public class UnresolvedFieldTemplateTests + public class MappedQueryGroupTests { [Test] - public void UnresolvedField_WhenAllowAnonymousAdded_AddsAnonymousAttribute() + public void MapQueryGroup_WhenAllowAnonymousAdded_AddsAnonymousAttribute() { var services = new ServiceCollection(); var options = new SchemaOptions(services); - var field = options.MapQuery("/path1/path2"); + var field = options.MapQueryGroup("/path1/path2"); field.AllowAnonymous(); @@ -35,12 +36,12 @@ public void UnresolvedField_WhenAllowAnonymousAdded_AddsAnonymousAttribute() } [Test] - public void UnresolvedField_WhenRequireAuthAdded_AddsAuthAttribute() + public void MapQueryGroup_WhenRequireAuthAdded_AddsAuthAttribute() { var services = new ServiceCollection(); var options = new SchemaOptions(services); - var field = options.MapQuery("/path1/path2"); + var field = options.MapQueryGroup("/path1/path2"); field.RequireAuthorization("policy1", "roles1"); @@ -52,71 +53,56 @@ public void UnresolvedField_WhenRequireAuthAdded_AddsAuthAttribute() } [Test] - public void UnresolvedField_WhenResolverAdded_BecomesResolvedField() + public void MapQueryGroup_WhenUnresolvedChildFieldIsAdded_PathIsCorrect() { var services = new ServiceCollection(); var options = new SchemaOptions(services); - var field = options.MapQuery("/path1/path2"); + var field = options.MapQueryGroup("/path1/path2"); - Assert.IsInstanceOf(typeof(IGraphQLRuntimeFieldDefinition), field); - Assert.IsNotInstanceOf(typeof(IGraphQLRuntimeResolvedFieldDefinition), field); + var childField = field.MapSubGroup("/path3/path4"); - var field1 = field.AddResolver((string a) => 1); - Assert.IsInstanceOf(typeof(IGraphQLRuntimeResolvedFieldDefinition), field1); - Assert.IsNull(field1.ReturnType); - } - - [Test] - public void UnresolvedField_WhenResolverAddedWithSpecificType_BecomesResolvedField() - { - var services = new ServiceCollection(); - var options = new SchemaOptions(services); - - var field = options.MapQuery("/path1/path2"); - - Assert.IsInstanceOf(typeof(IGraphQLRuntimeFieldDefinition), field); - Assert.IsNotInstanceOf(typeof(IGraphQLRuntimeResolvedFieldDefinition), field); - - var field1 = field.AddResolver((string a) => 1); - Assert.IsInstanceOf(typeof(IGraphQLRuntimeResolvedFieldDefinition), field1); - Assert.AreEqual(typeof(decimal), field1.ReturnType); + Assert.AreEqual("[query]/path1/path2/path3/path4", childField.Route.Path); } [Test] - public void UnresolvedField_WhenUnresolvedChildFieldIsAdded_PathIsCorrect() + public void MapQueryGroup_WhenResolvedChildFieldIsAdded_PathIsCorrect() { var services = new ServiceCollection(); var options = new SchemaOptions(services); - var field = options.MapQuery("/path1/path2"); + var field = options.MapQueryGroup("/path1/path2"); - var childField = field.MapField("/path3/path4"); + var childField = field.MapField("/path3/path4", (string a) => 1); Assert.AreEqual("[query]/path1/path2/path3/path4", childField.Route.Path); } [Test] - public void UnresolvedField_WhenResolvedChildFieldIsAdded_PathIsCorrect() + public void MapMutationGroup_WhenAllowAnonymousAdded_ThenResolvedField_AddsAnonymousAttributeToField() { var services = new ServiceCollection(); var options = new SchemaOptions(services); - var field = options.MapQuery("/path1/path2"); + var field = options.MapQueryGroup("/path1/path2"); - var childField = field.MapField("/path3/path4", (string a) => 1); + field.AllowAnonymous(); - Assert.AreEqual("[query]/path1/path2/path3/path4", childField.Route.Path); + var chidlField = field.MapField("/path3/path4", (string a) => 1); + + Assert.AreEqual(2, chidlField.Attributes.Count()); + Assert.IsNotNull(chidlField.Attributes.FirstOrDefault(x => x is AllowAnonymousAttribute)); + Assert.IsNotNull(chidlField.Attributes.FirstOrDefault(x => x is QueryRootAttribute)); } [Test] - public void UnresolvedField_WhenResolvedChildFieldIsAddedToUnresolvedChildField_PathIsCorrect() + public void MapQueryGroup_WhenResolvedChildFieldIsAddedToUnresolvedChildField_PathIsCorrect() { var services = new ServiceCollection(); var options = new SchemaOptions(services); - var field = options.MapQuery("/path1/path2"); - var childField = field.MapField("/path3/path4"); + var field = options.MapQueryGroup("/path1/path2"); + var childField = field.MapSubGroup("/path3/path4"); var resolvedField = childField.MapField("/path5/path6", (string a) => 1); Assert.AreEqual("[query]/path1/path2/path3/path4/path5/path6", resolvedField.Route.Path); @@ -124,12 +110,12 @@ public void UnresolvedField_WhenResolvedChildFieldIsAddedToUnresolvedChildField_ } [Test] - public void UnresolvedField_WhenResolvedChildFieldIsAdded_AndParentPathIsChanged_PathIsCorrect() + public void MapQueryGroup_WhenResolvedChildFieldIsAdded_AndParentPathIsChanged_PathIsCorrect() { var services = new ServiceCollection(); var options = new SchemaOptions(services); - var field = options.MapQuery("/path1/path2"); + var field = options.MapQueryGroup("/path1/path2"); var childField = field.MapField("/path3/path4", (string a) => 1); diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedQueryTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedQueryTemplateTests.cs index 08f84d643..adf6c7140 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedQueryTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedQueryTemplateTests.cs @@ -29,23 +29,6 @@ public int TestDelegate(string a) return 0; } - [Test] - public void MapQuery_FromSchemaOptions_WithNoDelegate_DoesNotAddFieldToSchema() - { - var services = new ServiceCollection(); - var options = new SchemaOptions(services); - - var field = options.MapQuery("/path1/path2"); - - Assert.IsNotNull(field); - Assert.AreEqual(SchemaItemCollections.Query, field.Route.RootCollection); - Assert.IsInstanceOf(typeof(IGraphQLRuntimeFieldDefinition), field); - Assert.AreEqual(0, options.RuntimeTemplates.Count()); - - // no top level attribute should be available - Assert.AreEqual(0, field.Attributes.Count()); - } - [Test] public void MapQuery_FromSchemaOptions_WithDelegate_DoesAddFieldToSchema() { @@ -63,26 +46,6 @@ public void MapQuery_FromSchemaOptions_WithDelegate_DoesAddFieldToSchema() Assert.IsNotNull(queryRootAttrib); } - [Test] - public void MapQuery_FromBuilder_WithNoDelegate_DoesNotAddFieldToSchema() - { - var services = new ServiceCollection(); - var options = new SchemaOptions(services); - - var builderMock = new Mock(); - builderMock.Setup(x => x.Options).Returns(options); - - var field = builderMock.Object.MapQuery("/path1/path2"); - - Assert.IsNotNull(field); - Assert.AreEqual(SchemaItemCollections.Query, field.Route.RootCollection); - Assert.IsInstanceOf(typeof(IGraphQLRuntimeFieldDefinition), field); - Assert.AreEqual(0, options.RuntimeTemplates.Count()); - - // no top level attribute should be available - Assert.AreEqual(0, field.Attributes.Count()); - } - [Test] public void MapQuery_FromBuilder_WithDelegate_DoesAddFieldToSchema() { diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionRuntimeFieldTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionRuntimeFieldTests.cs index 2441d1bf6..643f94aa2 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionRuntimeFieldTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionRuntimeFieldTests.cs @@ -11,6 +11,8 @@ namespace GraphQL.AspNet.Tests.Execution { using System.Threading.Tasks; using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Controllers.ActionResults; + using GraphQL.AspNet.Interfaces.Controllers; using GraphQL.AspNet.Tests.Execution.TestData.RuntimeFieldTest; using GraphQL.AspNet.Tests.Framework; using GraphQL.AspNet.Tests.Framework.CommonHelpers; @@ -47,6 +49,64 @@ public async Task BasicMappedQuery_ExecutesMethod() result); } + [Test] + public async Task BasicMappedQuery_AddingResolverAfter_ExecutesMethod() + { + var serverBuilder = new TestServerBuilder() + .AddGraphQL(o => + { + o.MapQuery("/field1/field2") + .AddResolver((int a, int b) => + { + return a + b; + }); + }); + + var server = serverBuilder.Build(); + var builder = server.CreateQueryContextBuilder(); + builder.AddQueryText(@"query { field1 { field2(a: 5, b: 33 } } }"); + + var result = await server.RenderResult(builder); + CommonAssertions.AreEqualJsonStrings( + @"{ + ""data"": { + ""field1"": { + ""field2"" : 38 + } + } + }", + result); + } + + [Test] + public async Task MappedQuery_ViaGroup_ExecutesMethod() + { + var serverBuilder = new TestServerBuilder() + .AddGraphQL(o => + { + var group = o.MapQueryGroup("/field1"); + group.MapField("/field2", (int a, int b) => + { + return a + b; + }); + }); + + var server = serverBuilder.Build(); + var builder = server.CreateQueryContextBuilder(); + builder.AddQueryText(@"query { field1 { field2(a: 5, b: 33 } } }"); + + var result = await server.RenderResult(builder); + CommonAssertions.AreEqualJsonStrings( + @"{ + ""data"": { + ""field1"": { + ""field2"" : 38 + } + } + }", + result); + } + [Test] public async Task BasicMappedMutation_ExecutesMethod() { @@ -75,6 +135,35 @@ public async Task BasicMappedMutation_ExecutesMethod() result); } + [Test] + public async Task BasicMappedMutation_AddingResolverAfter_ExecutesMethod() + { + var serverBuilder = new TestServerBuilder() + .AddGraphQL(o => + { + o.MapMutation("/field1/field2") + .AddResolver((int a, int b) => + { + return a + b; + }); + }); + + var server = serverBuilder.Build(); + var builder = server.CreateQueryContextBuilder(); + builder.AddQueryText(@"mutation { field1 { field2(a: 4, b: 33 } } }"); + + var result = await server.RenderResult(builder); + CommonAssertions.AreEqualJsonStrings( + @"{ + ""data"": { + ""field1"": { + ""field2"" : 37 + } + } + }", + result); + } + [Test] public async Task StaticMethodMappedDelegate_ThrowsValidationException() { @@ -127,5 +216,34 @@ public async Task InstanceMethodMappedDelegate_ExecutesMethod() }", result); } + + [Test] + public async Task BasicMappedQuery_ReturningActionResult_ResolvesCorrectly() + { + var serverBuilder = new TestServerBuilder() + .AddGraphQL(o => + { + o.MapQuery("/field1/field2") + .AddResolver((int a, int b) => + { + return GraphActionResult.Ok(a + b); + }); + }); + + var server = serverBuilder.Build(); + var builder = server.CreateQueryContextBuilder(); + builder.AddQueryText(@"query { field1 { field2(a: 5, b: 33 } } }"); + + var result = await server.RenderResult(builder); + CommonAssertions.AreEqualJsonStrings( + @"{ + ""data"": { + ""field1"": { + ""field2"" : 38 + } + } + }", + result); + } } } \ No newline at end of file From 3713674178edf8234b42da1a082a70d4ac7f0198 Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Wed, 28 Jun 2023 17:37:05 -0700 Subject: [PATCH 14/63] WIP --- .../Common/Extensions/AttributeExtensions.cs | 44 +++++++++++++++ ...aItemDefinitionExtensions_VirtualFields.cs | 14 ++--- .../BaseRuntimeControllerActionDefinition.cs | 55 ++++++++++++++----- .../Extensions/AttributeExtensionTests.cs | 39 +++++++++++++ .../Templates/MappedQueryGroupTests.cs | 54 ++++++++++++++++++ .../MappedQuery_AuthorizationTests.cs | 16 ++++++ 6 files changed, 200 insertions(+), 22 deletions(-) create mode 100644 src/graphql-aspnet/Common/Extensions/AttributeExtensions.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Common/Extensions/AttributeExtensionTests.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Security/MappedQuery_AuthorizationTests.cs diff --git a/src/graphql-aspnet/Common/Extensions/AttributeExtensions.cs b/src/graphql-aspnet/Common/Extensions/AttributeExtensions.cs new file mode 100644 index 000000000..89dd03e14 --- /dev/null +++ b/src/graphql-aspnet/Common/Extensions/AttributeExtensions.cs @@ -0,0 +1,44 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Common.Extensions +{ + using System; + using System.Linq; + using Microsoft.AspNetCore.Authorization; + + /// + /// Extension methods for working with the attributes supplied by the library. + /// + public static class AttributeExtensions + { + /// + /// Inspects the given attribute's attributes to determine if its allowed to be applied more than once + /// to a given entity. + /// + /// + /// Used primarily for runtime field configuration to ensure correct usage within the templating system. + /// + /// The attribute to check. + /// true if this instance can be applied to an entity multiple times the specified attribute; otherwise, false. + public static bool CanBeAppliedMultipleTimes(this Attribute attribute) + { + var usage = attribute.GetType().GetCustomAttributes(typeof(AttributeUsageAttribute), true) + .Cast() + .ToList(); + + // the default is always false + if (usage.Count == 0) + return false; + + // take the first found instance in the inheritance stack + return usage[0].AllowMultiple; + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_VirtualFields.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_VirtualFields.cs index d052d7b85..76affd06b 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_VirtualFields.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_VirtualFields.cs @@ -70,8 +70,8 @@ public static IGraphQLRuntimeFieldDefinition AllowAnonymous(this IGraphQLRuntime } /// - /// Begins a new field group for the query schema object. All fields created using - /// against this group will be nested underneath it and inherit any set parameters such as authorization requirements. + /// Begins a new field group for the query schema object. All fields created using + /// this group will be nested underneath it and inherit any set parameters such as authorization requirements. /// /// The builder to append the query group to. /// The template path for this group. @@ -82,8 +82,8 @@ public static IGraphQLRuntimeFieldDefinition MapQueryGroup(this ISchemaBuilder s } /// - /// Begins a new field group for the query schema object. All fields created using - /// against this group will be nested underneath it and inherit any set parameters such as authorization requirements. + /// Begins a new field group for the query schema object. All fields created using + /// this group will be nested underneath it and inherit any set parameters such as authorization requirements. /// /// The schema options to append the query group to. /// The template path for this group. @@ -95,8 +95,7 @@ public static IGraphQLRuntimeFieldDefinition MapQueryGroup(this SchemaOptions sc } /// - /// Begins a new field group for the mutation schema object. All fields created using - /// against this group will be nested underneath it and inherit any set parameters such as authorization requirements. + /// Begins a new field group for the mutation schema object. All fields created using this group will be nested underneath it and inherit any set parameters such as authorization requirements. /// /// The builder to append the mutation group to. /// The template path for this group. @@ -107,8 +106,7 @@ public static IGraphQLRuntimeFieldDefinition MapMutationGroup(this ISchemaBuilde } /// - /// Begins a new field group for the mutation schema object. All fields created using - /// against this group will be nested underneath it and inherit any set parameters such as authorization requirements. + /// Begins a new field group for the mutation schema object. All fields created using this group will be nested underneath it and inherit any set parameters such as authorization requirements. /// /// The schema options to append the mutation group to. /// The template path for this group. diff --git a/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/BaseRuntimeControllerActionDefinition.cs b/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/BaseRuntimeControllerActionDefinition.cs index 70c326fd7..8c0132c88 100644 --- a/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/BaseRuntimeControllerActionDefinition.cs +++ b/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/BaseRuntimeControllerActionDefinition.cs @@ -12,6 +12,7 @@ namespace GraphQL.AspNet.Configuration.Templates using System; using System.Collections.Generic; using GraphQL.AspNet.Common; + using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Execution; using GraphQL.AspNet.Interfaces.Configuration.Templates; @@ -23,6 +24,8 @@ namespace GraphQL.AspNet.Configuration.Templates /// internal abstract class BaseRuntimeControllerActionDefinition : IGraphQLRuntimeSchemaItemDefinition { + private readonly IGraphQLRuntimeFieldDefinition _parentField; + /// /// Prevents a default instance of the class from being created. /// @@ -92,33 +95,54 @@ public virtual void AddAttribute(Attribute attrib) } /// - /// Creates the primary attribute that would identify this + /// Creates the primary attribute that would identify this instance if it was defined on + /// a controller. /// - /// Attribute. + /// The primary attribute. protected abstract Attribute CreatePrimaryAttribute(); - private readonly IGraphQLRuntimeFieldDefinition _parentField; - - /// - public virtual SchemaOptions Options { get; protected set; } - /// - public IEnumerable Attributes + public virtual IEnumerable Attributes { get { - var topAttrib = this.CreatePrimaryAttribute(); - if (topAttrib != null) - yield return topAttrib; + var combinedAttribs = new List(1 + this.AppendedAttributes.Count); + var definedTypes = new HashSet(); + // apply the attributes defined on the parent (and parent's parents) + // FIRST to mimic controller level attribs being encountered before action method params. if (_parentField != null) { foreach (var attrib in _parentField.Attributes) - yield return attrib; + { + if (!definedTypes.Contains(attrib.GetType()) || attrib.CanBeAppliedMultipleTimes()) + { + combinedAttribs.Add(attrib); + definedTypes.Add(attrib.GetType()); + } + } + } + + // apply the primary attribute first as its defined by this + // exact instance + var topAttrib = this.CreatePrimaryAttribute(); + if (topAttrib != null) + { + combinedAttribs.Add(topAttrib); + definedTypes.Add(topAttrib.GetType()); } + // apply all the secondary attributes defined directly on this instance foreach (var attrib in this.AppendedAttributes) - yield return attrib; + { + if (!definedTypes.Contains(attrib.GetType()) || attrib.CanBeAppliedMultipleTimes()) + { + combinedAttribs.Add(attrib); + definedTypes.Add(attrib.GetType()); + } + } + + return combinedAttribs; } } @@ -126,7 +150,10 @@ public IEnumerable Attributes /// Gets a list of attributes that were directly appended to this instance. /// /// The appended attributes. - protected IList AppendedAttributes { get; } + protected List AppendedAttributes { get; } + + /// + public virtual SchemaOptions Options { get; protected set; } /// public SchemaItemPath Route { get; protected set; } diff --git a/src/unit-tests/graphql-aspnet-tests/Common/Extensions/AttributeExtensionTests.cs b/src/unit-tests/graphql-aspnet-tests/Common/Extensions/AttributeExtensionTests.cs new file mode 100644 index 000000000..77f708129 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Common/Extensions/AttributeExtensionTests.cs @@ -0,0 +1,39 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Common.Extensions +{ + using GraphQL.AspNet.Common.Extensions; + using Microsoft.AspNetCore.Authorization; + using NUnit.Framework; + + [TestFixture] + public class AttributeExtensionTests + { + [Test] + public void CanBeAppliedMultipleTimes_MultipleCopyAttribute_ReturnsTrue() + { + var attrib = new AuthorizeAttribute("bob"); + + var result = attrib.CanBeAppliedMultipleTimes(); + + Assert.IsTrue(result); + } + + [Test] + public void CanBeAppliedMultipleTimes_SingleCopyAttribute_ReturnsFalse() + { + var attrib = new AllowAnonymousAttribute(); + + var result = attrib.CanBeAppliedMultipleTimes(); + + Assert.IsFalse(result); + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedQueryGroupTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedQueryGroupTests.cs index 553672188..c6ed9bbcc 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedQueryGroupTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedQueryGroupTests.cs @@ -121,5 +121,59 @@ public void MapQueryGroup_WhenResolvedChildFieldIsAdded_AndParentPathIsChanged_P Assert.AreEqual("[query]/path1/path2/path3/path4", childField.Route.Path); } + + [Test] + public void MapQueryGroup_SingleCopyAttribute_AppliedToGroupAndField_IsOnlyAppliedOnce() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapQueryGroup("/path1/path2") + .AllowAnonymous(); + + var childField = field.MapField("/path3/path4", (string a) => 1) + .AllowAnonymous(); + + var anonCount = childField.Attributes.Where(x => x is AllowAnonymousAttribute).Count(); + Assert.AreEqual(1, anonCount); + } + + [Test] + public void MapQueryGroup_MultipleCopyAttribute_AppliedToGroupAndField_IsAppliedMultipleTimes() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapQueryGroup("/path1/path2") + .RequireAuthorization("policy1"); + + var childField = field.MapField("/path3/path4", (string a) => 1) + .RequireAuthorization("policy2"); + + Assert.AreEqual(3, childField.Attributes.Count()); + var anonCount = childField.Attributes.Where(x => x is AuthorizeAttribute).Count(); + + Assert.AreEqual(2, anonCount); + Assert.IsNotNull(childField.Attributes.SingleOrDefault(x => x is AuthorizeAttribute a && a.Policy == "policy1")); + Assert.IsNotNull(childField.Attributes.SingleOrDefault(x => x is AuthorizeAttribute a && a.Policy == "policy2")); + + // ensure the order of applied attributes is parent field then child field + var i = 0; + foreach (var attrib in childField.Attributes) + { + if (attrib is AuthorizeAttribute a && a.Policy == "policy1") + { + Assert.AreEqual(0, i); + i++; + } + else if (attrib is AuthorizeAttribute b && b.Policy == "policy2") + { + Assert.AreEqual(1, i); + i++; + } + } + + Assert.AreEqual(2, i); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Security/MappedQuery_AuthorizationTests.cs b/src/unit-tests/graphql-aspnet-tests/Security/MappedQuery_AuthorizationTests.cs new file mode 100644 index 000000000..be3be6788 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Security/MappedQuery_AuthorizationTests.cs @@ -0,0 +1,16 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Security +{ + public class MappedQuery_AuthorizationTests + { + // tests for security against mapped query fields + } +} \ No newline at end of file From 84b8336f24cd0b41f905f9be84a7590ef764a17d Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Thu, 29 Jun 2023 16:37:31 -0700 Subject: [PATCH 15/63] WIP, execution tests for authentication for minimal api --- .../MappedQuery_AuthorizationTests.cs | 99 ++++++++++++++++++- 1 file changed, 98 insertions(+), 1 deletion(-) diff --git a/src/unit-tests/graphql-aspnet-tests/Security/MappedQuery_AuthorizationTests.cs b/src/unit-tests/graphql-aspnet-tests/Security/MappedQuery_AuthorizationTests.cs index be3be6788..600c74932 100644 --- a/src/unit-tests/graphql-aspnet-tests/Security/MappedQuery_AuthorizationTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Security/MappedQuery_AuthorizationTests.cs @@ -9,8 +9,105 @@ namespace GraphQL.AspNet.Tests.Security { + using System.Runtime.CompilerServices; + using System.Threading.Tasks; + using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Execution; + using GraphQL.AspNet.Tests.Framework; + using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using NUnit.Framework; + + [TestFixture] public class MappedQuery_AuthorizationTests { - // tests for security against mapped query fields + [Test] + public async Task MappedQuery_UserWithPolicy_CanAccessMethod() + { + var serverBuilder = new TestServerBuilder(); + serverBuilder.AddGraphQL(o => + { + o.MapQuery("/field1/field2", (int a, int b) => + { + return a + b; + }) + .RequireAuthorization("policy1"); + }); + + serverBuilder.Authorization.AddClaimPolicy("policy1", "claim1", "claimValue1"); + serverBuilder.UserContext.Authenticate(); + serverBuilder.UserContext.AddUserClaim("claim1", "claimValue1"); + + var server = serverBuilder.Build(); + + var builder = server.CreateQueryContextBuilder(); + builder.AddQueryText(@"query { field1 { field2(a: 5, b: 33 } } }"); + + var result = await server.RenderResult(builder); + CommonAssertions.AreEqualJsonStrings( + @"{ + ""data"": { + ""field1"": { + ""field2"" : 38 + } + } + }", + result); + } + + [Test] + public async Task MappedQuery_UserWithoutPolicy_AccessDenied() + { + var serverBuilder = new TestServerBuilder(); + serverBuilder.AddGraphQL(o => + { + o.MapQuery("/field1/field2", (int a, int b) => + { + return a + b; + }) + .RequireAuthorization("policy1"); + }); + + serverBuilder.Authorization.AddClaimPolicy("policy1", "claim1", "claimValue1"); + serverBuilder.UserContext.Authenticate(); + + var server = serverBuilder.Build(); + + var builder = server.CreateQueryContextBuilder(); + builder.AddQueryText(@"query { field1 { field2(a: 5, b: 33 } } }"); + + var result = await server.ExecuteQuery(builder); + + Assert.AreEqual(1, result.Messages.Count); + Assert.AreEqual(GraphMessageSeverity.Critical, result.Messages[0].Severity); + Assert.AreEqual("ACCESS_DENIED", result.Messages[0].Code); + } + + [Test] + public async Task MappedQuery_UnauthenticatedUser_AccessDenied() + { + var serverBuilder = new TestServerBuilder(); + serverBuilder.AddGraphQL(o => + { + o.MapQuery("/field1/field2", (int a, int b) => + { + return a + b; + }) + .RequireAuthorization("policy1"); + }); + + serverBuilder.Authorization.AddClaimPolicy("policy1", "claim1", "claimValue1"); + serverBuilder.UserContext.Authenticate(); + + var server = serverBuilder.Build(); + + var builder = server.CreateQueryContextBuilder(); + builder.AddQueryText(@"query { field1 { field2(a: 5, b: 33 } } }"); + + var result = await server.ExecuteQuery(builder); + + Assert.AreEqual(1, result.Messages.Count); + Assert.AreEqual(GraphMessageSeverity.Critical, result.Messages[0].Severity); + Assert.AreEqual("ACCESS_DENIED", result.Messages[0].Code); + } } } \ No newline at end of file From 8ae20fd4ddd07e0ae033f1855b1b177d76db3b91 Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Sat, 1 Jul 2023 08:02:37 -0700 Subject: [PATCH 16/63] WIP, added ITypedSchemaItem to IGraphField --- .../SubscriptionEnabledGraphFieldMaker.cs | 11 +++++++++- .../SubscriptionMethodGraphField.cs | 5 ++++- .../Engine/TypeMakers/GraphFieldMaker.cs | 11 +++++++++- .../Execution/GraphSchemaInitializer.cs | 22 +++++++++++++------ ...MustBeSuppliedOrHaveDefaultValueOnField.cs | 4 +--- ...BeSuppliedOrHaveDefaultValueOnDirective.cs | 4 +--- .../Interfaces/Schema/IGraphFieldBase.cs | 10 +-------- .../TypeTemplates/GraphArgumentTemplate.cs | 12 ++++------ .../Structural/GraphFieldCollection.cs | 1 + .../ExtendableGraphTypeExtensions.cs | 3 ++- .../TypeSystem/GraphArgumentModifiers.cs | 12 ++++++---- .../GraphArgumentModifiersExtensions.cs | 10 --------- .../Fields/Introspection_SchemaField.cs | 1 + .../Fields/Introspection_TypeGraphField.cs | 1 + .../Fields/Introspection_TypeNameMetaField.cs | 3 ++- .../Introspection/Introspection_TypeType.cs | 2 ++ .../Model/IntrospectedDirective.cs | 2 +- .../Introspection/Model/IntrospectedField.cs | 2 +- .../Schemas/TypeSystem/MethodGraphField.cs | 9 ++++++++ .../Schemas/TypeSystem/PropertyGraphField.cs | 10 +-------- .../Schemas/TypeSystem/VirtualGraphField.cs | 4 ++++ .../Templating/GraphActionTemplateTests.cs | 2 -- .../TypeExtensionFieldTemplateTests.cs | 6 ----- .../Schemas/GraphFieldArgumentCloningTests.cs | 2 +- .../Schemas/GraphFieldCloningTests.cs | 3 +++ .../MappedQuery_AuthorizationTests.cs | 4 ++-- 26 files changed, 85 insertions(+), 71 deletions(-) diff --git a/src/graphql-aspnet-subscriptions/Engine/TypeMakers/SubscriptionEnabledGraphFieldMaker.cs b/src/graphql-aspnet-subscriptions/Engine/TypeMakers/SubscriptionEnabledGraphFieldMaker.cs index 2456c393f..a38e52e62 100644 --- a/src/graphql-aspnet-subscriptions/Engine/TypeMakers/SubscriptionEnabledGraphFieldMaker.cs +++ b/src/graphql-aspnet-subscriptions/Engine/TypeMakers/SubscriptionEnabledGraphFieldMaker.cs @@ -6,6 +6,15 @@ // -- // License: MIT // ************************************************************* + +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* namespace GraphQL.AspNet.Engine.TypeMakers { using System.Collections.Generic; @@ -14,7 +23,6 @@ namespace GraphQL.AspNet.Engine.TypeMakers using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Internal.TypeTemplates; - using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Security; @@ -50,6 +58,7 @@ protected override MethodGraphField InstantiateField( formatter.FormatFieldName(template.Name), template.TypeExpression.CloneTo(formatter.FormatGraphTypeName(template.TypeExpression.TypeName)), template.Route, + template.InternalName, template.ObjectType, template.DeclaredReturnType, template.Mode, diff --git a/src/graphql-aspnet-subscriptions/Schemas/TypeSystem/SubscriptionMethodGraphField.cs b/src/graphql-aspnet-subscriptions/Schemas/TypeSystem/SubscriptionMethodGraphField.cs index 1d9a156d9..bd26e60e5 100644 --- a/src/graphql-aspnet-subscriptions/Schemas/TypeSystem/SubscriptionMethodGraphField.cs +++ b/src/graphql-aspnet-subscriptions/Schemas/TypeSystem/SubscriptionMethodGraphField.cs @@ -27,6 +27,7 @@ public class SubscriptionMethodGraphField : MethodGraphField, ISubscriptionGraph /// Name of the field in the type declaration.. /// The meta data about how this type field is implemented. /// The formal route to this field in the object graph. + /// Name of the declared method. /// The .NET type of the item or items that represent the graph type returned by this field. /// The .NET type as it was declared on the property which generated this field.. /// The execution mode of this field. @@ -38,6 +39,7 @@ public SubscriptionMethodGraphField( string fieldName, GraphTypeExpression typeExpression, SchemaItemPath route, + string declaredMethodName, Type objectType = null, Type declaredReturnType = null, Execution.FieldResolutionMode mode = Execution.FieldResolutionMode.PerSourceItem, @@ -45,7 +47,7 @@ public SubscriptionMethodGraphField( IEnumerable securityPolicies = null, string eventName = null, IAppliedDirectiveCollection directives = null) - : base(fieldName, typeExpression, route, objectType, declaredReturnType, mode, resolver, securityPolicies, directives) + : base(fieldName, typeExpression, route, declaredMethodName, objectType, declaredReturnType, mode, resolver, securityPolicies, directives) { this.EventName = eventName; } @@ -57,6 +59,7 @@ protected override MethodGraphField CreateNewInstance(IGraphType parent) this.Name, this.TypeExpression.Clone(), parent.Route.CreateChild(this.Name), + this.InternalName, this.ObjectType, this.DeclaredReturnType, this.Mode, diff --git a/src/graphql-aspnet/Engine/TypeMakers/GraphFieldMaker.cs b/src/graphql-aspnet/Engine/TypeMakers/GraphFieldMaker.cs index 469368f2c..65e62092b 100644 --- a/src/graphql-aspnet/Engine/TypeMakers/GraphFieldMaker.cs +++ b/src/graphql-aspnet/Engine/TypeMakers/GraphFieldMaker.cs @@ -6,6 +6,15 @@ // -- // License: MIT // ************************************************************* + +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* namespace GraphQL.AspNet.Engine.TypeMakers { using System; @@ -14,7 +23,6 @@ namespace GraphQL.AspNet.Engine.TypeMakers using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Common.Generics; using GraphQL.AspNet.Configuration.Formatting; - using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Interfaces.Engine; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; @@ -121,6 +129,7 @@ protected virtual MethodGraphField InstantiateField( formatter.FormatFieldName(template.Name), template.TypeExpression.CloneTo(formatter.FormatGraphTypeName(template.TypeExpression.TypeName)), template.Route, + template.DeclaredName, template.ObjectType, template.DeclaredReturnType, template.Mode, diff --git a/src/graphql-aspnet/Execution/GraphSchemaInitializer.cs b/src/graphql-aspnet/Execution/GraphSchemaInitializer.cs index a74b6691b..ab8162071 100644 --- a/src/graphql-aspnet/Execution/GraphSchemaInitializer.cs +++ b/src/graphql-aspnet/Execution/GraphSchemaInitializer.cs @@ -67,7 +67,7 @@ public void Initialize(TSchema schema) var manager = new GraphSchemaManager(schema); manager.AddBuiltInDirectives(); - // add any configured types to this instance + // Step 1: Register any configured types to this instance // -------------------------------------- foreach (var registration in _options.SchemaTypesToRegister) { @@ -78,7 +78,7 @@ public void Initialize(TSchema schema) manager.EnsureGraphType(registration.Type, registration.TypeKind); } - // add in any runtime configured fields and directives (minimal api) + // Step 2: Register any runtime configured fields and directives (minimal api) // -------------------------------------- var runtimeFields = _options.RuntimeTemplates .Where(x => x is IGraphQLRuntimeResolvedFieldDefinition) @@ -87,19 +87,27 @@ public void Initialize(TSchema schema) foreach (var field in runtimeFields) manager.AddRuntimeFieldDeclaration(field); - // execute any assigned schema configuration extensions - // ----------------------- - // this includes any late bound directives added to the type - // system via .ApplyDirective() + // Step 3: execute any assigned schema configuration extensions + // -------------------------------------- + // this includes any late bound directives added to the type system via .ApplyDirective() foreach (var extension in _options.ConfigurationExtensions) extension.Configure(schema); - // apply all queued type system directives + // Step 4: Set runtime properties of all fields on all objects + // and interfaces to determine if they are part of the schema + // or read from the DI container + // -------------------------------------- + // manager.RebuildFieldArgumentSourceLocations(); + + // Step 5: apply all queued type system directives + // -------------------------------------- var processor = new DirectiveProcessorTypeSystem( _serviceProvider, new QuerySession()); processor.ApplyDirectives(schema); + // Step 6: Generate the schema's final introspection data + // -------------------------------------- manager.RebuildIntrospectionData(); schema.IsInitialized = true; } diff --git a/src/graphql-aspnet/Execution/RulesEngine/RuleSets/DocumentValidation/FieldSelectionSteps/Rule_5_4_2_1_RequiredArgumentMustBeSuppliedOrHaveDefaultValueOnField.cs b/src/graphql-aspnet/Execution/RulesEngine/RuleSets/DocumentValidation/FieldSelectionSteps/Rule_5_4_2_1_RequiredArgumentMustBeSuppliedOrHaveDefaultValueOnField.cs index 4b322e613..442ceb536 100644 --- a/src/graphql-aspnet/Execution/RulesEngine/RuleSets/DocumentValidation/FieldSelectionSteps/Rule_5_4_2_1_RequiredArgumentMustBeSuppliedOrHaveDefaultValueOnField.cs +++ b/src/graphql-aspnet/Execution/RulesEngine/RuleSets/DocumentValidation/FieldSelectionSteps/Rule_5_4_2_1_RequiredArgumentMustBeSuppliedOrHaveDefaultValueOnField.cs @@ -35,9 +35,7 @@ public override bool Execute(DocumentValidationContext context) // any argument flaged as being a source input (such as for type extensions) // or internal (such as subscription event sources) // and can be skipped when validating query document - if (argument.ArgumentModifiers.IsSourceParameter()) - continue; - if (argument.ArgumentModifiers.IsInternalParameter()) + if (argument.ArgumentModifiers.IsNotPartOfTheSchema()) continue; if (argument.IsRequired && diff --git a/src/graphql-aspnet/Execution/RulesEngine/RuleSets/DocumentValidation/QueryDirectiveSteps/Rule_5_4_2_1_RequiredArgumentMustBeSuppliedOrHaveDefaultValueOnDirective.cs b/src/graphql-aspnet/Execution/RulesEngine/RuleSets/DocumentValidation/QueryDirectiveSteps/Rule_5_4_2_1_RequiredArgumentMustBeSuppliedOrHaveDefaultValueOnDirective.cs index 7f8e61530..8110f8a23 100644 --- a/src/graphql-aspnet/Execution/RulesEngine/RuleSets/DocumentValidation/QueryDirectiveSteps/Rule_5_4_2_1_RequiredArgumentMustBeSuppliedOrHaveDefaultValueOnDirective.cs +++ b/src/graphql-aspnet/Execution/RulesEngine/RuleSets/DocumentValidation/QueryDirectiveSteps/Rule_5_4_2_1_RequiredArgumentMustBeSuppliedOrHaveDefaultValueOnDirective.cs @@ -40,9 +40,7 @@ public override bool Execute(DocumentValidationContext context) // any argument flaged as being a source input (such as for type extensions) // or internal (such as subscription event sources) // and can be skipped when validating query document - if (argument.ArgumentModifiers.IsSourceParameter()) - continue; - if (argument.ArgumentModifiers.IsInternalParameter()) + if (argument.ArgumentModifiers.IsNotPartOfTheSchema()) continue; if (argument.IsRequired && !suppliedArgs.ContainsKey(argument.Name.AsMemory())) diff --git a/src/graphql-aspnet/Interfaces/Schema/IGraphFieldBase.cs b/src/graphql-aspnet/Interfaces/Schema/IGraphFieldBase.cs index 2c8953d25..d37946ad5 100644 --- a/src/graphql-aspnet/Interfaces/Schema/IGraphFieldBase.cs +++ b/src/graphql-aspnet/Interfaces/Schema/IGraphFieldBase.cs @@ -15,7 +15,7 @@ namespace GraphQL.AspNet.Interfaces.Schema /// /// A base set of items common between all field types (input, interface or object based fields). /// - public interface IGraphFieldBase : ISchemaItem + public interface IGraphFieldBase : ITypedSchemaItem, ISchemaItem { /// /// Updates the known graph type this field belongs to. @@ -48,13 +48,5 @@ public interface IGraphFieldBase : ISchemaItem /// /// true if publish; otherwise, false. bool Publish { get; set; } - - /// - /// Gets the core type of the object (or objects) returned by this field. If this field - /// is meant to return a list of items, this property represents the type of item in - /// that list. - /// - /// The type of the object. - public Type ObjectType { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Internal/TypeTemplates/GraphArgumentTemplate.cs b/src/graphql-aspnet/Internal/TypeTemplates/GraphArgumentTemplate.cs index 8dc951d0f..e4e680fa2 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/GraphArgumentTemplate.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/GraphArgumentTemplate.cs @@ -117,15 +117,11 @@ public virtual void Parse() // since the source data will be an OBJECT type (not INPUT_OBJECT) there is no way the user could have supplied it if (this.IsSourceDataArgument()) { - this.ArgumentModifiers = this.ArgumentModifiers - | GraphArgumentModifiers.Internal - | GraphArgumentModifiers.ParentFieldResult; + this.ArgumentModifiers = this.ArgumentModifiers | GraphArgumentModifiers.ParentFieldResult; } else if (this.IsCancellationTokenArgument()) { - this.ArgumentModifiers = this.ArgumentModifiers - | GraphArgumentModifiers.Internal - | GraphArgumentModifiers.CancellationToken; + this.ArgumentModifiers = this.ArgumentModifiers | GraphArgumentModifiers.CancellationToken; } } @@ -175,7 +171,7 @@ protected virtual bool IsCancellationTokenArgument() /// IEnumerable<Type>. public IEnumerable RetrieveRequiredTypes() { - if (this.ArgumentModifiers.IsInternalParameter()) + if (this.ArgumentModifiers.IsNotPartOfTheSchema()) { // internal parameters should not be injected into the object graph // so they have no dependents @@ -225,7 +221,7 @@ public void ValidateOrThrow() $".NET parameter. (Declared '{this.TypeExpression}' is incompatiable with '{actualTypeExpression}') "); } - if (!this.ArgumentModifiers.IsInternalParameter() && this.ObjectType.IsInterface) + if (this.ArgumentModifiers.IsPartOfTheSchema() && this.ObjectType.IsInterface) { throw new GraphTypeDeclarationException( $"The item '{this.Parent.InternalFullName}' declares an argument '{this.Name}' of type '{this.ObjectType.FriendlyName()}' " + diff --git a/src/graphql-aspnet/Schemas/Structural/GraphFieldCollection.cs b/src/graphql-aspnet/Schemas/Structural/GraphFieldCollection.cs index 9b10e137b..46c9a1825 100644 --- a/src/graphql-aspnet/Schemas/Structural/GraphFieldCollection.cs +++ b/src/graphql-aspnet/Schemas/Structural/GraphFieldCollection.cs @@ -88,6 +88,7 @@ internal IGraphField AddField( fieldName, typeExpression, route, + "GraphQLCustomInternalField", GraphValidation.EliminateNextWrapperFromCoreType(typeof(TReturn)), typeof(TReturn), FieldResolutionMode.PerSourceItem, diff --git a/src/graphql-aspnet/Schemas/TypeSystem/ExtendableGraphTypeExtensions.cs b/src/graphql-aspnet/Schemas/TypeSystem/ExtendableGraphTypeExtensions.cs index 41c702391..51b4b15e5 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/ExtendableGraphTypeExtensions.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/ExtendableGraphTypeExtensions.cs @@ -66,7 +66,7 @@ public static IGraphField Extend( where TSource : class { Validation.ThrowIfNullOrReturn(graphType, nameof(graphType)); - Validation.ThrowIfNullWhiteSpaceOrReturn(fieldName, nameof(fieldName)); + fieldName = Validation.ThrowIfNullWhiteSpaceOrReturn(fieldName, nameof(fieldName)); var fieldRoute = graphType.Route.CreateChild(fieldName); @@ -74,6 +74,7 @@ public static IGraphField Extend( fieldName, typeExpression, fieldRoute, + $"GraphQLExtendedField", GraphValidation.EliminateNextWrapperFromCoreType(typeof(TReturn)), typeof(TReturn), FieldResolutionMode.PerSourceItem, diff --git a/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiers.cs b/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiers.cs index de90d1639..8e19b2ec4 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiers.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiers.cs @@ -23,10 +23,8 @@ public enum GraphArgumentModifiers /// None = 0, - /// - /// This parameter is internal to the server environment and will not be exposed on the object graph. - /// - Internal = 1, + // The Value 1 was deprecated and removed. Its value will not be re-used + // to ensure no cross contamination of old code in referencing libraries. /// /// This parameter is declared to contain the result of the resolved parent field. @@ -38,5 +36,11 @@ public enum GraphArgumentModifiers /// governing the request or the default token if none was supplied on said request. /// CancellationToken = 4, + + /// + /// This parameter is supplied to a field via a DI Container injection. It will not be exposed + /// on the object graph. + /// + Injected = 8, } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiersExtensions.cs b/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiersExtensions.cs index 81a92ada2..bf8e4d3c5 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiersExtensions.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiersExtensions.cs @@ -25,16 +25,6 @@ public static bool IsSourceParameter(this GraphArgumentModifiers modifiers) return modifiers.HasFlag(GraphArgumentModifiers.ParentFieldResult); } - /// - /// Determines whether the modifers indicate the argument is internal and not part of the graph. - /// - /// The modifiers set to check. - /// true if the modifers set declares the internal modifer. - public static bool IsInternalParameter(this GraphArgumentModifiers modifiers) - { - return modifiers.HasFlag(GraphArgumentModifiers.Internal); - } - /// /// Determines whether the modifers indicate the argument is a reference /// to the cancellation token governing the overall request. diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_SchemaField.cs b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_SchemaField.cs index add3b51c9..c8e830fd7 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_SchemaField.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_SchemaField.cs @@ -39,6 +39,7 @@ public Introspection_SchemaField(IntrospectedSchema schema) Constants.ReservedNames.SCHEMA_FIELD, new GraphTypeExpression(Constants.ReservedNames.SCHEMA_TYPE), FIELD_PATH, + nameof(Introspection_SchemaField), resolver: new FunctionGraphFieldResolver((x) => schema.AsCompletedTask())) { this.IntrospectedSchema = Validation.ThrowIfNullOrReturn(schema, nameof(schema)); diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_TypeGraphField.cs b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_TypeGraphField.cs index d97787adb..adb1f0853 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_TypeGraphField.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_TypeGraphField.cs @@ -37,6 +37,7 @@ public Introspection_TypeGraphField(IntrospectedSchema schema) Constants.ReservedNames.TYPE_FIELD, new GraphTypeExpression(Constants.ReservedNames.TYPE_TYPE), FIELD_PATH, + nameof(Introspection_TypeGraphField), mode: FieldResolutionMode.PerSourceItem, resolver: new Schema_TypeGraphFieldResolver(schema)) { diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_TypeNameMetaField.cs b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_TypeNameMetaField.cs index 8e57c44e3..1ed51e251 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_TypeNameMetaField.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_TypeNameMetaField.cs @@ -38,7 +38,8 @@ public Introspection_TypeNameMetaField(string graphTypeName) : base( Constants.ReservedNames.TYPENAME_FIELD, new GraphTypeExpression(Constants.ScalarNames.STRING, MetaGraphTypes.IsNotNull), - FIELD_PATH) + FIELD_PATH, + nameof(Introspection_TypeNameMetaField)) { Validation.ThrowIfNull(graphTypeName, nameof(graphTypeName)); this.UpdateResolver(new FunctionGraphFieldResolver((obj) => graphTypeName.AsCompletedTask()), FieldResolutionMode.PerSourceItem); diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_TypeType.cs b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_TypeType.cs index 0f6066601..175b03085 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_TypeType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_TypeType.cs @@ -59,6 +59,7 @@ public Introspection_TypeType() "fields", new GraphTypeExpression(Constants.ReservedNames.FIELD_TYPE, MetaGraphTypes.IsList, MetaGraphTypes.IsNotNull), new IntrospectedRoutePath(SchemaItemCollections.Types, this.Name, "fields"), + "Introspection_TypeType_Fields", mode: FieldResolutionMode.PerSourceItem, resolver: new Type_TypeGraphFieldResolver()) { @@ -95,6 +96,7 @@ public Introspection_TypeType() "enumValues", new GraphTypeExpression(Constants.ReservedNames.ENUM_VALUE_TYPE, MetaGraphTypes.IsList, MetaGraphTypes.IsNotNull), new IntrospectedRoutePath(SchemaItemCollections.Types, this.Name, Constants.ReservedNames.ENUM_VALUE_TYPE), + "Introspection_TypeType_EnumValues", mode: FieldResolutionMode.PerSourceItem, resolver: new Type_EnumValuesGraphFieldResolver()) { diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedDirective.cs b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedDirective.cs index 0a0617507..b205a8b34 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedDirective.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedDirective.cs @@ -37,7 +37,7 @@ public IntrospectedDirective(IDirective directiveType) public override void Initialize(IntrospectedSchema introspectedSchema) { var list = new List(); - var directiveArguments = this.Directive.Arguments.Where(x => !x.ArgumentModifiers.IsInternalParameter()); + var directiveArguments = this.Directive.Arguments.Where(x => x.ArgumentModifiers.IsPartOfTheSchema()); foreach (var arg in directiveArguments) { var introspectedType = introspectedSchema.FindIntrospectedType(arg.TypeExpression.TypeName); diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedField.cs b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedField.cs index 76fd04be0..766306c70 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedField.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedField.cs @@ -42,7 +42,7 @@ public IntrospectedField(IGraphField field, IntrospectedType introspectedFieldOw public override void Initialize(IntrospectedSchema introspectedSchema) { var list = new List(); - foreach (var arg in _field.Arguments.Where(x => !x.ArgumentModifiers.HasFlag(GraphArgumentModifiers.Internal))) + foreach (var arg in _field.Arguments.Where(x => x.ArgumentModifiers.IsPartOfTheSchema())) { var introspectedType = introspectedSchema.FindIntrospectedType(arg.TypeExpression.TypeName); introspectedType = Introspection.WrapBaseTypeWithModifiers(introspectedType, arg.TypeExpression); diff --git a/src/graphql-aspnet/Schemas/TypeSystem/MethodGraphField.cs b/src/graphql-aspnet/Schemas/TypeSystem/MethodGraphField.cs index f46b05e7c..13c0b0666 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/MethodGraphField.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/MethodGraphField.cs @@ -37,6 +37,8 @@ public class MethodGraphField : IGraphField /// Name of the field in the graph. /// The meta data describing the type of data this field returns. /// The formal route to this field in the object graph. + /// Name of the method this field respresents, as it was declared + /// in C# code. /// The .NET type of the item or items that represent the graph type returned by this field. /// The .NET type as it was declared on the property which generated this field.. /// The mode in which the runtime will process this field. @@ -47,6 +49,7 @@ public MethodGraphField( string fieldName, GraphTypeExpression typeExpression, SchemaItemPath route, + string declaredMethodName, Type objectType = null, Type declaredReturnType = null, FieldResolutionMode mode = FieldResolutionMode.PerSourceItem, @@ -60,6 +63,7 @@ public MethodGraphField( this.Arguments = new GraphFieldArgumentCollection(this); this.ObjectType = objectType; this.DeclaredReturnType = declaredReturnType; + this.InternalName = declaredMethodName; this.AppliedDirectives = directives?.Clone(this) ?? new AppliedDirectiveCollection(this); @@ -67,6 +71,7 @@ public MethodGraphField( this.UpdateResolver(resolver, mode); this.Publish = true; + } /// @@ -150,6 +155,7 @@ protected virtual MethodGraphField CreateNewInstance(IGraphType parent) this.Name, this.TypeExpression.Clone(), parent.Route.CreateChild(this.Name), + this.InternalName, this.ObjectType, this.DeclaredReturnType, this.Mode, @@ -214,5 +220,8 @@ protected virtual MethodGraphField CreateNewInstance(IGraphType parent) /// public IAppliedDirectiveCollection AppliedDirectives { get; } + + /// + public string InternalName { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/TypeSystem/PropertyGraphField.cs b/src/graphql-aspnet/Schemas/TypeSystem/PropertyGraphField.cs index 699056d5e..803ed3a0e 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/PropertyGraphField.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/PropertyGraphField.cs @@ -47,9 +47,8 @@ public PropertyGraphField( IGraphFieldResolver resolver = null, IEnumerable securityPolicies = null, IAppliedDirectiveCollection directives = null) - : base(fieldName, typeExpression, route, objectType, declaredReturnType, mode, resolver, securityPolicies, directives) + : base(fieldName, typeExpression, route, declaredPropertyName, objectType, declaredReturnType, mode, resolver, securityPolicies, directives) { - this.InternalName = declaredPropertyName; } /// @@ -71,12 +70,5 @@ protected override MethodGraphField CreateNewInstance(IGraphType parent) this.SecurityGroups, this.AppliedDirectives); } - - /// - /// Gets a fully qualified name of the type as it exists on the server (i.e. Namespace.ClassName.PropertyName). This name - /// is used in many exceptions and internal error messages. - /// - /// The fully qualified name of the proeprty this field was created from. - public string InternalName { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/TypeSystem/VirtualGraphField.cs b/src/graphql-aspnet/Schemas/TypeSystem/VirtualGraphField.cs index 9416c357d..6bc765673 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/VirtualGraphField.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/VirtualGraphField.cs @@ -66,6 +66,7 @@ public VirtualGraphField( this.TypeExpression = new GraphTypeExpression(parentTypeName); this.Arguments = new GraphFieldArgumentCollection(this); this.Resolver = new GraphControllerRouteFieldResolver(new VirtualResolvedObject(this.TypeExpression.TypeName)); + this.InternalName = $"VirtualField_{this.Name}"; // fields made from controller route parameters have no policies directly unto themselves // any controller class level policies are individually added to fields they declare @@ -192,5 +193,8 @@ public virtual bool CanResolveForGraphType(IGraphType graphType) /// public IAppliedDirectiveCollection AppliedDirectives { get; } + + /// + public string InternalName { get; } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/GraphActionTemplateTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/GraphActionTemplateTests.cs index fc79a83c2..5adcd3aa6 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/GraphActionTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/GraphActionTemplateTests.cs @@ -78,7 +78,6 @@ public void ActionTemplate_Parse_ParameterSameAsReturnTypeIsMarkedSource() var action = this.CreateActionTemplate(nameof(SubscriptionMethodController.SingleMethod)); Assert.AreEqual(1, action.Arguments.Count); - Assert.IsTrue(action.Arguments[0].ArgumentModifiers.HasFlag(GraphArgumentModifiers.Internal)); Assert.IsTrue(action.Arguments[0].ArgumentModifiers.HasFlag(GraphArgumentModifiers.ParentFieldResult)); } @@ -88,7 +87,6 @@ public void ActionTemplate_Parse_ExplicitlyDeclaredSourceIsAttributedCorrectly() var action = this.CreateActionTemplate(nameof(SubscriptionMethodController.ExplicitSourceReference)); Assert.AreEqual(1, action.Arguments.Count); - Assert.IsTrue(action.Arguments[0].ArgumentModifiers.HasFlag(GraphArgumentModifiers.Internal)); Assert.IsTrue(action.Arguments[0].ArgumentModifiers.HasFlag(GraphArgumentModifiers.ParentFieldResult)); } diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/TypeExtensionFieldTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Internal/Templating/TypeExtensionFieldTemplateTests.cs index a3c9994b8..0b1db6629 100644 --- a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/TypeExtensionFieldTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Internal/Templating/TypeExtensionFieldTemplateTests.cs @@ -66,7 +66,6 @@ public void ClassTypeExtension_PropertyCheck() // first arg should be declared for the source data Assert.IsTrue(template.Arguments[0].ArgumentModifiers.HasFlag(GraphArgumentModifiers.ParentFieldResult)); - Assert.IsTrue(template.Arguments[0].ArgumentModifiers.HasFlag(GraphArgumentModifiers.Internal)); } [Test] @@ -87,7 +86,6 @@ public void ClassBatchExtension_PropertyCheck() // first arg should be declared for the source data Assert.IsTrue(template.Arguments[0].ArgumentModifiers.HasFlag(GraphArgumentModifiers.ParentFieldResult)); - Assert.IsTrue(template.Arguments[0].ArgumentModifiers.HasFlag(GraphArgumentModifiers.Internal)); } [Test] @@ -114,7 +112,6 @@ public void StructTypeExtension_PropertyCheck() // first arg should be declared for the source data Assert.IsTrue(template.Arguments[0].ArgumentModifiers.HasFlag(GraphArgumentModifiers.ParentFieldResult)); - Assert.IsTrue(template.Arguments[0].ArgumentModifiers.HasFlag(GraphArgumentModifiers.Internal)); } [Test] @@ -135,7 +132,6 @@ public void StructBatchExtension_PropertyCheck() // first arg should be declared for the source data Assert.IsTrue(template.Arguments[0].ArgumentModifiers.HasFlag(GraphArgumentModifiers.ParentFieldResult)); - Assert.IsTrue(template.Arguments[0].ArgumentModifiers.HasFlag(GraphArgumentModifiers.Internal)); } [Test] @@ -162,7 +158,6 @@ public void InterfaceTypeExtension_PropertyCheck() // first arg should be declared for the source data Assert.IsTrue(template.Arguments[0].ArgumentModifiers.HasFlag(GraphArgumentModifiers.ParentFieldResult)); - Assert.IsTrue(template.Arguments[0].ArgumentModifiers.HasFlag(GraphArgumentModifiers.Internal)); } [Test] @@ -183,7 +178,6 @@ public void InterfaceBatchExtension_PropertyCheck() // first arg should be declared for the source data Assert.IsTrue(template.Arguments[0].ArgumentModifiers.HasFlag(GraphArgumentModifiers.ParentFieldResult)); - Assert.IsTrue(template.Arguments[0].ArgumentModifiers.HasFlag(GraphArgumentModifiers.Internal)); } [Test] diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GraphFieldArgumentCloningTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GraphFieldArgumentCloningTests.cs index 01ea9413d..696775bf1 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/GraphFieldArgumentCloningTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GraphFieldArgumentCloningTests.cs @@ -34,7 +34,7 @@ public void ClonedArgument_PropertyCheck() "argName", GraphTypeExpression.FromDeclaration("String"), new SchemaItemPath("[type]/GraphType1/Field1/Arg1"), - GraphArgumentModifiers.Internal, + GraphArgumentModifiers.ParentFieldResult, "paramName", "internalName", typeof(string), diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GraphFieldCloningTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GraphFieldCloningTests.cs index d2c8c1ea8..73e3a3bc9 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/GraphFieldCloningTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GraphFieldCloningTests.cs @@ -11,6 +11,7 @@ namespace GraphQL.AspNet.Tests.Schemas { using System.Collections.Generic; using System.Linq; + using GraphQL.AspNet.Execution.Parsing.NodeBuilders; using GraphQL.AspNet.Interfaces.Execution; using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Internal.TypeTemplates; @@ -45,6 +46,7 @@ public void MethodField_PropertyCheck() "field1", GraphTypeExpression.FromDeclaration("[Int]"), new SchemaItemPath("[type]/JohnType/field1"), + "internalFieldName", typeof(TwoPropertyObject), typeof(List), AspNet.Execution.FieldResolutionMode.PerSourceItem, @@ -89,6 +91,7 @@ public void MethodField_PropertyCheck() Assert.AreEqual(field.DeprecationReason, clonedField.DeprecationReason); Assert.AreEqual(field.Complexity, clonedField.Complexity); Assert.AreEqual(field.FieldSource, clonedField.FieldSource); + Assert.AreEqual(field.InternalName, clonedField.InternalName); Assert.IsFalse(object.ReferenceEquals(field.TypeExpression, clonedField.TypeExpression)); Assert.IsTrue(object.ReferenceEquals(field.Resolver, clonedField.Resolver)); diff --git a/src/unit-tests/graphql-aspnet-tests/Security/MappedQuery_AuthorizationTests.cs b/src/unit-tests/graphql-aspnet-tests/Security/MappedQuery_AuthorizationTests.cs index 600c74932..038d1f804 100644 --- a/src/unit-tests/graphql-aspnet-tests/Security/MappedQuery_AuthorizationTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Security/MappedQuery_AuthorizationTests.cs @@ -21,7 +21,7 @@ namespace GraphQL.AspNet.Tests.Security public class MappedQuery_AuthorizationTests { [Test] - public async Task MappedQuery_UserWithPolicy_CanAccessMethod() + public async Task MappedQuery_AuthorizedUser_AccessAllowed() { var serverBuilder = new TestServerBuilder(); serverBuilder.AddGraphQL(o => @@ -55,7 +55,7 @@ public async Task MappedQuery_UserWithPolicy_CanAccessMethod() } [Test] - public async Task MappedQuery_UserWithoutPolicy_AccessDenied() + public async Task MappedQuery_UnauthorizedUser_AccessDenied() { var serverBuilder = new TestServerBuilder(); serverBuilder.AddGraphQL(o => From 72ed3ecd2992b50de7a641dce7101a79a5e74f28 Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Sat, 1 Jul 2023 08:47:44 -0700 Subject: [PATCH 17/63] WIP, stubbed out runtime schema item validation --- .../Execution/GraphSchemaInitializer.cs | 11 ++- .../Interfaces/Schema/ISchemaItem.cs | 1 + .../Interfaces/Schema/ISchemaItemValidator.cs | 26 +++++++ .../Schemas/GraphSchemaManager.cs | 67 +++++++++++++++++++ .../Schemas/SchemaItemValidationFactory.cs | 31 +++++++++ .../BaseSchemaItemValidator.cs | 18 +++++ .../Schemas/TypeSystem/SchemaExtensions.cs | 2 +- 7 files changed, 154 insertions(+), 2 deletions(-) create mode 100644 src/graphql-aspnet/Interfaces/Schema/ISchemaItemValidator.cs create mode 100644 src/graphql-aspnet/Schemas/SchemaItemValidationFactory.cs create mode 100644 src/graphql-aspnet/Schemas/SchemaItemValidators/BaseSchemaItemValidator.cs diff --git a/src/graphql-aspnet/Execution/GraphSchemaInitializer.cs b/src/graphql-aspnet/Execution/GraphSchemaInitializer.cs index ab8162071..6744da171 100644 --- a/src/graphql-aspnet/Execution/GraphSchemaInitializer.cs +++ b/src/graphql-aspnet/Execution/GraphSchemaInitializer.cs @@ -97,7 +97,7 @@ public void Initialize(TSchema schema) // and interfaces to determine if they are part of the schema // or read from the DI container // -------------------------------------- - // manager.RebuildFieldArgumentSourceLocations(); + manager.RebuildFieldArgumentSourceLocations(); // Step 5: apply all queued type system directives // -------------------------------------- @@ -108,7 +108,16 @@ public void Initialize(TSchema schema) // Step 6: Generate the schema's final introspection data // -------------------------------------- + manager.RebuildFieldArgumentSourceLocations(); + + // Step 7: Run final validations to ensure the schema is internally consistant + // -------------------------------------- + manager.ValidateSchemaIntegrity(); + + // Step 8: Rebuild introspection data to match the now completed schema instance + // -------------------------------------- manager.RebuildIntrospectionData(); + schema.IsInitialized = true; } } diff --git a/src/graphql-aspnet/Interfaces/Schema/ISchemaItem.cs b/src/graphql-aspnet/Interfaces/Schema/ISchemaItem.cs index a8a472ccd..c196081e3 100644 --- a/src/graphql-aspnet/Interfaces/Schema/ISchemaItem.cs +++ b/src/graphql-aspnet/Interfaces/Schema/ISchemaItem.cs @@ -9,6 +9,7 @@ namespace GraphQL.AspNet.Interfaces.Schema { + using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Schemas.Structural; /// diff --git a/src/graphql-aspnet/Interfaces/Schema/ISchemaItemValidator.cs b/src/graphql-aspnet/Interfaces/Schema/ISchemaItemValidator.cs new file mode 100644 index 000000000..87eb7a34f --- /dev/null +++ b/src/graphql-aspnet/Interfaces/Schema/ISchemaItemValidator.cs @@ -0,0 +1,26 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Interfaces.Schema +{ + /// + /// A runtime validator to check instances to ensure they are + /// usable at runtime. + /// + internal interface ISchemaItemValidator + { + /// + /// Validates that the given is valid and internally consistant + /// with the provided schema instance. + /// + /// The schema item to check. + /// The schema to check against. + void ValidateOrThrow(ISchemaItem schemaItem, ISchema schema); + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/GraphSchemaManager.cs b/src/graphql-aspnet/Schemas/GraphSchemaManager.cs index 1279a12b1..a44a80315 100644 --- a/src/graphql-aspnet/Schemas/GraphSchemaManager.cs +++ b/src/graphql-aspnet/Schemas/GraphSchemaManager.cs @@ -450,6 +450,58 @@ private void EnsureDependents(IGraphItemDependencies dependencySet) } } + /// + /// Inspects the schema's current exposed types and attempts to determine the source location + /// for any arguments of any fields declared on those types. + /// + public void RebuildFieldArgumentSourceLocations() + { + var typesToConfigure = this.Schema.KnownTypes.Where( + x => x.Kind == TypeKind.OBJECT || + x.Kind == TypeKind.INTERFACE || + x.Kind == TypeKind.DIRECTIVE); + + foreach (var type in typesToConfigure) + { + IEnumerable fieldArguments; + switch (type) + { + case IObjectGraphType ogt: + fieldArguments = ogt.Fields.Select(x => x.Arguments); + break; + + case IInterfaceGraphType iigt: + fieldArguments = iigt.Fields.Select(x => x.Arguments); + break; + + case IDirective id: + fieldArguments = new IGraphArgumentCollection[] { id.Arguments }; + break; + + default: + continue; + } + + foreach (var argumentSet in fieldArguments) + { + foreach (var argument in argumentSet) + { + if (argument.ArgumentModifiers.IsPartOfTheSchema()) + { + // need the ability to chagne argument modifiers on IGraphArgument + + // need some validation routines on each ISchemaItem + // to ensure its runtime validity after its been built + // + // how does this relate to template validation some things need to be moved + + + } + } + } + } + } + /// /// Clears, builds and caches the introspection metadata used to describe this schema. If introspection /// fields have not been added to the schema this method does nothing. No changes to the schema @@ -471,6 +523,21 @@ public void RebuildIntrospectionData() field.IntrospectedSchema.Rebuild(); } + /// + /// Validates each registered type, field, argument and directive to ensure that its + /// internally consistance with itself and that the schema is in a usable state. + /// + public void ValidateSchemaIntegrity() + { + var allItems = this.Schema.AllSchemaItems(includeDirectives: true); + + foreach (var item in allItems) + { + var validator = SchemaItemValidationFactory.CreateValidator(item); + validator.ValidateOrThrow(item, this.Schema); + } + } + /// /// Gets the schema being managed and built by this instance. /// diff --git a/src/graphql-aspnet/Schemas/SchemaItemValidationFactory.cs b/src/graphql-aspnet/Schemas/SchemaItemValidationFactory.cs new file mode 100644 index 000000000..fb6546751 --- /dev/null +++ b/src/graphql-aspnet/Schemas/SchemaItemValidationFactory.cs @@ -0,0 +1,31 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Schemas +{ + using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Schemas.SchemaItemValidators; + + /// + /// A factory for producing validator instances that can validate a given + /// consistancy against a target schema. + /// + internal static class SchemaItemValidationFactory + { + /// + /// Creates a validator instance for the given schema item. + /// + /// The schema item. + /// ISchemaItemValidator. + public static ISchemaItemValidator CreateValidator(ISchemaItem schemaItem) + { + return new BaseSchemaItemValidator(); + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/SchemaItemValidators/BaseSchemaItemValidator.cs b/src/graphql-aspnet/Schemas/SchemaItemValidators/BaseSchemaItemValidator.cs new file mode 100644 index 000000000..600942c1f --- /dev/null +++ b/src/graphql-aspnet/Schemas/SchemaItemValidators/BaseSchemaItemValidator.cs @@ -0,0 +1,18 @@ +namespace GraphQL.AspNet.Schemas.SchemaItemValidators +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using System.Threading.Tasks; + using GraphQL.AspNet.Interfaces.Schema; + + internal class BaseSchemaItemValidator : ISchemaItemValidator + { + /// + public void ValidateOrThrow(ISchemaItem schemaItem, ISchema schema) + { + + } + } +} diff --git a/src/graphql-aspnet/Schemas/TypeSystem/SchemaExtensions.cs b/src/graphql-aspnet/Schemas/TypeSystem/SchemaExtensions.cs index 843378a19..4fcea98eb 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/SchemaExtensions.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/SchemaExtensions.cs @@ -33,7 +33,7 @@ public static IEnumerable AllSchemaItems(this ISchema schema, bool foreach (var operationEntry in schema.Operations) yield return operationEntry.Value; - // process each graph item except directives + // process each graph item except directives unless allowed var graphTypesToProcess = schema.KnownTypes.Where(x => (includeDirectives || x.Kind != TypeKind.DIRECTIVE) && !(x is IGraphOperation)); // dont let operations get included twice From c8c5338d29f7399a87839c95ba1632b0c3d29e17 Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Sun, 2 Jul 2023 14:39:45 -0700 Subject: [PATCH 18/63] WIP, decoupled resolver metadata from primary field template --- .../GraphFieldErrorActionResult.cs | 2 +- .../InternalServerErrorGraphActionResult.cs | 4 +- .../RouteNotFoundGraphActionResult.cs | 4 +- .../Controllers/GraphControllerBase.cs | 16 ++-- .../RuntimeFieldExecutionController.cs | 2 +- .../Directives/GraphDirective.cs | 2 +- .../Engine/DefaultGraphEventLogger.cs | 10 +-- .../Execution/ExecutionArgumentCollection.cs | 2 +- .../Execution/GraphSchemaInitializer.cs | 16 +--- .../Execution/IExecutionArgumentCollection.cs | 2 +- ...thod.cs => IGraphFieldResolverMetaData.cs} | 2 +- .../Internal/IGraphDirectiveTemplate.cs | 2 +- .../Internal/IGraphFieldTemplate.cs | 2 + .../Interfaces/Logging/IGraphEventLogger.cs | 10 +-- .../Resolvers/FieldResolverMetaData.cs | 89 +++++++++++++++++++ .../GraphControllerActionResolver.cs | 4 +- .../Resolvers/GraphDirectiveActionResolver.cs | 2 +- .../ObjectMethodGraphFieldResolver.cs | 6 +- .../ObjectPropertyGraphFieldResolver.cs | 4 +- .../ControllerActionGraphFieldTemplate.cs | 15 +++- .../TypeTemplates/GraphArgumentTemplate.cs | 7 -- .../GraphDirectiveMethodTemplate.cs | 19 +++- .../GraphDirectiveMethodTemplateContainer.cs | 4 +- .../TypeTemplates/GraphDirectiveTemplate.cs | 4 +- .../TypeTemplates/GraphFieldTemplateBase.cs | 3 + .../GraphTypeExtensionFieldTemplate.cs | 2 +- .../MethodGraphFieldTemplateBase.cs | 20 ++++- .../PropertyGraphFieldTemplate.cs | 20 ++++- .../ActionMethodExceptionLogEntryBase.cs | 2 +- ...ActionMethodInvocationCompletedLogEntry.cs | 2 +- ...ActionMethodInvocationExceptionLogEntry.cs | 2 +- .../ActionMethodInvocationStartedLogEntry.cs | 2 +- ...ActionMethodModelStateValidatedLogEntry.cs | 2 +- .../ActionMethodUnhandledExceptionLogEntry.cs | 2 +- .../Schemas/GraphSchemaManager.cs | 53 +---------- .../Schemas/SchemaItemValidationFactory.cs | 31 ------- .../BaseSchemaItemValidator.cs | 25 +++--- .../GraphArgumentValidator.cs | 56 ++++++++++++ .../NoValidationSchemaItemValidator.cs | 38 ++++++++ .../SchemaItemValidationFactory.cs | 36 ++++++++ .../Controllers/ControllerExtensionTests.cs | 10 +-- .../Templating/GraphActionTemplateTests.cs | 3 +- .../FieldContextBuilder.cs | 26 +++--- .../TestServer.cs | 8 +- .../ActionResults/ActionResultTests.cs | 4 +- .../Controllers/GraphControllerTests.cs | 16 ++-- .../Internal/ObjectMethodResolverTests.cs | 16 ++-- .../Internal/ObjectPropertyResolverTests.cs | 18 ++-- .../Templating/ActionMethodTemplateTests.cs | 6 +- .../DirectiveMethodTemplateTests.cs | 19 ---- .../Templating/DirectiveTemplateTests.cs | 2 +- .../MethodGraphFieldTemplateTests.cs | 9 -- .../TypeExtensionFieldTemplateTests.cs | 26 +++--- ...nMethodModelStateValidatedLogEntryTests.cs | 10 +-- .../GeneralEventLogEntryPropertyChecks.cs | 15 ++-- .../Schemas/GraphSchemaManagerTests.cs | 34 +++---- .../PocoWithInterfaceArgument.cs | 23 +++++ 57 files changed, 475 insertions(+), 296 deletions(-) rename src/graphql-aspnet/Interfaces/Execution/{IGraphFieldResolverMethod.cs => IGraphFieldResolverMetaData.cs} (98%) create mode 100644 src/graphql-aspnet/Internal/Resolvers/FieldResolverMetaData.cs delete mode 100644 src/graphql-aspnet/Schemas/SchemaItemValidationFactory.cs create mode 100644 src/graphql-aspnet/Schemas/SchemaItemValidators/GraphArgumentValidator.cs create mode 100644 src/graphql-aspnet/Schemas/SchemaItemValidators/NoValidationSchemaItemValidator.cs create mode 100644 src/graphql-aspnet/Schemas/SchemaItemValidators/SchemaItemValidationFactory.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/PocoWithInterfaceArgument.cs diff --git a/src/graphql-aspnet/Controllers/ActionResults/GraphFieldErrorActionResult.cs b/src/graphql-aspnet/Controllers/ActionResults/GraphFieldErrorActionResult.cs index 22f4986bf..1a878fd48 100644 --- a/src/graphql-aspnet/Controllers/ActionResults/GraphFieldErrorActionResult.cs +++ b/src/graphql-aspnet/Controllers/ActionResults/GraphFieldErrorActionResult.cs @@ -16,7 +16,7 @@ namespace GraphQL.AspNet.Controllers.ActionResults using GraphQL.AspNet.Interfaces.Execution; /// - /// An action result indicating that the errored or in some way did + /// An action result indicating that the errored or in some way did /// not fulfill its request for data in an acceptable manner. This result is always interpreted as a /// critical error and stops execution of the current query. /// diff --git a/src/graphql-aspnet/Controllers/ActionResults/InternalServerErrorGraphActionResult.cs b/src/graphql-aspnet/Controllers/ActionResults/InternalServerErrorGraphActionResult.cs index 30af6ad4d..f8dff3dca 100644 --- a/src/graphql-aspnet/Controllers/ActionResults/InternalServerErrorGraphActionResult.cs +++ b/src/graphql-aspnet/Controllers/ActionResults/InternalServerErrorGraphActionResult.cs @@ -23,7 +23,7 @@ namespace GraphQL.AspNet.Controllers.ActionResults public class InternalServerErrorGraphActionResult : IGraphActionResult { private readonly string _errorMessage; - private readonly IGraphFieldResolverMethod _action; + private readonly IGraphFieldResolverMetaData _action; private readonly Exception _exception; /// @@ -51,7 +51,7 @@ public InternalServerErrorGraphActionResult(string errorMessage, Exception excep /// /// The action that was invoked to cause this internal error, if any. /// The exception, if any, that was thrown. Useful for logging or other intermediate actions. - public InternalServerErrorGraphActionResult(IGraphFieldResolverMethod action, Exception exception) + public InternalServerErrorGraphActionResult(IGraphFieldResolverMetaData action, Exception exception) { _action = action; _errorMessage = $"An unhandled exception was thrown during the execution of field '{_action?.Name ?? "-unknown-"}'."; diff --git a/src/graphql-aspnet/Controllers/ActionResults/RouteNotFoundGraphActionResult.cs b/src/graphql-aspnet/Controllers/ActionResults/RouteNotFoundGraphActionResult.cs index cc417f989..b55c6072d 100644 --- a/src/graphql-aspnet/Controllers/ActionResults/RouteNotFoundGraphActionResult.cs +++ b/src/graphql-aspnet/Controllers/ActionResults/RouteNotFoundGraphActionResult.cs @@ -22,7 +22,7 @@ namespace GraphQL.AspNet.Controllers.ActionResults /// public class RouteNotFoundGraphActionResult : IGraphActionResult { - private readonly IGraphFieldResolverMethod _invokeDef; + private readonly IGraphFieldResolverMetaData _invokeDef; private readonly Exception _thrownException; private readonly string _message; @@ -31,7 +31,7 @@ public class RouteNotFoundGraphActionResult : IGraphActionResult /// /// The invoked action at the route location. /// The thrown exception that occured when invoking the action, if any. - public RouteNotFoundGraphActionResult(IGraphFieldResolverMethod invokedAction, Exception thrownException = null) + public RouteNotFoundGraphActionResult(IGraphFieldResolverMetaData invokedAction, Exception thrownException = null) { _invokeDef = invokedAction; _thrownException = thrownException; diff --git a/src/graphql-aspnet/Controllers/GraphControllerBase.cs b/src/graphql-aspnet/Controllers/GraphControllerBase.cs index 0c643e433..c04417c05 100644 --- a/src/graphql-aspnet/Controllers/GraphControllerBase.cs +++ b/src/graphql-aspnet/Controllers/GraphControllerBase.cs @@ -34,7 +34,7 @@ public abstract class GraphControllerBase where TRequest : class, IDataRequest { private SchemaItemResolutionContext _schemaItemContext; - private IGraphFieldResolverMethod _action; + private IGraphFieldResolverMetaData _action; /// /// Invoke the specified action method as an asynchronous operation. @@ -44,7 +44,7 @@ public abstract class GraphControllerBase /// Task<System.Object>. [GraphSkip] internal virtual async Task InvokeActionAsync( - IGraphFieldResolverMethod actionToInvoke, + IGraphFieldResolverMetaData actionToInvoke, SchemaItemResolutionContext schemaItemContext) { // deconstruct the context for processing @@ -127,28 +127,28 @@ internal virtual async Task InvokeActionAsync( } /// - /// Invoke the actual C# method declared by the + /// Invoke the actual C# method declared by the /// using this controller instance as the target object of the invocation. /// - /// The resolver declaration that needs to be executed. + /// The resolver declaration that needs to be executed. /// The realized set of arguments that need /// to be passed to the invocable method instance. /// The exact return value from the invoked resolver. - protected virtual object CreateAndInvokeAction(IGraphFieldResolverMethod resolver, object[] invocationArguments) + protected virtual object CreateAndInvokeAction(IGraphFieldResolverMetaData methodMetadata, object[] invocationArguments) { - if (resolver.Method.DeclaringType != this.GetType()) + if (methodMetadata.Method.DeclaringType != this.GetType()) { throw new TargetException($"Unable to invoke action '{_action.Route.Path}' on controller '{this.GetType().FriendlyName()}'. The controller " + "does not own the method."); } - if (resolver.Method.IsStatic) + if (methodMetadata.Method.IsStatic) { throw new TargetException($"Unable to invoke action '{_action.Route.Path}' on controller '{this.GetType().FriendlyName()}'. The method " + "is static and cannot be directly invoked on this controller instance."); } - var invoker = InstanceFactory.CreateInstanceMethodInvoker(resolver.Method); + var invoker = InstanceFactory.CreateInstanceMethodInvoker(methodMetadata.Method); var controllerRef = this as object; return invoker(ref controllerRef, invocationArguments); diff --git a/src/graphql-aspnet/Controllers/RuntimeFieldExecutionController.cs b/src/graphql-aspnet/Controllers/RuntimeFieldExecutionController.cs index 9b2618ca8..de4d53097 100644 --- a/src/graphql-aspnet/Controllers/RuntimeFieldExecutionController.cs +++ b/src/graphql-aspnet/Controllers/RuntimeFieldExecutionController.cs @@ -21,7 +21,7 @@ namespace GraphQL.AspNet.Controllers internal sealed class RuntimeFieldExecutionController : GraphController { /// - protected override object CreateAndInvokeAction(IGraphFieldResolverMethod resolver, object[] invocationArguments) + protected override object CreateAndInvokeAction(IGraphFieldResolverMetaData resolver, object[] invocationArguments) { // minimal api resolvers are allowed to be static since there is no // extra context to setup or make available such as 'this.User' etc. diff --git a/src/graphql-aspnet/Directives/GraphDirective.cs b/src/graphql-aspnet/Directives/GraphDirective.cs index 3cfb23c47..6045b7e5f 100644 --- a/src/graphql-aspnet/Directives/GraphDirective.cs +++ b/src/graphql-aspnet/Directives/GraphDirective.cs @@ -28,7 +28,7 @@ public abstract partial class GraphDirective : GraphControllerBase internal override Task InvokeActionAsync( - IGraphFieldResolverMethod actionToInvoke, + IGraphFieldResolverMetaData actionToInvoke, SchemaItemResolutionContext context) { Validation.ThrowIfNull(context, nameof(context)); diff --git a/src/graphql-aspnet/Engine/DefaultGraphEventLogger.cs b/src/graphql-aspnet/Engine/DefaultGraphEventLogger.cs index 2b9ea655e..b6d1e8ecd 100644 --- a/src/graphql-aspnet/Engine/DefaultGraphEventLogger.cs +++ b/src/graphql-aspnet/Engine/DefaultGraphEventLogger.cs @@ -224,7 +224,7 @@ public virtual void FieldResolutionCompleted(FieldResolutionContext context) } /// - public virtual void ActionMethodInvocationRequestStarted(IGraphFieldResolverMethod action, IDataRequest request) + public virtual void ActionMethodInvocationRequestStarted(IGraphFieldResolverMetaData action, IDataRequest request) { if (!this.IsEnabled(LogLevel.Trace)) return; @@ -234,7 +234,7 @@ public virtual void ActionMethodInvocationRequestStarted(IGraphFieldResolverMeth } /// - public virtual void ActionMethodModelStateValidated(IGraphFieldResolverMethod action, IDataRequest request, InputModelStateDictionary modelState) + public virtual void ActionMethodModelStateValidated(IGraphFieldResolverMetaData action, IDataRequest request, InputModelStateDictionary modelState) { if (!this.IsEnabled(LogLevel.Trace)) return; @@ -244,7 +244,7 @@ public virtual void ActionMethodModelStateValidated(IGraphFieldResolverMethod ac } /// - public virtual void ActionMethodInvocationException(IGraphFieldResolverMethod action, IDataRequest request, Exception exception) + public virtual void ActionMethodInvocationException(IGraphFieldResolverMetaData action, IDataRequest request, Exception exception) { if (!this.IsEnabled(LogLevel.Error)) return; @@ -254,7 +254,7 @@ public virtual void ActionMethodInvocationException(IGraphFieldResolverMethod ac } /// - public virtual void ActionMethodUnhandledException(IGraphFieldResolverMethod action, IDataRequest request, Exception exception) + public virtual void ActionMethodUnhandledException(IGraphFieldResolverMetaData action, IDataRequest request, Exception exception) { if (!this.IsEnabled(LogLevel.Error)) return; @@ -264,7 +264,7 @@ public virtual void ActionMethodUnhandledException(IGraphFieldResolverMethod act } /// - public virtual void ActionMethodInvocationCompleted(IGraphFieldResolverMethod action, IDataRequest request, object result) + public virtual void ActionMethodInvocationCompleted(IGraphFieldResolverMetaData action, IDataRequest request, object result) { if (!this.IsEnabled(LogLevel.Trace)) return; diff --git a/src/graphql-aspnet/Execution/ExecutionArgumentCollection.cs b/src/graphql-aspnet/Execution/ExecutionArgumentCollection.cs index e8db459ad..9b48f463f 100644 --- a/src/graphql-aspnet/Execution/ExecutionArgumentCollection.cs +++ b/src/graphql-aspnet/Execution/ExecutionArgumentCollection.cs @@ -85,7 +85,7 @@ public bool TryGetArgument(string argumentName, out TType argumentValue) } /// - public object[] PrepareArguments(IGraphFieldResolverMethod graphMethod) + public object[] PrepareArguments(IGraphFieldResolverMetaData graphMethod) { var preparedParams = new List(); var paramInfos = graphMethod.Parameters; diff --git a/src/graphql-aspnet/Execution/GraphSchemaInitializer.cs b/src/graphql-aspnet/Execution/GraphSchemaInitializer.cs index 6744da171..dbc7bda74 100644 --- a/src/graphql-aspnet/Execution/GraphSchemaInitializer.cs +++ b/src/graphql-aspnet/Execution/GraphSchemaInitializer.cs @@ -93,28 +93,18 @@ public void Initialize(TSchema schema) foreach (var extension in _options.ConfigurationExtensions) extension.Configure(schema); - // Step 4: Set runtime properties of all fields on all objects - // and interfaces to determine if they are part of the schema - // or read from the DI container - // -------------------------------------- - manager.RebuildFieldArgumentSourceLocations(); - - // Step 5: apply all queued type system directives + // Step 4: apply all queued type system directives // -------------------------------------- var processor = new DirectiveProcessorTypeSystem( _serviceProvider, new QuerySession()); processor.ApplyDirectives(schema); - // Step 6: Generate the schema's final introspection data - // -------------------------------------- - manager.RebuildFieldArgumentSourceLocations(); - - // Step 7: Run final validations to ensure the schema is internally consistant + // Step 5: Run final validations to ensure the schema is internally consistant // -------------------------------------- manager.ValidateSchemaIntegrity(); - // Step 8: Rebuild introspection data to match the now completed schema instance + // Step 6: Rebuild introspection data to match the now completed schema instance // -------------------------------------- manager.RebuildIntrospectionData(); diff --git a/src/graphql-aspnet/Interfaces/Execution/IExecutionArgumentCollection.cs b/src/graphql-aspnet/Interfaces/Execution/IExecutionArgumentCollection.cs index f92505b43..d86ffef80 100644 --- a/src/graphql-aspnet/Interfaces/Execution/IExecutionArgumentCollection.cs +++ b/src/graphql-aspnet/Interfaces/Execution/IExecutionArgumentCollection.cs @@ -48,7 +48,7 @@ public interface IExecutionArgumentCollection : IReadOnlyDictionary /// The graph method. /// System.Object[]. - object[] PrepareArguments(IGraphFieldResolverMethod graphMethod); + object[] PrepareArguments(IGraphFieldResolverMetaData graphMethod); /// /// Gets the source data, if any, that is supplying values for this execution run. diff --git a/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverMethod.cs b/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverMetaData.cs similarity index 98% rename from src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverMethod.cs rename to src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverMetaData.cs index 22e4a4579..1c4003773 100644 --- a/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverMethod.cs +++ b/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverMetaData.cs @@ -23,7 +23,7 @@ namespace GraphQL.AspNet.Interfaces.Execution /// This interface describes the "bridge" between a field on an schema /// and the C# code from which that field originated. /// - public interface IGraphFieldResolverMethod + public interface IGraphFieldResolverMetaData { /// /// Gets the type template from which this method was generated. diff --git a/src/graphql-aspnet/Interfaces/Internal/IGraphDirectiveTemplate.cs b/src/graphql-aspnet/Interfaces/Internal/IGraphDirectiveTemplate.cs index d7dbb6c38..ba84910c1 100644 --- a/src/graphql-aspnet/Interfaces/Internal/IGraphDirectiveTemplate.cs +++ b/src/graphql-aspnet/Interfaces/Internal/IGraphDirectiveTemplate.cs @@ -24,7 +24,7 @@ public interface IGraphDirectiveTemplate : IGraphTypeTemplate /// /// The location. /// IGraphMethod. - IGraphFieldResolverMethod FindMethod(DirectiveLocation location); + IGraphFieldResolverMetaData FindMetaData(DirectiveLocation location); /// /// Creates a resolver capable of completing a resolution of this directive. diff --git a/src/graphql-aspnet/Interfaces/Internal/IGraphFieldTemplate.cs b/src/graphql-aspnet/Interfaces/Internal/IGraphFieldTemplate.cs index 5d1a0caa9..9fb8f68c0 100644 --- a/src/graphql-aspnet/Interfaces/Internal/IGraphFieldTemplate.cs +++ b/src/graphql-aspnet/Interfaces/Internal/IGraphFieldTemplate.cs @@ -27,6 +27,8 @@ public interface IGraphFieldTemplate : IGraphFieldTemplateBase, ISecureItem /// IGraphFieldResolver. IGraphFieldResolver CreateResolver(); + IGraphFieldResolverMetaData CreateResolverMetaData(); + /// /// Gets the return type of this field as its declared in the C# code base with no modifications or /// coerions applied. diff --git a/src/graphql-aspnet/Interfaces/Logging/IGraphEventLogger.cs b/src/graphql-aspnet/Interfaces/Logging/IGraphEventLogger.cs index 6eca2ff3e..e6306dfef 100644 --- a/src/graphql-aspnet/Interfaces/Logging/IGraphEventLogger.cs +++ b/src/graphql-aspnet/Interfaces/Logging/IGraphEventLogger.cs @@ -137,7 +137,7 @@ void QueryPlanCacheFetchHit(string key) /// /// The action method on the controller being invoked. /// The request being completed by the action method. - void ActionMethodInvocationRequestStarted(IGraphFieldResolverMethod action, IDataRequest request); + void ActionMethodInvocationRequestStarted(IGraphFieldResolverMetaData action, IDataRequest request); /// /// Recorded when a controller completes validation of the model data that will be passed @@ -146,7 +146,7 @@ void QueryPlanCacheFetchHit(string key) /// The action method on the controller being invoked. /// The request being completed by the action method. /// The model data that was validated. - void ActionMethodModelStateValidated(IGraphFieldResolverMethod action, IDataRequest request, InputModelStateDictionary modelState); + void ActionMethodModelStateValidated(IGraphFieldResolverMetaData action, IDataRequest request, InputModelStateDictionary modelState); /// /// Recorded after a controller invokes and receives a result from an action method. @@ -154,7 +154,7 @@ void QueryPlanCacheFetchHit(string key) /// The action method on the controller being invoked. /// The request being completed by the action method. /// The result object that was returned from the action method. - void ActionMethodInvocationCompleted(IGraphFieldResolverMethod action, IDataRequest request, object result); + void ActionMethodInvocationCompleted(IGraphFieldResolverMetaData action, IDataRequest request, object result); /// /// Recorded when the invocation of action method generated a known exception; generally @@ -163,7 +163,7 @@ void QueryPlanCacheFetchHit(string key) /// The action method on the controller being invoked. /// The request being completed by the action method. /// The exception that was generated. - void ActionMethodInvocationException(IGraphFieldResolverMethod action, IDataRequest request, Exception exception); + void ActionMethodInvocationException(IGraphFieldResolverMetaData action, IDataRequest request, Exception exception); /// /// Recorded when the invocation of action method generated an unknown exception. This @@ -172,7 +172,7 @@ void QueryPlanCacheFetchHit(string key) /// The action method on the controller being invoked. /// The request being completed by the action method. /// The exception that was generated. - void ActionMethodUnhandledException(IGraphFieldResolverMethod action, IDataRequest request, Exception exception); + void ActionMethodUnhandledException(IGraphFieldResolverMetaData action, IDataRequest request, Exception exception); /// /// Recorded by an executor after the entire graphql operation has been completed diff --git a/src/graphql-aspnet/Internal/Resolvers/FieldResolverMetaData.cs b/src/graphql-aspnet/Internal/Resolvers/FieldResolverMetaData.cs new file mode 100644 index 000000000..58ed2dc97 --- /dev/null +++ b/src/graphql-aspnet/Internal/Resolvers/FieldResolverMetaData.cs @@ -0,0 +1,89 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Internal.Resolvers +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Reflection; + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Interfaces.Execution; + using GraphQL.AspNet.Interfaces.Internal; + using GraphQL.AspNet.Schemas.Structural; + + /// + /// A concrete class that implements . Used by the templating + /// engine to generate invocation info for any method or property. + /// + internal class FieldResolverMetaData : IGraphFieldResolverMetaData + { + public FieldResolverMetaData( + IGraphTypeTemplate parent, + MethodInfo method, + IEnumerable parameters, + IEnumerable arguments, + Type expectedReturnType, + Type objectType, + SchemaItemPath route, + bool isAsyncField, + string name, + string internalName, + string internalFullName) + { + this.Method = Validation.ThrowIfNullOrReturn(method, nameof(method)); + this.Route = Validation.ThrowIfNullOrReturn(route, nameof(route)); + this.Parent = Validation.ThrowIfNullOrReturn(parent, nameof(parent)); + + this.ObjectType = Validation.ThrowIfNullOrReturn(objectType, nameof(objectType)); + this.ExpectedReturnType = Validation.ThrowIfNullOrReturn(expectedReturnType, nameof(expectedReturnType)); + + this.IsAsyncField = isAsyncField; + this.Parameters = new List(parameters ?? Enumerable.Empty()); + this.Arguments = new List(arguments ?? Enumerable.Empty()); + + this.Name = Validation.ThrowIfNullWhiteSpaceOrReturn(name, nameof(name)); + this.InternalName = Validation.ThrowIfNullWhiteSpaceOrReturn(internalName, nameof(internalName)); + this.InternalFullName = Validation.ThrowIfNullWhiteSpaceOrReturn(internalFullName, nameof(internalFullName)); + } + + /// + public Type ExpectedReturnType { get; } + + /// + public MethodInfo Method { get; } + + /// + public bool IsAsyncField { get; } + + /// + public string Name { get; } + + /// + public string InternalFullName { get; } + + /// + public string InternalName { get; } + + /// + public IGraphTypeTemplate Parent { get; } + + /// + public Type ObjectType { get; } + + /// + public IReadOnlyList Parameters { get; } + + /// + public SchemaItemPath Route { get; } + + /// + public IReadOnlyList Arguments { get; } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Internal/Resolvers/GraphControllerActionResolver.cs b/src/graphql-aspnet/Internal/Resolvers/GraphControllerActionResolver.cs index 028ae10d1..b0b52703c 100644 --- a/src/graphql-aspnet/Internal/Resolvers/GraphControllerActionResolver.cs +++ b/src/graphql-aspnet/Internal/Resolvers/GraphControllerActionResolver.cs @@ -26,13 +26,13 @@ namespace GraphQL.AspNet.Internal.Resolvers /// internal class GraphControllerActionResolver : GraphControllerActionResolverBase, IGraphFieldResolver { - private readonly IGraphFieldResolverMethod _actionMethod; + private readonly IGraphFieldResolverMetaData _actionMethod; /// /// Initializes a new instance of the class. /// /// The action method that this resolver will invoke. - public GraphControllerActionResolver(IGraphFieldResolverMethod actionMethod) + public GraphControllerActionResolver(IGraphFieldResolverMetaData actionMethod) { _actionMethod = Validation.ThrowIfNullOrReturn(actionMethod, nameof(actionMethod)); } diff --git a/src/graphql-aspnet/Internal/Resolvers/GraphDirectiveActionResolver.cs b/src/graphql-aspnet/Internal/Resolvers/GraphDirectiveActionResolver.cs index 6543bd4d7..460efc688 100644 --- a/src/graphql-aspnet/Internal/Resolvers/GraphDirectiveActionResolver.cs +++ b/src/graphql-aspnet/Internal/Resolvers/GraphDirectiveActionResolver.cs @@ -44,7 +44,7 @@ public GraphDirectiveActionResolver(IGraphDirectiveTemplate directiveTemplate) /// public async Task ResolveAsync(DirectiveResolutionContext context, CancellationToken cancelToken = default) { - var action = _directiveTemplate.FindMethod(context.Request.InvocationContext.Location); + var action = _directiveTemplate.FindMetaData(context.Request.InvocationContext.Location); // if no action is found skip processing of this directive if (action == null) diff --git a/src/graphql-aspnet/Internal/Resolvers/ObjectMethodGraphFieldResolver.cs b/src/graphql-aspnet/Internal/Resolvers/ObjectMethodGraphFieldResolver.cs index 14cf1bd43..56eb2f2c5 100644 --- a/src/graphql-aspnet/Internal/Resolvers/ObjectMethodGraphFieldResolver.cs +++ b/src/graphql-aspnet/Internal/Resolvers/ObjectMethodGraphFieldResolver.cs @@ -22,18 +22,18 @@ namespace GraphQL.AspNet.Internal.Resolvers /// /// A field resolver that will invoke a schema pipeline for whatever schema is beng processed - /// resulting in the configured handling the request. + /// resulting in the configured handling the request. /// internal class ObjectMethodGraphFieldResolver : IGraphFieldResolver { - private readonly IGraphFieldResolverMethod _graphMethod; + private readonly IGraphFieldResolverMetaData _graphMethod; private readonly MethodInfo _methodInfo; /// /// Initializes a new instance of the class. /// /// A resolver method that points to a .NET method. - public ObjectMethodGraphFieldResolver(IGraphFieldResolverMethod graphMethod) + public ObjectMethodGraphFieldResolver(IGraphFieldResolverMetaData graphMethod) { _graphMethod = Validation.ThrowIfNullOrReturn(graphMethod, nameof(graphMethod)); _methodInfo = _graphMethod.Method; diff --git a/src/graphql-aspnet/Internal/Resolvers/ObjectPropertyGraphFieldResolver.cs b/src/graphql-aspnet/Internal/Resolvers/ObjectPropertyGraphFieldResolver.cs index 202c982ec..f042c1874 100644 --- a/src/graphql-aspnet/Internal/Resolvers/ObjectPropertyGraphFieldResolver.cs +++ b/src/graphql-aspnet/Internal/Resolvers/ObjectPropertyGraphFieldResolver.cs @@ -27,13 +27,13 @@ namespace GraphQL.AspNet.Internal.Resolvers [DebuggerDisplay("Prop Resolver: {_graphMethod.Name}")] internal class ObjectPropertyGraphFieldResolver : IGraphFieldResolver { - private readonly IGraphFieldResolverMethod _graphMethod; + private readonly IGraphFieldResolverMetaData _graphMethod; /// /// Initializes a new instance of the class. /// /// A resolver method that points to a .NET property getter. - public ObjectPropertyGraphFieldResolver(IGraphFieldResolverMethod propertyGetMethod) + public ObjectPropertyGraphFieldResolver(IGraphFieldResolverMetaData propertyGetMethod) { _graphMethod = Validation.ThrowIfNullOrReturn(propertyGetMethod, nameof(propertyGetMethod)); } diff --git a/src/graphql-aspnet/Internal/TypeTemplates/ControllerActionGraphFieldTemplate.cs b/src/graphql-aspnet/Internal/TypeTemplates/ControllerActionGraphFieldTemplate.cs index 39b5f76a8..b09003ce6 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/ControllerActionGraphFieldTemplate.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/ControllerActionGraphFieldTemplate.cs @@ -100,7 +100,20 @@ public override void ValidateOrThrow() /// IGraphFieldResolver. public override IGraphFieldResolver CreateResolver() { - return new GraphControllerActionResolver(this); + var metaData = new FieldResolverMetaData( + this.Parent, + this.Method, + this.Parameters, + this.Arguments, + this.ExpectedReturnType, + this.ObjectType, + this.Route, + this.IsAsyncField, + this.Name, + this.InternalName, + this.InternalFullName); + + return new GraphControllerActionResolver(metaData); } /// diff --git a/src/graphql-aspnet/Internal/TypeTemplates/GraphArgumentTemplate.cs b/src/graphql-aspnet/Internal/TypeTemplates/GraphArgumentTemplate.cs index e4e680fa2..f031a5b3d 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/GraphArgumentTemplate.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/GraphArgumentTemplate.cs @@ -221,13 +221,6 @@ public void ValidateOrThrow() $".NET parameter. (Declared '{this.TypeExpression}' is incompatiable with '{actualTypeExpression}') "); } - if (this.ArgumentModifiers.IsPartOfTheSchema() && this.ObjectType.IsInterface) - { - throw new GraphTypeDeclarationException( - $"The item '{this.Parent.InternalFullName}' declares an argument '{this.Name}' of type '{this.ObjectType.FriendlyName()}' " + - $"which is an interface. Interfaces cannot be used as input arguments to any type."); - } - foreach (var directive in this.AppliedDirectives) directive.ValidateOrThrow(); } diff --git a/src/graphql-aspnet/Internal/TypeTemplates/GraphDirectiveMethodTemplate.cs b/src/graphql-aspnet/Internal/TypeTemplates/GraphDirectiveMethodTemplate.cs index 68b706368..ba8277765 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/GraphDirectiveMethodTemplate.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/GraphDirectiveMethodTemplate.cs @@ -24,6 +24,7 @@ namespace GraphQL.AspNet.Internal.TypeTemplates using GraphQL.AspNet.Interfaces.Controllers; using GraphQL.AspNet.Interfaces.Execution; using GraphQL.AspNet.Interfaces.Internal; + using GraphQL.AspNet.Internal.Resolvers; using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; @@ -32,7 +33,7 @@ namespace GraphQL.AspNet.Internal.TypeTemplates /// A template describing an action method declared on a directive. /// [DebuggerDisplay("{InternalName} (Type: {Parent.InternalName})")] - public class GraphDirectiveMethodTemplate : IGraphFieldTemplateBase, IGraphFieldResolverMethod + public class GraphDirectiveMethodTemplate : IGraphFieldTemplateBase { private readonly List _arguments; @@ -192,6 +193,22 @@ public IEnumerable RetrieveRequiredTypes() return list; } + internal IGraphFieldResolverMetaData CreateResolverMetaData() + { + return new FieldResolverMetaData( + this.Parent, + this.Method, + this.Parameters, + this.Arguments, + this.ExpectedReturnType, + this.ObjectType, + this.Route, + this.IsAsyncField, + this.Name, + this.InternalName, + this.InternalFullName); + } + /// /// Gets the bitwise flags of locations that this method is defined /// to handle. diff --git a/src/graphql-aspnet/Internal/TypeTemplates/GraphDirectiveMethodTemplateContainer.cs b/src/graphql-aspnet/Internal/TypeTemplates/GraphDirectiveMethodTemplateContainer.cs index 72b2e38e5..f262446bb 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/GraphDirectiveMethodTemplateContainer.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/GraphDirectiveMethodTemplateContainer.cs @@ -81,10 +81,10 @@ public void RegisterMethod(GraphDirectiveMethodTemplate methodTemplate) /// /// A valid graphql directive location. /// IGraphMethod. - public IGraphFieldResolverMethod FindMethod(DirectiveLocation location) + public IGraphFieldResolverMetaData FindMetaData(DirectiveLocation location) { if (_templateMap.ContainsKey(location)) - return _templateMap[location]; + return _templateMap[location].CreateResolverMetaData(); return null; } diff --git a/src/graphql-aspnet/Internal/TypeTemplates/GraphDirectiveTemplate.cs b/src/graphql-aspnet/Internal/TypeTemplates/GraphDirectiveTemplate.cs index c727072e6..01560599c 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/GraphDirectiveTemplate.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/GraphDirectiveTemplate.cs @@ -84,9 +84,9 @@ protected override void ParseTemplateDefinition() } /// - public IGraphFieldResolverMethod FindMethod(DirectiveLocation location) + public IGraphFieldResolverMetaData FindMetaData(DirectiveLocation location) { - return this.Methods.FindMethod(location); + return this.Methods.FindMetaData(location); } /// diff --git a/src/graphql-aspnet/Internal/TypeTemplates/GraphFieldTemplateBase.cs b/src/graphql-aspnet/Internal/TypeTemplates/GraphFieldTemplateBase.cs index a72d48133..07410a6c1 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/GraphFieldTemplateBase.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/GraphFieldTemplateBase.cs @@ -381,6 +381,9 @@ private void ValidateBatchMethodSignatureOrThrow() /// public abstract IGraphFieldResolver CreateResolver(); + /// + public abstract IGraphFieldResolverMetaData CreateResolverMetaData(); + /// public override IEnumerable RetrieveRequiredTypes() { diff --git a/src/graphql-aspnet/Internal/TypeTemplates/GraphTypeExtensionFieldTemplate.cs b/src/graphql-aspnet/Internal/TypeTemplates/GraphTypeExtensionFieldTemplate.cs index 0c0059f51..7f2e727ae 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/GraphTypeExtensionFieldTemplate.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/GraphTypeExtensionFieldTemplate.cs @@ -88,7 +88,7 @@ protected override void ParseTemplateDefinition() /// public override IGraphFieldResolver CreateResolver() { - return new GraphControllerActionResolver(this); + return new GraphControllerActionResolver(this.CreateResolverMetaData()); } /// diff --git a/src/graphql-aspnet/Internal/TypeTemplates/MethodGraphFieldTemplateBase.cs b/src/graphql-aspnet/Internal/TypeTemplates/MethodGraphFieldTemplateBase.cs index 3ae1f6a62..93bbddfd7 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/MethodGraphFieldTemplateBase.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/MethodGraphFieldTemplateBase.cs @@ -25,7 +25,7 @@ namespace GraphQL.AspNet.Internal.TypeTemplates /// C# methods. /// [DebuggerDisplay("Route: {Route.Path}")] - public abstract class MethodGraphFieldTemplateBase : GraphFieldTemplateBase, IGraphFieldResolverMethod + public abstract class MethodGraphFieldTemplateBase : GraphFieldTemplateBase { private readonly List _arguments; @@ -103,7 +103,23 @@ public override void ValidateOrThrow() /// public override IGraphFieldResolver CreateResolver() { - return new ObjectMethodGraphFieldResolver(this); + return new ObjectMethodGraphFieldResolver(this.CreateResolverMetaData()); + } + + public override IGraphFieldResolverMetaData CreateResolverMetaData() + { + return new FieldResolverMetaData( + this.Parent, + this.Method, + this.Parameters, + this.Arguments, + this.ExpectedReturnType, + this.ObjectType, + this.Route, + this.IsAsyncField, + this.Name, + this.InternalName, + this.InternalFullName); } /// diff --git a/src/graphql-aspnet/Internal/TypeTemplates/PropertyGraphFieldTemplate.cs b/src/graphql-aspnet/Internal/TypeTemplates/PropertyGraphFieldTemplate.cs index b55ac29f5..24f57bebd 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/PropertyGraphFieldTemplate.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/PropertyGraphFieldTemplate.cs @@ -29,7 +29,7 @@ namespace GraphQL.AspNet.Internal.TypeTemplates /// is created from a C# object property. /// [DebuggerDisplay("Route: {Route.Path}")] - public class PropertyGraphFieldTemplate : GraphFieldTemplateBase, IGraphFieldResolverMethod + public class PropertyGraphFieldTemplate : GraphFieldTemplateBase { /// /// Initializes a new instance of the class. @@ -111,7 +111,23 @@ protected override void ParseTemplateDefinition() /// public override IGraphFieldResolver CreateResolver() { - return new ObjectPropertyGraphFieldResolver(this); + return new ObjectPropertyGraphFieldResolver(this.CreateResolverMetaData()); + } + + public override IGraphFieldResolverMetaData CreateResolverMetaData() + { + return new FieldResolverMetaData( + this.Parent, + this.Method, + this.Parameters, + this.Arguments, + this.ExpectedReturnType, + this.ObjectType, + this.Route, + this.IsAsyncField, + this.Name, + this.InternalName, + this.InternalFullName); } /// diff --git a/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodExceptionLogEntryBase.cs b/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodExceptionLogEntryBase.cs index 03091c6b7..a39fd3202 100644 --- a/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodExceptionLogEntryBase.cs +++ b/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodExceptionLogEntryBase.cs @@ -30,7 +30,7 @@ public abstract class ActionMethodExceptionLogEntryBase : GraphLogEntry /// The exception that was thrown. protected ActionMethodExceptionLogEntryBase( EventId eventId, - IGraphFieldResolverMethod method, + IGraphFieldResolverMetaData method, IDataRequest request, Exception exception) : base(eventId) diff --git a/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodInvocationCompletedLogEntry.cs b/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodInvocationCompletedLogEntry.cs index d9a8a3347..3543c7041 100644 --- a/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodInvocationCompletedLogEntry.cs +++ b/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodInvocationCompletedLogEntry.cs @@ -27,7 +27,7 @@ public class ActionMethodInvocationCompletedLogEntry : GraphLogEntry /// The method being invoked. /// The request being executed on the method. /// The result that was generated. - public ActionMethodInvocationCompletedLogEntry(IGraphFieldResolverMethod method, IDataRequest request, object result) + public ActionMethodInvocationCompletedLogEntry(IGraphFieldResolverMetaData method, IDataRequest request, object result) : base(LogEventIds.ControllerInvocationCompleted) { this.PipelineRequestId = request?.Id.ToString(); diff --git a/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodInvocationExceptionLogEntry.cs b/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodInvocationExceptionLogEntry.cs index de92549a7..168e3c08a 100644 --- a/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodInvocationExceptionLogEntry.cs +++ b/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodInvocationExceptionLogEntry.cs @@ -25,7 +25,7 @@ public class ActionMethodInvocationExceptionLogEntry : ActionMethodExceptionLogE /// The request being executed on the method. /// The exception that was thrown. public ActionMethodInvocationExceptionLogEntry( - IGraphFieldResolverMethod method, + IGraphFieldResolverMetaData method, IDataRequest request, Exception exception) : base( diff --git a/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodInvocationStartedLogEntry.cs b/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodInvocationStartedLogEntry.cs index 0f9c37865..152c9d2e0 100644 --- a/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodInvocationStartedLogEntry.cs +++ b/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodInvocationStartedLogEntry.cs @@ -25,7 +25,7 @@ public class ActionMethodInvocationStartedLogEntry : GraphLogEntry /// /// The method being invoked. /// The request being executed on the method. - public ActionMethodInvocationStartedLogEntry(IGraphFieldResolverMethod method, IDataRequest request) + public ActionMethodInvocationStartedLogEntry(IGraphFieldResolverMetaData method, IDataRequest request) : base(LogEventIds.ControllerInvocationStarted) { this.PipelineRequestId = request?.Id.ToString(); diff --git a/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodModelStateValidatedLogEntry.cs b/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodModelStateValidatedLogEntry.cs index 54ff93d7c..676b4b855 100644 --- a/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodModelStateValidatedLogEntry.cs +++ b/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodModelStateValidatedLogEntry.cs @@ -32,7 +32,7 @@ public class ActionMethodModelStateValidatedLogEntry : GraphLogEntry /// The request being executed on the method. /// the model dictionary created by the controller. public ActionMethodModelStateValidatedLogEntry( - IGraphFieldResolverMethod method, + IGraphFieldResolverMetaData method, IDataRequest request, InputModelStateDictionary modelState) : base(LogEventIds.ControllerModelValidated) diff --git a/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodUnhandledExceptionLogEntry.cs b/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodUnhandledExceptionLogEntry.cs index 2d2b4645f..177bceec1 100644 --- a/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodUnhandledExceptionLogEntry.cs +++ b/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodUnhandledExceptionLogEntry.cs @@ -25,7 +25,7 @@ public class ActionMethodUnhandledExceptionLogEntry : ActionMethodExceptionLogEn /// The request being executed on the method. /// The exception that was thrown. public ActionMethodUnhandledExceptionLogEntry( - IGraphFieldResolverMethod method, + IGraphFieldResolverMetaData method, IDataRequest request, Exception exception) : base( diff --git a/src/graphql-aspnet/Schemas/GraphSchemaManager.cs b/src/graphql-aspnet/Schemas/GraphSchemaManager.cs index a44a80315..fecfd4b54 100644 --- a/src/graphql-aspnet/Schemas/GraphSchemaManager.cs +++ b/src/graphql-aspnet/Schemas/GraphSchemaManager.cs @@ -23,6 +23,7 @@ namespace GraphQL.AspNet.Schemas using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Internal; using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Schemas.SchemaItemValidators; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Schemas.TypeSystem.Introspection; @@ -450,58 +451,6 @@ private void EnsureDependents(IGraphItemDependencies dependencySet) } } - /// - /// Inspects the schema's current exposed types and attempts to determine the source location - /// for any arguments of any fields declared on those types. - /// - public void RebuildFieldArgumentSourceLocations() - { - var typesToConfigure = this.Schema.KnownTypes.Where( - x => x.Kind == TypeKind.OBJECT || - x.Kind == TypeKind.INTERFACE || - x.Kind == TypeKind.DIRECTIVE); - - foreach (var type in typesToConfigure) - { - IEnumerable fieldArguments; - switch (type) - { - case IObjectGraphType ogt: - fieldArguments = ogt.Fields.Select(x => x.Arguments); - break; - - case IInterfaceGraphType iigt: - fieldArguments = iigt.Fields.Select(x => x.Arguments); - break; - - case IDirective id: - fieldArguments = new IGraphArgumentCollection[] { id.Arguments }; - break; - - default: - continue; - } - - foreach (var argumentSet in fieldArguments) - { - foreach (var argument in argumentSet) - { - if (argument.ArgumentModifiers.IsPartOfTheSchema()) - { - // need the ability to chagne argument modifiers on IGraphArgument - - // need some validation routines on each ISchemaItem - // to ensure its runtime validity after its been built - // - // how does this relate to template validation some things need to be moved - - - } - } - } - } - } - /// /// Clears, builds and caches the introspection metadata used to describe this schema. If introspection /// fields have not been added to the schema this method does nothing. No changes to the schema diff --git a/src/graphql-aspnet/Schemas/SchemaItemValidationFactory.cs b/src/graphql-aspnet/Schemas/SchemaItemValidationFactory.cs deleted file mode 100644 index fb6546751..000000000 --- a/src/graphql-aspnet/Schemas/SchemaItemValidationFactory.cs +++ /dev/null @@ -1,31 +0,0 @@ -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - -namespace GraphQL.AspNet.Schemas -{ - using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Schemas.SchemaItemValidators; - - /// - /// A factory for producing validator instances that can validate a given - /// consistancy against a target schema. - /// - internal static class SchemaItemValidationFactory - { - /// - /// Creates a validator instance for the given schema item. - /// - /// The schema item. - /// ISchemaItemValidator. - public static ISchemaItemValidator CreateValidator(ISchemaItem schemaItem) - { - return new BaseSchemaItemValidator(); - } - } -} \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/SchemaItemValidators/BaseSchemaItemValidator.cs b/src/graphql-aspnet/Schemas/SchemaItemValidators/BaseSchemaItemValidator.cs index 600942c1f..716f70242 100644 --- a/src/graphql-aspnet/Schemas/SchemaItemValidators/BaseSchemaItemValidator.cs +++ b/src/graphql-aspnet/Schemas/SchemaItemValidators/BaseSchemaItemValidator.cs @@ -1,18 +1,19 @@ -namespace GraphQL.AspNet.Schemas.SchemaItemValidators +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Schemas.SchemaItemValidators { - using System; - using System.Collections.Generic; - using System.Linq; - using System.Text; - using System.Threading.Tasks; using GraphQL.AspNet.Interfaces.Schema; - internal class BaseSchemaItemValidator : ISchemaItemValidator + internal abstract class BaseSchemaItemValidator : ISchemaItemValidator { /// - public void ValidateOrThrow(ISchemaItem schemaItem, ISchema schema) - { - - } + public abstract void ValidateOrThrow(ISchemaItem schemaItem, ISchema schema); } -} +} \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/SchemaItemValidators/GraphArgumentValidator.cs b/src/graphql-aspnet/Schemas/SchemaItemValidators/GraphArgumentValidator.cs new file mode 100644 index 000000000..12b83b368 --- /dev/null +++ b/src/graphql-aspnet/Schemas/SchemaItemValidators/GraphArgumentValidator.cs @@ -0,0 +1,56 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Schemas.SchemaItemValidators +{ + using System; + using GraphQL.AspNet.Common.Extensions; + using GraphQL.AspNet.Execution.Exceptions; + using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Schemas.TypeSystem; + + /// + /// A validator of a completed and schema-attached graph argument that ensures it can function as + /// expected in the target schema. + /// + internal class GraphArgumentValidator : BaseSchemaItemValidator + { + /// + /// Gets the singular instnace of this validator. + /// + /// The instance. + public static ISchemaItemValidator Instance { get; } = new GraphArgumentValidator(); + + /// + /// Prevents a default instance of the class from being created. + /// + private GraphArgumentValidator() + { + } + + /// + public override void ValidateOrThrow(ISchemaItem schemaItem, ISchema schema) + { + var argument = schemaItem as IGraphArgument; + if (argument == null) + { + throw new InvalidCastException( + $"Unable to validate argument. Expected type " + + $"'{typeof(IGraphArgument).FriendlyName()}' but got '{schema?.GetType().FriendlyName() ?? "-none-"}'"); + } + + if (argument.ArgumentModifiers.IsPartOfTheSchema() && argument.ObjectType.IsInterface) + { + throw new GraphTypeDeclarationException( + $"The item '{argument.InternalName}' declares an argument '{argument.Name}' of type '{argument.ObjectType.FriendlyName()}' " + + $"which is an interface. Interfaces cannot be used as input arguments to any type."); + } + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/SchemaItemValidators/NoValidationSchemaItemValidator.cs b/src/graphql-aspnet/Schemas/SchemaItemValidators/NoValidationSchemaItemValidator.cs new file mode 100644 index 000000000..ac49b52ea --- /dev/null +++ b/src/graphql-aspnet/Schemas/SchemaItemValidators/NoValidationSchemaItemValidator.cs @@ -0,0 +1,38 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Schemas.SchemaItemValidators +{ + using GraphQL.AspNet.Interfaces.Schema; + + /// + /// A runtime schema item validator that performs no validation. + /// + internal class NoValidationSchemaItemValidator : BaseSchemaItemValidator + { + /// + /// Gets the singular instnace of this validator. + /// + /// The instance. + public static ISchemaItemValidator Instance { get; } = new NoValidationSchemaItemValidator(); + + /// + /// Prevents a default instance of the class from being created. + /// + private NoValidationSchemaItemValidator() + { + } + + /// + public override void ValidateOrThrow(ISchemaItem schemaItem, ISchema schema) + { + // do nothing + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/SchemaItemValidators/SchemaItemValidationFactory.cs b/src/graphql-aspnet/Schemas/SchemaItemValidators/SchemaItemValidationFactory.cs new file mode 100644 index 000000000..5ef924f0a --- /dev/null +++ b/src/graphql-aspnet/Schemas/SchemaItemValidators/SchemaItemValidationFactory.cs @@ -0,0 +1,36 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Schemas.SchemaItemValidators; + +using GraphQL.AspNet.Interfaces.Schema; + +/// +/// A factory for producing validator instances that can validate a given +/// consistancy against a target schema. +/// +internal static class SchemaItemValidationFactory +{ + /// + /// Creates a validator instance for the given schema item. + /// + /// The schema item. + /// ISchemaItemValidator. + public static ISchemaItemValidator CreateValidator(ISchemaItem schemaItem) + { + switch (schemaItem) + { + case IGraphArgument _: + return GraphArgumentValidator.Instance; + + default: + return NoValidationSchemaItemValidator.Instance; + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Controllers/ControllerExtensionTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Controllers/ControllerExtensionTests.cs index e8083ff58..195e9f3d9 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Controllers/ControllerExtensionTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Controllers/ControllerExtensionTests.cs @@ -40,7 +40,7 @@ public async Task PublishSubEvent_PublishesEventWithCorrectData() var resolutionContext = fieldContextBuilder.CreateResolutionContext(); var controller = new InvokableController(); - var result = await controller.InvokeActionAsync(fieldContextBuilder.GraphMethod.Object, resolutionContext); + var result = await controller.InvokeActionAsync(fieldContextBuilder.ResolverMetaData.Object, resolutionContext); // ensure the method executed completely Assert.IsNotNull(result); @@ -81,7 +81,7 @@ public void PublishSubEvent_NoDataThrowsException() Assert.ThrowsAsync(async () => { - var result = await controller.InvokeActionAsync(fieldContextBuilder.GraphMethod.Object, resolutionContext); + var result = await controller.InvokeActionAsync(fieldContextBuilder.ResolverMetaData.Object, resolutionContext); }); } @@ -103,7 +103,7 @@ public async Task PublishSubEvent_ExistingEventCollectionisAppendedTo() resolutionContext.Session.Items.TryAdd(SubscriptionConstants.ContextDataKeys.RAISED_EVENTS_COLLECTION, eventCollection); var controller = new InvokableController(); - var result = await controller.InvokeActionAsync(fieldContextBuilder.GraphMethod.Object, resolutionContext); + var result = await controller.InvokeActionAsync(fieldContextBuilder.ResolverMetaData.Object, resolutionContext); // ensure the method executed completely Assert.IsNotNull(result); @@ -136,7 +136,7 @@ public void PublishSubEvent_UnusableListForSubscriptionEvents_ThrowsException() var controller = new InvokableController(); Assert.ThrowsAsync(async () => { - var result = await controller.InvokeActionAsync(fieldContextBuilder.GraphMethod.Object, resolutionContext); + var result = await controller.InvokeActionAsync(fieldContextBuilder.ResolverMetaData.Object, resolutionContext); }); } @@ -158,7 +158,7 @@ public void PublishSubEvent_NoEventNameFailsTheResolver_BubblesExceptionUp() Assert.ThrowsAsync(async () => { - var result = await controller.InvokeActionAsync(fieldContextBuilder.GraphMethod.Object, resolutionContext); + var result = await controller.InvokeActionAsync(fieldContextBuilder.ResolverMetaData.Object, resolutionContext); }); } } diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/GraphActionTemplateTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/GraphActionTemplateTests.cs index 5adcd3aa6..c930c93a4 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/GraphActionTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/GraphActionTemplateTests.cs @@ -48,6 +48,7 @@ public void ActionTemplate_Parse_BasicPropertySets() { var methodInfo = typeof(OneMethodSubscriptionController).GetMethod(nameof(OneMethodSubscriptionController.SingleMethod)); var action = this.CreateActionTemplate(nameof(OneMethodSubscriptionController.SingleMethod)); + var metaData = action.CreateResolverMetaData(); Assert.AreEqual("SubDescription", action.Description); Assert.AreEqual(typeof(TwoPropertyObject), action.SourceObjectType); @@ -55,7 +56,7 @@ public void ActionTemplate_Parse_BasicPropertySets() Assert.AreEqual(SchemaItemCollections.Subscription, action.Route.RootCollection); Assert.AreEqual("[subscription]/path0/path1", action.Route.Path); Assert.AreEqual($"{nameof(OneMethodSubscriptionController)}.{nameof(OneMethodSubscriptionController.SingleMethod)}", action.InternalFullName); - Assert.AreEqual(methodInfo.ReflectedType, ((IGraphFieldResolverMethod)action).Parent.ObjectType); + Assert.AreEqual(methodInfo.ReflectedType, metaData.Parent.ObjectType); Assert.AreEqual("path0", action.Parent.Name); Assert.AreEqual(methodInfo, action.Method); Assert.AreEqual(1, action.Arguments.Count); diff --git a/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/FieldContextBuilder.cs b/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/FieldContextBuilder.cs index 5a473b47a..7fa2a2b2c 100644 --- a/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/FieldContextBuilder.cs +++ b/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/FieldContextBuilder.cs @@ -57,7 +57,7 @@ public FieldContextBuilder( IUserSecurityContext userSecurityContext, IGraphField graphField, ISchema schema, - IGraphFieldResolverMethod graphMethod) + IGraphFieldResolverMetaData graphMethod) { _schema = Validation.ThrowIfNullOrReturn(schema, nameof(schema)); _graphField = Validation.ThrowIfNullOrReturn(graphField, nameof(graphField)); @@ -99,17 +99,17 @@ public FieldContextBuilder( _mockRequest.Setup(x => x.Field).Returns(_graphField); _mockRequest.Setup(x => x.InvocationContext).Returns(_mockInvocationContext.Object); - this.GraphMethod = new Mock(); - this.GraphMethod.Setup(x => x.Parent).Returns(graphMethod.Parent); - this.GraphMethod.Setup(x => x.ObjectType).Returns(graphMethod.ObjectType); - this.GraphMethod.Setup(x => x.ExpectedReturnType).Returns(graphMethod.ExpectedReturnType); - this.GraphMethod.Setup(x => x.Method).Returns(graphMethod.Method); - this.GraphMethod.Setup(x => x.IsAsyncField).Returns(graphMethod.IsAsyncField); - this.GraphMethod.Setup(x => x.Name).Returns(graphMethod.Name); - this.GraphMethod.Setup(x => x.InternalFullName).Returns(graphMethod.InternalFullName); - this.GraphMethod.Setup(x => x.InternalName).Returns(graphMethod.InternalName); - this.GraphMethod.Setup(x => x.Route).Returns(graphMethod.Route); - this.GraphMethod.Setup(x => x.Arguments).Returns(graphMethod.Arguments); + this.ResolverMetaData = new Mock(); + this.ResolverMetaData.Setup(x => x.Parent).Returns(graphMethod.Parent); + this.ResolverMetaData.Setup(x => x.ObjectType).Returns(graphMethod.ObjectType); + this.ResolverMetaData.Setup(x => x.ExpectedReturnType).Returns(graphMethod.ExpectedReturnType); + this.ResolverMetaData.Setup(x => x.Method).Returns(graphMethod.Method); + this.ResolverMetaData.Setup(x => x.IsAsyncField).Returns(graphMethod.IsAsyncField); + this.ResolverMetaData.Setup(x => x.Name).Returns(graphMethod.Name); + this.ResolverMetaData.Setup(x => x.InternalFullName).Returns(graphMethod.InternalFullName); + this.ResolverMetaData.Setup(x => x.InternalName).Returns(graphMethod.InternalName); + this.ResolverMetaData.Setup(x => x.Route).Returns(graphMethod.Route); + this.ResolverMetaData.Setup(x => x.Arguments).Returns(graphMethod.Arguments); } /// @@ -249,6 +249,6 @@ public FieldResolutionContext CreateResolutionContext() /// against the testserver. /// /// The graph method. - public Mock GraphMethod { get; } + public Mock ResolverMetaData { get; } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-testframework/TestServer.cs b/src/unit-tests/graphql-aspnet-testframework/TestServer.cs index 5b74fa3f1..f01ebd6ee 100644 --- a/src/unit-tests/graphql-aspnet-testframework/TestServer.cs +++ b/src/unit-tests/graphql-aspnet-testframework/TestServer.cs @@ -201,7 +201,7 @@ public virtual FieldContextBuilder CreateGraphTypeFieldContextBuilder(str /// Name of the field. /// The type kind to resolve the field as (only necessary for input object types). /// IGraphMethod. - public virtual IGraphFieldResolverMethod CreateInvokableReference(string fieldName, TypeKind? typeKind = null) + public virtual IGraphFieldResolverMetaData CreateInvokableReference(string fieldName, TypeKind? typeKind = null) { var template = GraphQLTemplateHelper.CreateGraphTypeTemplate(typeKind); var fieldContainer = template as IGraphTypeFieldTemplateContainer; @@ -383,10 +383,10 @@ public virtual IGraphFieldResolverMethod CreateInvokableReference(s throw new InvalidOperationException($"The provided type '{typeof(TObjectType).FriendlyName()}' does not " + $"contain a field named '{fieldName}'."); } - var method = fieldTemplate as IGraphFieldResolverMethod; + var method = fieldTemplate.CreateResolverMetaData(); if (method == null) { - throw new InvalidOperationException($"The field named '{fieldName}' on the provided type '{typeof(TObjectType).FriendlyName()}' " + $"does not represent an invokable {typeof(IGraphFieldResolverMethod)}. Operation cannot proceed."); + throw new InvalidOperationException($"The field named '{fieldName}' on the provided type '{typeof(TObjectType).FriendlyName()}' " + $"does not represent an invokable {typeof(IGraphFieldResolverMetaData)}. Operation cannot proceed."); } return method; diff --git a/src/unit-tests/graphql-aspnet-tests/Controllers/ActionResults/ActionResultTests.cs b/src/unit-tests/graphql-aspnet-tests/Controllers/ActionResults/ActionResultTests.cs index f89e8d8fb..470cd03f6 100644 --- a/src/unit-tests/graphql-aspnet-tests/Controllers/ActionResults/ActionResultTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Controllers/ActionResults/ActionResultTests.cs @@ -119,7 +119,7 @@ public async Task GraphFieldError_WithMessageAndCode_ReturnsMessageWithException [Test] public async Task InternalServerError_WithAction_AndException_FriendlyErrorMessage() { - var action = GraphQLTemplateHelper.CreateFieldTemplate(nameof(ActionableController.DoStuff)) as IGraphFieldResolverMethod; + var action = GraphQLTemplateHelper.CreateFieldTemplate(nameof(ActionableController.DoStuff)).CreateResolverMetaData(); var exception = new Exception("Fail"); var actionResult = new InternalServerErrorGraphActionResult(action, exception); @@ -167,7 +167,7 @@ public async Task ObjectRetrunedGraph_ReturnsSameItemGivenToIt() [Test] public async Task RouteNotFound_ViaGraphAction_YieldsNegativeResult() { - var action = GraphQLTemplateHelper.CreateFieldTemplate(nameof(ActionableController.DoStuff)) as IGraphFieldResolverMethod; + var action = GraphQLTemplateHelper.CreateFieldTemplate(nameof(ActionableController.DoStuff)).CreateResolverMetaData(); var exception = new Exception("fail"); var actionResult = new RouteNotFoundGraphActionResult(action, exception); diff --git a/src/unit-tests/graphql-aspnet-tests/Controllers/GraphControllerTests.cs b/src/unit-tests/graphql-aspnet-tests/Controllers/GraphControllerTests.cs index 0ecb894a2..92261bce7 100644 --- a/src/unit-tests/graphql-aspnet-tests/Controllers/GraphControllerTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Controllers/GraphControllerTests.cs @@ -36,7 +36,7 @@ public async Task MethodInvocation_EnsureInternalPropertiesAreSet() var resolutionContext = fieldContextBuilder.CreateResolutionContext(); var controller = new InvokableController(); - var result = await controller.InvokeActionAsync(fieldContextBuilder.GraphMethod.Object, resolutionContext); + var result = await controller.InvokeActionAsync(fieldContextBuilder.ResolverMetaData.Object, resolutionContext); Assert.IsNotNull(result); Assert.IsTrue(result is ObjectReturnedGraphActionResult); @@ -64,7 +64,7 @@ public async Task MethodInvocation_SyncMethodReturnsObjectNotTask() var controller = new InvokableController(); var resolutionContext = fieldContextBuilder.CreateResolutionContext(); - var result = await controller.InvokeActionAsync(fieldContextBuilder.GraphMethod.Object, resolutionContext); + var result = await controller.InvokeActionAsync(fieldContextBuilder.ResolverMetaData.Object, resolutionContext); Assert.IsNotNull(result); Assert.IsTrue(result is ObjectReturnedGraphActionResult); @@ -80,11 +80,11 @@ public async Task MethodInvocation_UnawaitableAsyncMethodFlag_ResultsInInternalE nameof(InvokableController.SyncronousActionMethod)); fieldContextBuilder.AddInputArgument("arg1", "random string"); - fieldContextBuilder.GraphMethod.Setup(x => x.IsAsyncField).Returns(true); + fieldContextBuilder.ResolverMetaData.Setup(x => x.IsAsyncField).Returns(true); var controller = new InvokableController(); var resolutionContext = fieldContextBuilder.CreateResolutionContext(); - var result = await controller.InvokeActionAsync(fieldContextBuilder.GraphMethod.Object, resolutionContext); + var result = await controller.InvokeActionAsync(fieldContextBuilder.ResolverMetaData.Object, resolutionContext); // ensure a server error reslt is generated Assert.IsNotNull(result); @@ -100,11 +100,11 @@ public async Task MethodInvocation_MissingMethodInfo_ReturnsInternalServerError( var fieldContextBuilder = tester.CreateGraphTypeFieldContextBuilder( nameof(InvokableController.SyncronousActionMethod)); fieldContextBuilder.AddInputArgument("arg1", "random string"); - fieldContextBuilder.GraphMethod.Setup(x => x.Method).Returns(null); + fieldContextBuilder.ResolverMetaData.Setup(x => x.Method).Returns(null); var controller = new InvokableController(); var resolutionContext = fieldContextBuilder.CreateResolutionContext(); - var result = await controller.InvokeActionAsync(fieldContextBuilder.GraphMethod.Object, resolutionContext); + var result = await controller.InvokeActionAsync(fieldContextBuilder.ResolverMetaData.Object, resolutionContext); // ensure a server error reslt is generated Assert.IsNotNull(result); @@ -124,7 +124,7 @@ public void MethodInvocation_UserCodeExceptionIsAllowedToThrow() var controller = new InvokableController(); var resolutionContext = fieldContextBuilder.CreateResolutionContext(); - Assert.ThrowsAsync(async () => await controller.InvokeActionAsync(fieldContextBuilder.GraphMethod.Object, resolutionContext)); + Assert.ThrowsAsync(async () => await controller.InvokeActionAsync(fieldContextBuilder.ResolverMetaData.Object, resolutionContext)); } [Test] @@ -140,7 +140,7 @@ public async Task ErrorResult() var controller = new InvokableController(); var resolutionContext = fieldContextBuilder.CreateResolutionContext(); var result = await controller.InvokeActionAsync( - fieldContextBuilder.GraphMethod.Object, + fieldContextBuilder.ResolverMetaData.Object, resolutionContext) as GraphFieldErrorActionResult; Assert.IsNotNull(result); diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/ObjectMethodResolverTests.cs b/src/unit-tests/graphql-aspnet-tests/Internal/ObjectMethodResolverTests.cs index ab6dbc054..b3a1c0b10 100644 --- a/src/unit-tests/graphql-aspnet-tests/Internal/ObjectMethodResolverTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Internal/ObjectMethodResolverTests.cs @@ -31,7 +31,7 @@ public async Task NullSourceData_FailsRequest() nameof(ResolverObject.MethodRetrieveData), null); - var resolver = new ObjectMethodGraphFieldResolver(builder.GraphMethod.Object); + var resolver = new ObjectMethodGraphFieldResolver(builder.ResolverMetaData.Object); var context = builder.CreateResolutionContext(); await resolver.ResolveAsync(context); @@ -54,7 +54,7 @@ public async Task SourceDataIsNotOfTheTemplate_FailsRequest() // source data is not of the type the resolver is for builder.AddSourceData(new TwoPropertyObject()); - var resolver = new ObjectMethodGraphFieldResolver(builder.GraphMethod.Object); + var resolver = new ObjectMethodGraphFieldResolver(builder.ResolverMetaData.Object); var context = builder.CreateResolutionContext(); await resolver.ResolveAsync(context); @@ -76,7 +76,7 @@ public async Task MethodThrowsException_FailsRequest() // source data is not of the type the resolver is for builder.AddSourceData(new ResolverObject()); - var resolver = new ObjectMethodGraphFieldResolver(builder.GraphMethod.Object); + var resolver = new ObjectMethodGraphFieldResolver(builder.ResolverMetaData.Object); var context = builder.CreateResolutionContext(); await resolver.ResolveAsync(context); @@ -104,7 +104,7 @@ public async Task KnownExecutionError_FailsRequest() // source data is not of the type the resolver is for builder.AddSourceData(new ResolverObject()); - var resolver = new ObjectMethodGraphFieldResolver(builder.GraphMethod.Object); + var resolver = new ObjectMethodGraphFieldResolver(builder.ResolverMetaData.Object); var context = builder.CreateResolutionContext(); await resolver.ResolveAsync(context); @@ -125,7 +125,7 @@ public async Task AsyncMethod_NullSourceData_FailsRequest() nameof(ResolverObject.MethodRetrieveDataAsync), null); - var resolver = new ObjectMethodGraphFieldResolver(builder.GraphMethod.Object); + var resolver = new ObjectMethodGraphFieldResolver(builder.ResolverMetaData.Object); var context = builder.CreateResolutionContext(); await resolver.ResolveAsync(context); @@ -148,7 +148,7 @@ public async Task AsyncMethod_SourceDataIsNotOfTheTemplate_FailsRequest() // source data is not of the type the resolver is for builder.AddSourceData(new TwoPropertyObject()); - var resolver = new ObjectMethodGraphFieldResolver(builder.GraphMethod.Object); + var resolver = new ObjectMethodGraphFieldResolver(builder.ResolverMetaData.Object); var context = builder.CreateResolutionContext(); await resolver.ResolveAsync(context); @@ -170,7 +170,7 @@ public async Task AsyncMethod_MethodThrowsException_FailsRequest() // source data is not of the type the resolver is for builder.AddSourceData(new ResolverObject()); - var resolver = new ObjectMethodGraphFieldResolver(builder.GraphMethod.Object); + var resolver = new ObjectMethodGraphFieldResolver(builder.ResolverMetaData.Object); var context = builder.CreateResolutionContext(); await resolver.ResolveAsync(context); @@ -198,7 +198,7 @@ public async Task AsyncMethod_KnownExecutionError_FailsRequest() // source data is not of the type the resolver is for builder.AddSourceData(new ResolverObject()); - var resolver = new ObjectMethodGraphFieldResolver(builder.GraphMethod.Object); + var resolver = new ObjectMethodGraphFieldResolver(builder.ResolverMetaData.Object); var context = builder.CreateResolutionContext(); await resolver.ResolveAsync(context); diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/ObjectPropertyResolverTests.cs b/src/unit-tests/graphql-aspnet-tests/Internal/ObjectPropertyResolverTests.cs index 9a215c93a..2661e2c76 100644 --- a/src/unit-tests/graphql-aspnet-tests/Internal/ObjectPropertyResolverTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Internal/ObjectPropertyResolverTests.cs @@ -37,7 +37,7 @@ public async Task NullSourceData_FailsRequest() fieldContextBuilder.AddSourceData(null); var resolutionContext = fieldContextBuilder.CreateResolutionContext(); - var resolver = new ObjectPropertyGraphFieldResolver(fieldContextBuilder.GraphMethod.Object); + var resolver = new ObjectPropertyGraphFieldResolver(fieldContextBuilder.ResolverMetaData.Object); await resolver.ResolveAsync(resolutionContext); Assert.AreEqual(null, resolutionContext.Result); @@ -67,8 +67,8 @@ public async Task TemplateIsInterface_SourceDataDoesImplementInterface_RendersCo var parentMock = new Mock(); parentMock.Setup(x => x.ObjectType).Returns(typeof(IResolverInterface)); - fieldContextBuilder.GraphMethod.Setup(x => x.Parent).Returns(parentMock.Object); - var resolver = new ObjectPropertyGraphFieldResolver(fieldContextBuilder.GraphMethod.Object); + fieldContextBuilder.ResolverMetaData.Setup(x => x.Parent).Returns(parentMock.Object); + var resolver = new ObjectPropertyGraphFieldResolver(fieldContextBuilder.ResolverMetaData.Object); var resolutionContext = fieldContextBuilder.CreateResolutionContext(); await resolver.ResolveAsync(resolutionContext); @@ -94,9 +94,9 @@ public async Task TemplateIsInterface_SourceDataDoesNotImplementInterface_FailsR var parentMock = new Mock(); parentMock.Setup(x => x.ObjectType).Returns(typeof(ITestInterface)); - fieldContextBuilder.GraphMethod.Setup(x => x.Parent).Returns(parentMock.Object); + fieldContextBuilder.ResolverMetaData.Setup(x => x.Parent).Returns(parentMock.Object); - var resolver = new ObjectPropertyGraphFieldResolver(fieldContextBuilder.GraphMethod.Object); + var resolver = new ObjectPropertyGraphFieldResolver(fieldContextBuilder.ResolverMetaData.Object); var resolutionContext = fieldContextBuilder.CreateResolutionContext(); await resolver.ResolveAsync(resolutionContext); @@ -118,7 +118,7 @@ public async Task SourceDataIsNotOfTheTemplate_FailsRequest() new ResolverStructB("struct")); // source data is not of the type the resolver is for - var resolver = new ObjectPropertyGraphFieldResolver(fieldContextBuilder.GraphMethod.Object); + var resolver = new ObjectPropertyGraphFieldResolver(fieldContextBuilder.ResolverMetaData.Object); var resolutionContext = fieldContextBuilder.CreateResolutionContext(); await resolver.ResolveAsync(resolutionContext); @@ -140,7 +140,7 @@ public async Task PropertyThrowsException_FailsRequest() // source data is not of the type the resolver is for fieldContextBuilder.AddSourceData(new ResolverObject()); - var resolver = new ObjectPropertyGraphFieldResolver(fieldContextBuilder.GraphMethod.Object); + var resolver = new ObjectPropertyGraphFieldResolver(fieldContextBuilder.ResolverMetaData.Object); var resolutionContext = fieldContextBuilder.CreateResolutionContext(); await resolver.ResolveAsync(resolutionContext); @@ -164,7 +164,7 @@ public async Task AsyncProperty_ValidSourceData_ReturnsData() var resolutionContext = fieldContextBuilder.CreateResolutionContext(); - var resolver = new ObjectPropertyGraphFieldResolver(fieldContextBuilder.GraphMethod.Object); + var resolver = new ObjectPropertyGraphFieldResolver(fieldContextBuilder.ResolverMetaData.Object); await resolver.ResolveAsync(resolutionContext); Assert.IsNotNull(resolutionContext.Result); @@ -185,7 +185,7 @@ public async Task AsyncProperty_ThrowsException_FailsRequest() // source data is not of the type the resolver is for fieldContextBuilder.AddSourceData(new ResolverObject()); - var resolver = new ObjectPropertyGraphFieldResolver(fieldContextBuilder.GraphMethod.Object); + var resolver = new ObjectPropertyGraphFieldResolver(fieldContextBuilder.ResolverMetaData.Object); var resolutionContext = fieldContextBuilder.CreateResolutionContext(); await resolver.ResolveAsync(resolutionContext); diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ActionMethodTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ActionMethodTemplateTests.cs index 35b4950e6..8f2c66882 100644 --- a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ActionMethodTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ActionMethodTemplateTests.cs @@ -51,14 +51,16 @@ public void ActionTemplate_Parse_BasicPropertySets() var action = this.CreateActionTemplate(nameof(OneMethodController.MethodWithBasicAttribtributes)); action.ValidateOrThrow(); + var metadata = action.CreateResolverMetaData(); + Assert.AreEqual("MethodDescription", action.Description); Assert.AreEqual(typeof(OneMethodController), action.SourceObjectType); Assert.AreEqual(typeof(OneMethodController), action.Parent.ObjectType); Assert.AreEqual(SchemaItemCollections.Query, action.Route.RootCollection); Assert.AreEqual("[query]/path0/path1", action.Route.Path); Assert.AreEqual($"{nameof(OneMethodController)}.{nameof(OneMethodController.MethodWithBasicAttribtributes)}", action.InternalFullName); - Assert.AreEqual(methodInfo.ReflectedType, ((IGraphFieldResolverMethod)action).Parent.ObjectType); - Assert.AreEqual("path0", ((IGraphFieldResolverMethod)action).Parent.Name); + Assert.AreEqual(methodInfo.ReflectedType, metadata.Parent.ObjectType); + Assert.AreEqual("path0", metadata.Parent.Name); Assert.AreEqual(methodInfo, action.Method); Assert.AreEqual(0, action.Arguments.Count); Assert.IsFalse(action.Route.IsTopLevelField); diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/DirectiveMethodTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Internal/Templating/DirectiveMethodTemplateTests.cs index d69d59639..0716cd5fe 100644 --- a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/DirectiveMethodTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Internal/Templating/DirectiveMethodTemplateTests.cs @@ -116,24 +116,5 @@ public void AsyncMethodWithNoReturnType_ThrowsException() template.ValidateOrThrow(); }); } - - [Test] - public void InterfaceAsInputParameter_ThrowsException() - { - var method = typeof(TestDirectiveMethodTemplateContainer2) - .GetMethod(nameof(TestDirectiveMethodTemplateContainer2.InterfaceAsParameter)); - - var mock = new Mock(); - mock.Setup(x => x.InternalFullName).Returns("Simple"); - var route = new SchemaItemPath(SchemaItemCollections.Directives, "Simple"); - mock.Setup(x => x.Route).Returns(route); - - Assert.Throws(() => - { - var template = new GraphDirectiveMethodTemplate(mock.Object, method); - template.Parse(); - template.ValidateOrThrow(); - }); - } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/DirectiveTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Internal/Templating/DirectiveTemplateTests.cs index b31ad82e8..07a375946 100644 --- a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/DirectiveTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Internal/Templating/DirectiveTemplateTests.cs @@ -36,7 +36,7 @@ public void Simpletemplate_AllDefaults_GeneralPropertyCheck() Assert.AreEqual(typeof(SimpleExecutableDirective), template.ObjectType); Assert.AreEqual("[directive]/SimpleExecutable", template.Route.Path); Assert.AreEqual(DirectiveLocation.FIELD, template.Locations); - Assert.IsNotNull(template.Methods.FindMethod(DirectiveLocation.FIELD)); + Assert.IsNotNull(template.Methods.FindMetaData(DirectiveLocation.FIELD)); Assert.IsFalse(template.IsRepeatable); } diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/MethodGraphFieldTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Internal/Templating/MethodGraphFieldTemplateTests.cs index 117879f44..978c1b7f9 100644 --- a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/MethodGraphFieldTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Internal/Templating/MethodGraphFieldTemplateTests.cs @@ -121,15 +121,6 @@ public void InvalidParameterName_ThrowsException() }); } - [Test] - public void InterfaceAsInputParameter_ThrowsException() - { - Assert.Throws(() => - { - this.CreateMethodTemplate(nameof(MethodClass.InterfaceAsInputParam)); - }); - } - [Test] public void AsyncMethodWithNoReturnType_ThrowsException() { diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/TypeExtensionFieldTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Internal/Templating/TypeExtensionFieldTemplateTests.cs index 0b1db6629..6f947719a 100644 --- a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/TypeExtensionFieldTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Internal/Templating/TypeExtensionFieldTemplateTests.cs @@ -54,8 +54,8 @@ public void ClassTypeExtension_PropertyCheck() Assert.AreEqual(typeof(TwoPropertyObject), template.SourceObjectType); Assert.AreEqual($"[type]/{nameof(TwoPropertyObject)}/Property3", template.Route.Path); Assert.AreEqual($"{nameof(ExtensionMethodController)}.{nameof(ExtensionMethodController.ClassTypeExtension)}", template.InternalFullName); - Assert.AreEqual(methodInfo.ReflectedType, ((IGraphFieldResolverMethod)template).Parent.ObjectType); - Assert.AreEqual("path0", ((IGraphFieldResolverMethod)template).Parent.Name); + Assert.AreEqual(methodInfo.ReflectedType, template.Parent.ObjectType); + Assert.AreEqual("path0", template.Parent.Name); Assert.AreEqual(methodInfo, template.Method); Assert.AreEqual(typeof(TwoPropertyObjectV2), template.ObjectType); Assert.AreEqual(2, template.Arguments.Count); @@ -75,9 +75,9 @@ public void ClassBatchExtension_PropertyCheck() var template = this.CreateExtensionTemplate(nameof(ExtensionMethodController.ClassBatchExtension)); Assert.AreEqual("ClassBatchExtensionDescription", template.Description); - Assert.AreEqual(methodInfo.ReflectedType, ((IGraphFieldResolverMethod)template).Parent.ObjectType); + Assert.AreEqual(methodInfo.ReflectedType, template.Parent.ObjectType); Assert.AreEqual(typeof(TwoPropertyObject), template.SourceObjectType); - Assert.AreEqual("path0", ((IGraphFieldResolverMethod)template).Parent.Name); + Assert.AreEqual("path0", template.Parent.Name); Assert.AreEqual(methodInfo, template.Method); Assert.AreEqual(typeof(int), template.ObjectType); CollectionAssert.AreEqual(new[] { MetaGraphTypes.IsList, MetaGraphTypes.IsNotNull }, template.TypeExpression.Wrappers); @@ -100,8 +100,8 @@ public void StructTypeExtension_PropertyCheck() Assert.AreEqual(typeof(TwoPropertyStruct), template.SourceObjectType); Assert.AreEqual($"[type]/{nameof(TwoPropertyStruct)}/Property3", template.Route.Path); Assert.AreEqual($"{nameof(ExtensionMethodController)}.{nameof(ExtensionMethodController.StructTypeExtension)}", template.InternalFullName); - Assert.AreEqual(methodInfo.ReflectedType, ((IGraphFieldResolverMethod)template).Parent.ObjectType); - Assert.AreEqual("path0", ((IGraphFieldResolverMethod)template).Parent.Name); + Assert.AreEqual(methodInfo.ReflectedType, template.Parent.ObjectType); + Assert.AreEqual("path0", template.Parent.Name); Assert.AreEqual(methodInfo, template.Method); Assert.AreEqual(typeof(TwoPropertyObjectV2), template.ObjectType); Assert.AreEqual(2, template.Arguments.Count); @@ -121,9 +121,9 @@ public void StructBatchExtension_PropertyCheck() var template = this.CreateExtensionTemplate(nameof(ExtensionMethodController.StructBatchTestExtension)); Assert.AreEqual("StructBatchExtensionDescription", template.Description); - Assert.AreEqual(methodInfo.ReflectedType, ((IGraphFieldResolverMethod)template).Parent.ObjectType); + Assert.AreEqual(methodInfo.ReflectedType, template.Parent.ObjectType); Assert.AreEqual(typeof(TwoPropertyStruct), template.SourceObjectType); - Assert.AreEqual("path0", ((IGraphFieldResolverMethod)template).Parent.Name); + Assert.AreEqual("path0", template.Parent.Name); Assert.AreEqual(methodInfo, template.Method); Assert.AreEqual(typeof(int), template.ObjectType); CollectionAssert.AreEqual(new[] { MetaGraphTypes.IsList, MetaGraphTypes.IsNotNull }, template.TypeExpression.Wrappers); @@ -146,8 +146,8 @@ public void InterfaceTypeExtension_PropertyCheck() Assert.AreEqual(typeof(ISinglePropertyObject), template.SourceObjectType); Assert.AreEqual($"[type]/TwoPropertyInterface/Property3", template.Route.Path); Assert.AreEqual($"{nameof(ExtensionMethodController)}.{nameof(ExtensionMethodController.InterfaceTypeExtension)}", template.InternalFullName); - Assert.AreEqual(methodInfo.ReflectedType, ((IGraphFieldResolverMethod)template).Parent.ObjectType); - Assert.AreEqual("path0", ((IGraphFieldResolverMethod)template).Parent.Name); + Assert.AreEqual(methodInfo.ReflectedType, template.Parent.ObjectType); + Assert.AreEqual("path0", template.Parent.Name); Assert.AreEqual(methodInfo, template.Method); Assert.AreEqual(typeof(TwoPropertyObjectV2), template.ObjectType); Assert.AreEqual(2, template.Arguments.Count); @@ -167,9 +167,9 @@ public void InterfaceBatchExtension_PropertyCheck() var template = this.CreateExtensionTemplate(nameof(ExtensionMethodController.InterfaceBatchTestExtension)); Assert.AreEqual("InterfaceBatchExtensionDescription", template.Description); - Assert.AreEqual(methodInfo.ReflectedType, ((IGraphFieldResolverMethod)template).Parent.ObjectType); + Assert.AreEqual(methodInfo.ReflectedType, template.Parent.ObjectType); Assert.AreEqual(typeof(ISinglePropertyObject), template.SourceObjectType); - Assert.AreEqual("path0", ((IGraphFieldResolverMethod)template).Parent.Name); + Assert.AreEqual("path0", template.Parent.Name); Assert.AreEqual(methodInfo, template.Method); Assert.AreEqual(typeof(int), template.ObjectType); CollectionAssert.AreEqual(new[] { MetaGraphTypes.IsList, MetaGraphTypes.IsNotNull }, template.TypeExpression.Wrappers); @@ -186,7 +186,7 @@ public void ValidBatchExtension_WithCustomReturnType_AndNoDeclaredTypeOnAttribut var methodInfo = typeof(ExtensionMethodController).GetMethod(nameof(ExtensionMethodController.CustomValidReturnType)); var template = this.CreateExtensionTemplate(nameof(ExtensionMethodController.CustomValidReturnType)); - Assert.AreEqual(methodInfo.ReflectedType, ((IGraphFieldResolverMethod)template).Parent.ObjectType); + Assert.AreEqual(methodInfo.ReflectedType, template.Parent.ObjectType); Assert.AreEqual(typeof(TwoPropertyObject), template.SourceObjectType); Assert.AreEqual(methodInfo, template.Method); CollectionAssert.AreEqual(new[] { MetaGraphTypes.IsList, MetaGraphTypes.IsNotNull }, template.TypeExpression.Wrappers); diff --git a/src/unit-tests/graphql-aspnet-tests/Logging/ActionMethodModelStateValidatedLogEntryTests.cs b/src/unit-tests/graphql-aspnet-tests/Logging/ActionMethodModelStateValidatedLogEntryTests.cs index 089c0e751..4fd605d09 100644 --- a/src/unit-tests/graphql-aspnet-tests/Logging/ActionMethodModelStateValidatedLogEntryTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Logging/ActionMethodModelStateValidatedLogEntryTests.cs @@ -48,7 +48,7 @@ private ExecutionArgument CreateArgument( } private void ValidateModelDictionaryToLogEntry( - IGraphFieldResolverMethod graphMethod, + IGraphFieldResolverMetaData graphMethod, IGraphFieldRequest fieldRequest, InputModelStateDictionary dictionary, ActionMethodModelStateValidatedLogEntry logEntry) @@ -127,11 +127,11 @@ public void InvalidModelItem_BuildsLogEntry() var dictionary = generator.CreateStateDictionary(argumentToTest); var entry = new ActionMethodModelStateValidatedLogEntry( - builder.GraphMethod.Object, + builder.ResolverMetaData.Object, context.Request, dictionary); - this.ValidateModelDictionaryToLogEntry(builder.GraphMethod.Object, context.Request, dictionary, entry); + this.ValidateModelDictionaryToLogEntry(builder.ResolverMetaData.Object, context.Request, dictionary, entry); } [Test] @@ -157,11 +157,11 @@ public void ValidModelItem_BuildsLogEntry() var dictionary = generator.CreateStateDictionary(argumentToTest); var entry = new ActionMethodModelStateValidatedLogEntry( - builder.GraphMethod.Object, + builder.ResolverMetaData.Object, context.Request, dictionary); - this.ValidateModelDictionaryToLogEntry(builder.GraphMethod.Object, context.Request, dictionary, entry); + this.ValidateModelDictionaryToLogEntry(builder.ResolverMetaData.Object, context.Request, dictionary, entry); } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Logging/GeneralEventLogEntryPropertyChecks.cs b/src/unit-tests/graphql-aspnet-tests/Logging/GeneralEventLogEntryPropertyChecks.cs index 7598ac508..544001ad0 100644 --- a/src/unit-tests/graphql-aspnet-tests/Logging/GeneralEventLogEntryPropertyChecks.cs +++ b/src/unit-tests/graphql-aspnet-tests/Logging/GeneralEventLogEntryPropertyChecks.cs @@ -399,7 +399,7 @@ public void ActionMethodInvocationStartedLogEntry() var server = new TestServerBuilder(TestOptions.UseCodeDeclaredNames) .AddType() .Build(); - var graphMethod = GraphQLTemplateHelper.CreateActionMethodTemplate(nameof(LogTestController.ExecuteField2)) as IGraphFieldResolverMethod; + var graphMethod = GraphQLTemplateHelper.CreateActionMethodTemplate(nameof(LogTestController.ExecuteField2)).CreateResolverMetaData(); var package = server.CreateGraphTypeFieldContextBuilder( nameof(LogTestController.ExecuteField2)); var fieldRequest = package.FieldRequest; @@ -423,7 +423,7 @@ public void ActionMethodInvocationCompletedLogEntry() .AddType() .Build(); - var graphMethod = GraphQLTemplateHelper.CreateActionMethodTemplate(nameof(LogTestController.ExecuteField2)) as IGraphFieldResolverMethod; + var graphMethod = GraphQLTemplateHelper.CreateActionMethodTemplate(nameof(LogTestController.ExecuteField2)).CreateResolverMetaData(); var package = server.CreateGraphTypeFieldContextBuilder( nameof(LogTestController.ExecuteField2)); var resolutionContext = package.CreateResolutionContext(); @@ -449,7 +449,7 @@ public void ActionMethodInvocationExceptionLogEntry() .AddType() .Build(); - var graphMethod = GraphQLTemplateHelper.CreateActionMethodTemplate(nameof(LogTestController.ExecuteField2)) as IGraphFieldResolverMethod; + var graphMethod = GraphQLTemplateHelper.CreateActionMethodTemplate(nameof(LogTestController.ExecuteField2)).CreateResolverMetaData(); var package = server.CreateGraphTypeFieldContextBuilder( nameof(LogTestController.ExecuteField2)); var fieldRequest = package.FieldRequest; @@ -482,18 +482,19 @@ public void ActionMethodUnhandledExceptionLogEntry() var package = server.CreateGraphTypeFieldContextBuilder( nameof(LogTestController.ExecuteField2)); - var graphMethod = GraphQLTemplateHelper.CreateActionMethodTemplate(nameof(LogTestController.ExecuteField2)) as IGraphFieldResolverMethod; + var template = GraphQLTemplateHelper.CreateActionMethodTemplate(nameof(LogTestController.ExecuteField2)); + var metaData = template.CreateResolverMetaData(); var fieldRequest = package.FieldRequest; var result = new object(); var exception = new Exception("inner error"); - var entry = new ActionMethodUnhandledExceptionLogEntry(graphMethod, fieldRequest, exception); + var entry = new ActionMethodUnhandledExceptionLogEntry(metaData, fieldRequest, exception); Assert.AreEqual(LogEventIds.ControllerUnhandledException.Id, entry.EventId); Assert.AreEqual(fieldRequest.Id.ToString(), entry.PipelineRequestId); - Assert.AreEqual(graphMethod.Parent.InternalFullName, entry.ControllerTypeName); - Assert.AreEqual(graphMethod.Name, entry.ActionName); + Assert.AreEqual(metaData.Parent.InternalFullName, entry.ControllerTypeName); + Assert.AreEqual(metaData.Name, entry.ActionName); Assert.IsNotNull(entry.ToString()); var exceptionEntry = entry.Exception as ExceptionLogItem; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GraphSchemaManagerTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GraphSchemaManagerTests.cs index 21ec2dc38..51d8a0311 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/GraphSchemaManagerTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GraphSchemaManagerTests.cs @@ -793,27 +793,6 @@ public void EnsureGraphType_WhenIsAGenericType_ButDeclaresACustomName_ThrowsExce Assert.Fail("No exception was thrown when one was expected."); } - [Test] - public void EnsureGraphType_WhenControllerHasInputParameterAsInterface_ThrowsException() - { - var schema = new GraphSchema() as ISchema; - schema.SetNoAlterationConfiguration(); - - var manager = new GraphSchemaManager(schema); - try - { - manager.EnsureGraphType(); - } - catch (GraphTypeDeclarationException ex) - { - var name = typeof(IPersonData).FriendlyName(); - Assert.IsTrue(ex.Message.Contains(name)); - return; - } - - Assert.Fail("No exception was thrown when one was expected."); - } - [Test] public void AttemptingToExtendATypeDirectly_AndThroughInterface_ThrowsException() { @@ -854,5 +833,18 @@ public void EnsureGraphType_WhenATypeWithNoStringsIsAdded_StringIsStillAddedBeca Assert.IsTrue(schema.KnownTypes.Contains(typeof(int))); // for the declared property Assert.IsTrue(schema.KnownTypes.Contains(typeof(string))); // for __typename } + + [Test] + public void ValidateSchemaIntegrity_WhenInterfaceArgument_OnField_ThrowsException() + { + var schema = new GraphSchema(); + var manager = new GraphSchemaManager(schema); + manager.EnsureGraphType(); + + var ex = Assert.Throws(() => + { + manager.ValidateSchemaIntegrity(); + }); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/PocoWithInterfaceArgument.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/PocoWithInterfaceArgument.cs new file mode 100644 index 000000000..3f6923695 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/PocoWithInterfaceArgument.cs @@ -0,0 +1,23 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.SchemaTestData +{ + using GraphQL.AspNet.Attributes; + using GraphQL.AspNet.Tests.Framework.Interfaces; + + public class PocoWithInterfaceArgument + { + [GraphField] + public string DoMethod(ISinglePropertyObject obj) + { + return string.Empty; + } + } +} \ No newline at end of file From 102588bc730affd36252f41962c97d9a5452e529 Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Sun, 2 Jul 2023 18:09:23 -0700 Subject: [PATCH 19/63] WIP, decoupled resolver metadata from parent template --- .../Execution/IGraphFieldResolverMetaData.cs | 33 +++++++++++---- .../Resolvers/FieldResolverMetaData.cs | 23 +++++++--- .../GraphControllerActionResolver.cs | 15 +++---- .../ObjectMethodGraphFieldResolver.cs | 2 +- .../ObjectPropertyGraphFieldResolver.cs | 42 +++++++++---------- .../ControllerActionGraphFieldTemplate.cs | 15 +------ .../GraphDirectiveMethodTemplate.cs | 6 ++- .../MethodGraphFieldTemplateBase.cs | 6 ++- .../PropertyGraphFieldTemplate.cs | 6 ++- .../ActionMethodExceptionLogEntryBase.cs | 2 +- ...ActionMethodInvocationCompletedLogEntry.cs | 4 +- .../ActionMethodInvocationStartedLogEntry.cs | 4 +- ...ActionMethodModelStateValidatedLogEntry.cs | 5 ++- ...SubscriptionEnabledFieldFieldMakerTests.cs | 3 +- .../Templating/GraphActionTemplateTests.cs | 7 ++-- .../FieldContextBuilder.cs | 32 +++++++------- .../FieldMaker_StandardFieldTests.cs | 21 +++++++--- .../Internal/ObjectPropertyResolverTests.cs | 4 +- .../Templating/ActionMethodTemplateTests.cs | 6 +-- ...nMethodModelStateValidatedLogEntryTests.cs | 2 +- .../GeneralEventLogEntryPropertyChecks.cs | 22 +++++----- 21 files changed, 146 insertions(+), 114 deletions(-) diff --git a/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverMetaData.cs b/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverMetaData.cs index 1c4003773..15ab9b139 100644 --- a/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverMetaData.cs +++ b/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverMetaData.cs @@ -26,20 +26,14 @@ namespace GraphQL.AspNet.Interfaces.Execution public interface IGraphFieldResolverMetaData { /// - /// Gets the type template from which this method was generated. + /// Gets the singular concrete type that represents the graph type returned by the resolver. /// - /// The type template that owns this method. - IGraphTypeTemplate Parent { get; } - - /// - /// Gets the singular concrete type this method is defined on. - /// - /// The objec type that defines this method. + /// The concrete object type that represents the graph type returned by the resolver. Type ObjectType { get; } /// /// Gets the type, unwrapped of any tasks, that this graph method should return upon completion. This value - /// represents the implementation return type as opposed to the expected graph type. + /// represents the implementation return type as opposed to the expected graph type represented by . /// /// The expected type of data returned by this method. Type ExpectedReturnType { get; } @@ -84,6 +78,27 @@ public interface IGraphFieldResolverMetaData /// The internal name given to this item. string InternalName { get; } + /// + /// Gets the type representing the graph type that will invoke the resolver identified by this + /// metadata object. + /// + /// The concrete type of the parent object that owns the resolver. + Type ParentObjectType { get; } + + /// + /// Gets the internal name of the parent item that ows the which generated + /// this metdata object. + /// + /// The name of the parent. + string ParentInternalName { get; } + + /// + /// Gets the full internal name of the parent item that ows the which generated + /// this metdata object. + /// + /// The name of the parent. + string ParentInternalFullName { get; } + /// /// Gets the unique route that points to the field in the object graph. /// diff --git a/src/graphql-aspnet/Internal/Resolvers/FieldResolverMetaData.cs b/src/graphql-aspnet/Internal/Resolvers/FieldResolverMetaData.cs index 58ed2dc97..a2efe02af 100644 --- a/src/graphql-aspnet/Internal/Resolvers/FieldResolverMetaData.cs +++ b/src/graphql-aspnet/Internal/Resolvers/FieldResolverMetaData.cs @@ -25,7 +25,6 @@ namespace GraphQL.AspNet.Internal.Resolvers internal class FieldResolverMetaData : IGraphFieldResolverMetaData { public FieldResolverMetaData( - IGraphTypeTemplate parent, MethodInfo method, IEnumerable parameters, IEnumerable arguments, @@ -35,11 +34,13 @@ public FieldResolverMetaData( bool isAsyncField, string name, string internalName, - string internalFullName) + string internalFullName, + Type parentObjectType, + string parentInternalName, + string parentInternalFullName) { this.Method = Validation.ThrowIfNullOrReturn(method, nameof(method)); this.Route = Validation.ThrowIfNullOrReturn(route, nameof(route)); - this.Parent = Validation.ThrowIfNullOrReturn(parent, nameof(parent)); this.ObjectType = Validation.ThrowIfNullOrReturn(objectType, nameof(objectType)); this.ExpectedReturnType = Validation.ThrowIfNullOrReturn(expectedReturnType, nameof(expectedReturnType)); @@ -51,6 +52,10 @@ public FieldResolverMetaData( this.Name = Validation.ThrowIfNullWhiteSpaceOrReturn(name, nameof(name)); this.InternalName = Validation.ThrowIfNullWhiteSpaceOrReturn(internalName, nameof(internalName)); this.InternalFullName = Validation.ThrowIfNullWhiteSpaceOrReturn(internalFullName, nameof(internalFullName)); + + this.ParentObjectType = Validation.ThrowIfNullOrReturn(parentObjectType, nameof(parentObjectType)); + this.ParentInternalName = Validation.ThrowIfNullWhiteSpaceOrReturn(parentInternalName, nameof(parentInternalName)); + this.ParentInternalFullName = Validation.ThrowIfNullWhiteSpaceOrReturn(parentInternalFullName, nameof(parentInternalFullName)); } /// @@ -71,9 +76,6 @@ public FieldResolverMetaData( /// public string InternalName { get; } - /// - public IGraphTypeTemplate Parent { get; } - /// public Type ObjectType { get; } @@ -85,5 +87,14 @@ public FieldResolverMetaData( /// public IReadOnlyList Arguments { get; } + + /// + public string ParentInternalName { get; } + + /// + public string ParentInternalFullName { get; } + + /// + public Type ParentObjectType { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Internal/Resolvers/GraphControllerActionResolver.cs b/src/graphql-aspnet/Internal/Resolvers/GraphControllerActionResolver.cs index b0b52703c..df4140fa4 100644 --- a/src/graphql-aspnet/Internal/Resolvers/GraphControllerActionResolver.cs +++ b/src/graphql-aspnet/Internal/Resolvers/GraphControllerActionResolver.cs @@ -26,15 +26,16 @@ namespace GraphQL.AspNet.Internal.Resolvers /// internal class GraphControllerActionResolver : GraphControllerActionResolverBase, IGraphFieldResolver { - private readonly IGraphFieldResolverMetaData _actionMethod; + private readonly IGraphFieldResolverMetaData _actionResolverMetaData; /// /// Initializes a new instance of the class. /// - /// The action method that this resolver will invoke. - public GraphControllerActionResolver(IGraphFieldResolverMetaData actionMethod) + /// The metadata describing an action + /// method that this resolver will invoke. + public GraphControllerActionResolver(IGraphFieldResolverMetaData actionResolverMetadata) { - _actionMethod = Validation.ThrowIfNullOrReturn(actionMethod, nameof(actionMethod)); + _actionResolverMetaData = Validation.ThrowIfNullOrReturn(actionResolverMetadata, nameof(actionResolverMetadata)); } /// @@ -47,7 +48,7 @@ public async Task ResolveAsync(FieldResolutionContext context, CancellationToken // create a scoped controller instance for this invocation var controller = context .ServiceProvider? - .GetService(_actionMethod.Parent.ObjectType) as GraphController; + .GetService(_actionResolverMetaData.ParentObjectType) as GraphController; if (controller == null) { @@ -58,7 +59,7 @@ public async Task ResolveAsync(FieldResolutionContext context, CancellationToken else { // invoke the right action method and set a result. - var task = controller.InvokeActionAsync(_actionMethod, context); + var task = controller.InvokeActionAsync(_actionResolverMetaData, context); var returnedItem = await task.ConfigureAwait(false); result = this.EnsureGraphActionResult(returnedItem); } @@ -75,6 +76,6 @@ public async Task ResolveAsync(FieldResolutionContext context, CancellationToken } /// - public Type ObjectType => _actionMethod.ObjectType; + public Type ObjectType => _actionResolverMetaData.ObjectType; } } \ No newline at end of file diff --git a/src/graphql-aspnet/Internal/Resolvers/ObjectMethodGraphFieldResolver.cs b/src/graphql-aspnet/Internal/Resolvers/ObjectMethodGraphFieldResolver.cs index 56eb2f2c5..6564237d9 100644 --- a/src/graphql-aspnet/Internal/Resolvers/ObjectMethodGraphFieldResolver.cs +++ b/src/graphql-aspnet/Internal/Resolvers/ObjectMethodGraphFieldResolver.cs @@ -64,7 +64,7 @@ public virtual async Task ResolveAsync(FieldResolutionContext context, Cancellat context.Request.Origin, new GraphExecutionException( $"The method '{_graphMethod.InternalFullName}' expected source data of type " + - $"'{_graphMethod.Parent.ObjectType.FriendlyName()}' but received '{sourceData.GetType().FriendlyName()}' " + + $"'{_graphMethod.ParentObjectType.FriendlyName()}' but received '{sourceData.GetType().FriendlyName()}' " + "which is not compatible.")); return; diff --git a/src/graphql-aspnet/Internal/Resolvers/ObjectPropertyGraphFieldResolver.cs b/src/graphql-aspnet/Internal/Resolvers/ObjectPropertyGraphFieldResolver.cs index f042c1874..cfcbc2aca 100644 --- a/src/graphql-aspnet/Internal/Resolvers/ObjectPropertyGraphFieldResolver.cs +++ b/src/graphql-aspnet/Internal/Resolvers/ObjectPropertyGraphFieldResolver.cs @@ -27,15 +27,15 @@ namespace GraphQL.AspNet.Internal.Resolvers [DebuggerDisplay("Prop Resolver: {_graphMethod.Name}")] internal class ObjectPropertyGraphFieldResolver : IGraphFieldResolver { - private readonly IGraphFieldResolverMetaData _graphMethod; + private readonly IGraphFieldResolverMetaData _resolverMetadata; /// /// Initializes a new instance of the class. /// - /// A resolver method that points to a .NET property getter. - public ObjectPropertyGraphFieldResolver(IGraphFieldResolverMetaData propertyGetMethod) + /// A set of metadata items that points to a .NET property getter. + public ObjectPropertyGraphFieldResolver(IGraphFieldResolverMetaData resolverMetaData) { - _graphMethod = Validation.ThrowIfNullOrReturn(propertyGetMethod, nameof(propertyGetMethod)); + _resolverMetadata = Validation.ThrowIfNullOrReturn(resolverMetaData, nameof(resolverMetaData)); } /// @@ -46,7 +46,7 @@ public async Task ResolveAsync(FieldResolutionContext context, CancellationToken { context.Messages.Critical( "No source data was provided to the field resolver " + - $"for '{_graphMethod.Name}'. Unable to complete the request.", + $"for '{_resolverMetadata.Name}'. Unable to complete the request.", Constants.ErrorCodes.INVALID_OBJECT, context.Request.Origin); @@ -56,33 +56,33 @@ public async Task ResolveAsync(FieldResolutionContext context, CancellationToken // valdidate the incoming source data to ensure its process-able by this property // resolver. If the data is being resolved through an interface or object reference // ensure the provided source data can be converted otherwise ensure the types match exactly. - if (_graphMethod.Parent.ObjectType.IsInterface || _graphMethod.Parent.ObjectType.IsClass) + if (_resolverMetadata.ParentObjectType.IsInterface || _resolverMetadata.ParentObjectType.IsClass) { - if (!Validation.IsCastable(sourceData.GetType(), _graphMethod.Parent.ObjectType)) + if (!Validation.IsCastable(sourceData.GetType(), _resolverMetadata.ParentObjectType)) { context.Messages.Critical( "The source data provided to the field resolver " + - $"for '{_graphMethod.Route.Path}' could not be coerced into the expected source graph type. See exception for details.", + $"for '{_resolverMetadata.Route.Path}' could not be coerced into the expected source graph type. See exception for details.", Constants.ErrorCodes.INVALID_OBJECT, context.Request.Origin, new GraphExecutionException( - $"The property '{_graphMethod.InternalFullName}' expected source data that implements the interface " + - $"'{_graphMethod.Parent.ObjectType.FriendlyName()}' but received '{sourceData.GetType().FriendlyName()}' which " + + $"The property '{_resolverMetadata.InternalFullName}' expected source data that implements the interface " + + $"'{_resolverMetadata.ParentObjectType.FriendlyName()}' but received '{sourceData.GetType().FriendlyName()}' which " + "is not compatible.")); return; } } - else if (sourceData.GetType() != _graphMethod.Parent.ObjectType) + else if (sourceData.GetType() != _resolverMetadata.ParentObjectType) { context.Messages.Critical( "The source data provided to the field resolver " + - $"for '{_graphMethod.Route.Path}' could not be coerced into the expected source graph type. See exception for details.", + $"for '{_resolverMetadata.Route.Path}' could not be coerced into the expected source graph type. See exception for details.", Constants.ErrorCodes.INVALID_OBJECT, context.Request.Origin, new GraphExecutionException( - $"The property '{_graphMethod.InternalFullName}' expected source data of type " + - $"'{_graphMethod.Parent.ObjectType.FriendlyName()}' but received '{sourceData.GetType().FriendlyName()}' " + + $"The property '{_resolverMetadata.InternalFullName}' expected source data of type " + + $"'{_resolverMetadata.ParentObjectType.FriendlyName()}' but received '{sourceData.GetType().FriendlyName()}' " + "which is not compatible.")); return; @@ -90,9 +90,9 @@ public async Task ResolveAsync(FieldResolutionContext context, CancellationToken try { - var invoker = InstanceFactory.CreateInstanceMethodInvoker(_graphMethod.Method); + var invoker = InstanceFactory.CreateInstanceMethodInvoker(_resolverMetadata.Method); var invokeReturn = invoker(ref sourceData, new object[0]); - if (_graphMethod.IsAsyncField) + if (_resolverMetadata.IsAsyncField) { if (invokeReturn is Task task) { @@ -100,17 +100,17 @@ public async Task ResolveAsync(FieldResolutionContext context, CancellationToken if (task.IsFaulted) throw task.UnwrapException(); - invokeReturn = task.ResultOfTypeOrNull(_graphMethod.ExpectedReturnType); + invokeReturn = task.ResultOfTypeOrNull(_resolverMetadata.ExpectedReturnType); } else { context.Messages.Critical( "The source data provided to the field resolver " + - $"for '{_graphMethod.Route.Path}' could not be coerced into the expected source graph type. See exception for details.", + $"for '{_resolverMetadata.Route.Path}' could not be coerced into the expected source graph type. See exception for details.", Constants.ErrorCodes.INVALID_OBJECT, context.Request.Origin, new GraphExecutionException( - $"The method '{_graphMethod.Route.Path}' is defined " + + $"The method '{_resolverMetadata.Route.Path}' is defined " + $"as asyncronous but it did not return a {typeof(Task)}.")); invokeReturn = null; } @@ -128,7 +128,7 @@ public async Task ResolveAsync(FieldResolutionContext context, CancellationToken catch (Exception ex) { context.Messages.Critical( - $"An unknown error occured atttempting to resolve the field '{_graphMethod.Route.Path}'. See exception for details.", + $"An unknown error occured atttempting to resolve the field '{_resolverMetadata.Route.Path}'. See exception for details.", Constants.ErrorCodes.UNHANDLED_EXCEPTION, context.Request.Origin, ex); @@ -136,6 +136,6 @@ public async Task ResolveAsync(FieldResolutionContext context, CancellationToken } /// - public Type ObjectType => _graphMethod.ObjectType; + public Type ObjectType => _resolverMetadata.ObjectType; } } \ No newline at end of file diff --git a/src/graphql-aspnet/Internal/TypeTemplates/ControllerActionGraphFieldTemplate.cs b/src/graphql-aspnet/Internal/TypeTemplates/ControllerActionGraphFieldTemplate.cs index b09003ce6..17ba2ff3d 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/ControllerActionGraphFieldTemplate.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/ControllerActionGraphFieldTemplate.cs @@ -100,20 +100,7 @@ public override void ValidateOrThrow() /// IGraphFieldResolver. public override IGraphFieldResolver CreateResolver() { - var metaData = new FieldResolverMetaData( - this.Parent, - this.Method, - this.Parameters, - this.Arguments, - this.ExpectedReturnType, - this.ObjectType, - this.Route, - this.IsAsyncField, - this.Name, - this.InternalName, - this.InternalFullName); - - return new GraphControllerActionResolver(metaData); + return new GraphControllerActionResolver(this.CreateResolverMetaData()); } /// diff --git a/src/graphql-aspnet/Internal/TypeTemplates/GraphDirectiveMethodTemplate.cs b/src/graphql-aspnet/Internal/TypeTemplates/GraphDirectiveMethodTemplate.cs index ba8277765..d7fc824de 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/GraphDirectiveMethodTemplate.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/GraphDirectiveMethodTemplate.cs @@ -196,7 +196,6 @@ public IEnumerable RetrieveRequiredTypes() internal IGraphFieldResolverMetaData CreateResolverMetaData() { return new FieldResolverMetaData( - this.Parent, this.Method, this.Parameters, this.Arguments, @@ -206,7 +205,10 @@ internal IGraphFieldResolverMetaData CreateResolverMetaData() this.IsAsyncField, this.Name, this.InternalName, - this.InternalFullName); + this.InternalFullName, + this.Parent.ObjectType, + this.Parent.InternalName, + this.Parent.InternalFullName); } /// diff --git a/src/graphql-aspnet/Internal/TypeTemplates/MethodGraphFieldTemplateBase.cs b/src/graphql-aspnet/Internal/TypeTemplates/MethodGraphFieldTemplateBase.cs index 93bbddfd7..674035c1b 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/MethodGraphFieldTemplateBase.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/MethodGraphFieldTemplateBase.cs @@ -109,7 +109,6 @@ public override IGraphFieldResolver CreateResolver() public override IGraphFieldResolverMetaData CreateResolverMetaData() { return new FieldResolverMetaData( - this.Parent, this.Method, this.Parameters, this.Arguments, @@ -119,7 +118,10 @@ public override IGraphFieldResolverMetaData CreateResolverMetaData() this.IsAsyncField, this.Name, this.InternalName, - this.InternalFullName); + this.InternalFullName, + this.Parent.ObjectType, + this.Parent.InternalName, + this.Parent.InternalFullName); } /// diff --git a/src/graphql-aspnet/Internal/TypeTemplates/PropertyGraphFieldTemplate.cs b/src/graphql-aspnet/Internal/TypeTemplates/PropertyGraphFieldTemplate.cs index 24f57bebd..6c8eac890 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/PropertyGraphFieldTemplate.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/PropertyGraphFieldTemplate.cs @@ -117,7 +117,6 @@ public override IGraphFieldResolver CreateResolver() public override IGraphFieldResolverMetaData CreateResolverMetaData() { return new FieldResolverMetaData( - this.Parent, this.Method, this.Parameters, this.Arguments, @@ -127,7 +126,10 @@ public override IGraphFieldResolverMetaData CreateResolverMetaData() this.IsAsyncField, this.Name, this.InternalName, - this.InternalFullName); + this.InternalFullName, + this.Parent.ObjectType, + this.Parent.InternalName, + this.Parent.InternalFullName); } /// diff --git a/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodExceptionLogEntryBase.cs b/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodExceptionLogEntryBase.cs index a39fd3202..f0098dc9f 100644 --- a/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodExceptionLogEntryBase.cs +++ b/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodExceptionLogEntryBase.cs @@ -36,7 +36,7 @@ protected ActionMethodExceptionLogEntryBase( : base(eventId) { this.PipelineRequestId = request?.Id.ToString(); - this.ControllerTypeName = method?.Parent?.InternalFullName; + this.ControllerTypeName = method?.ParentInternalFullName; this.ActionName = method?.Name; this.Exception = new ExceptionLogItem(exception); } diff --git a/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodInvocationCompletedLogEntry.cs b/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodInvocationCompletedLogEntry.cs index 3543c7041..0833f7c5f 100644 --- a/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodInvocationCompletedLogEntry.cs +++ b/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodInvocationCompletedLogEntry.cs @@ -31,11 +31,11 @@ public ActionMethodInvocationCompletedLogEntry(IGraphFieldResolverMetaData metho : base(LogEventIds.ControllerInvocationCompleted) { this.PipelineRequestId = request?.Id.ToString(); - this.ControllerName = method?.Parent?.InternalFullName; + this.ControllerName = method?.ParentInternalFullName; this.ActionName = method?.InternalName; this.FieldPath = method?.Route?.Path; this.ResultTypeName = result?.GetType().FriendlyName(true); - _shortControllerName = method?.Parent?.InternalName; + _shortControllerName = method?.ParentInternalName; } /// diff --git a/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodInvocationStartedLogEntry.cs b/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodInvocationStartedLogEntry.cs index 152c9d2e0..d87fbf09a 100644 --- a/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodInvocationStartedLogEntry.cs +++ b/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodInvocationStartedLogEntry.cs @@ -29,12 +29,12 @@ public ActionMethodInvocationStartedLogEntry(IGraphFieldResolverMetaData method, : base(LogEventIds.ControllerInvocationStarted) { this.PipelineRequestId = request?.Id.ToString(); - this.ControllerName = method?.Parent?.InternalFullName; + this.ControllerName = method?.ParentInternalFullName; this.ActionName = method?.Name; this.FieldPath = method?.Route?.Path; this.SourceObjectType = method?.ObjectType?.ToString(); this.IsAsync = method?.IsAsyncField; - _shortControllerName = method?.Parent?.InternalName; + _shortControllerName = method?.ParentInternalName; } /// diff --git a/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodModelStateValidatedLogEntry.cs b/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodModelStateValidatedLogEntry.cs index 676b4b855..151410522 100644 --- a/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodModelStateValidatedLogEntry.cs +++ b/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodModelStateValidatedLogEntry.cs @@ -38,11 +38,12 @@ public ActionMethodModelStateValidatedLogEntry( : base(LogEventIds.ControllerModelValidated) { this.PipelineRequestId = request?.Id.ToString(); - this.ControllerName = method?.Parent?.ObjectType?.FriendlyName(true) ?? method?.Parent?.Name; + this.ControllerName = method?.ParentInternalFullName; this.ActionName = method?.Name; this.FieldPath = method?.Route?.Path; this.ModelDataIsValid = modelState?.IsValid; - _shortControllerName = method?.Parent?.ObjectType?.FriendlyName() ?? method?.Parent?.Name; + + _shortControllerName = method?.ParentInternalName; this.ModelItems = null; if (modelState?.Values != null && modelState.Values.Any()) { diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/SubscriptionEnabledFieldFieldMakerTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/SubscriptionEnabledFieldFieldMakerTests.cs index 922e1ed9f..b60996cfa 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/SubscriptionEnabledFieldFieldMakerTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/SubscriptionEnabledFieldFieldMakerTests.cs @@ -26,7 +26,8 @@ public class SubscriptionEnabledFieldFieldMakerTests public void SubscriptionActionField_TransfersDirectives() { var mockController = new Mock(); - mockController.Setup(x => x.InternalFullName).Returns(typeof(SubscriptionTestController).Name); + mockController.Setup(x => x.InternalFullName).Returns(typeof(SubscriptionTestController).FullName); + mockController.Setup(x => x.InternalName).Returns(typeof(SubscriptionTestController).Name); mockController.Setup(x => x.Route).Returns(new SchemaItemPath("path0")); mockController.Setup(x => x.Name).Returns("path0"); mockController.Setup(x => x.ObjectType).Returns(typeof(SubscriptionTestController)); diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/GraphActionTemplateTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/GraphActionTemplateTests.cs index c930c93a4..1047d9ca0 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/GraphActionTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/GraphActionTemplateTests.cs @@ -30,7 +30,8 @@ private SubscriptionControllerActionGraphFieldTemplate CreateActionTemplate(); - mockController.Setup(x => x.InternalFullName).Returns(typeof(TControllerType).Name); + mockController.Setup(x => x.InternalFullName).Returns(typeof(TControllerType).FullName); + mockController.Setup(x => x.InternalName).Returns(typeof(TControllerType).Name); mockController.Setup(x => x.Route).Returns(new SchemaItemPath("path0")); mockController.Setup(x => x.Name).Returns("path0"); mockController.Setup(x => x.ObjectType).Returns(typeof(TControllerType)); @@ -55,8 +56,8 @@ public void ActionTemplate_Parse_BasicPropertySets() Assert.AreEqual(typeof(OneMethodSubscriptionController), action.Parent.ObjectType); Assert.AreEqual(SchemaItemCollections.Subscription, action.Route.RootCollection); Assert.AreEqual("[subscription]/path0/path1", action.Route.Path); - Assert.AreEqual($"{nameof(OneMethodSubscriptionController)}.{nameof(OneMethodSubscriptionController.SingleMethod)}", action.InternalFullName); - Assert.AreEqual(methodInfo.ReflectedType, metaData.Parent.ObjectType); + Assert.AreEqual($"{action.Parent.InternalFullName}.{nameof(OneMethodSubscriptionController.SingleMethod)}", action.InternalFullName); + Assert.AreEqual(methodInfo.ReflectedType, metaData.ParentObjectType); Assert.AreEqual("path0", action.Parent.Name); Assert.AreEqual(methodInfo, action.Method); Assert.AreEqual(1, action.Arguments.Count); diff --git a/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/FieldContextBuilder.cs b/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/FieldContextBuilder.cs index 7fa2a2b2c..211a6667d 100644 --- a/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/FieldContextBuilder.cs +++ b/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/FieldContextBuilder.cs @@ -51,13 +51,13 @@ public class FieldContextBuilder /// The user security context. /// The graph field. /// The schema. - /// The metadata describing the method/functon to be invoked by a resolver. + /// The metadata describing the method/functon to be invoked by a resolver. public FieldContextBuilder( IServiceProvider serviceProvider, IUserSecurityContext userSecurityContext, IGraphField graphField, ISchema schema, - IGraphFieldResolverMetaData graphMethod) + IGraphFieldResolverMetaData metaData) { _schema = Validation.ThrowIfNullOrReturn(schema, nameof(schema)); _graphField = Validation.ThrowIfNullOrReturn(graphField, nameof(graphField)); @@ -69,10 +69,10 @@ public FieldContextBuilder( Type expectedInputType = null; - if (!Validation.IsCastable(graphMethod.Parent.ObjectType) - && !Validation.IsCastable(graphMethod.Parent.ObjectType)) + if (!Validation.IsCastable(metaData.ParentObjectType) + && !Validation.IsCastable(metaData.ParentObjectType)) { - expectedInputType = graphMethod.Parent.ObjectType; + expectedInputType = metaData.ObjectType; } _mockFieldDocumentPart = new Mock(); @@ -100,16 +100,18 @@ public FieldContextBuilder( _mockRequest.Setup(x => x.InvocationContext).Returns(_mockInvocationContext.Object); this.ResolverMetaData = new Mock(); - this.ResolverMetaData.Setup(x => x.Parent).Returns(graphMethod.Parent); - this.ResolverMetaData.Setup(x => x.ObjectType).Returns(graphMethod.ObjectType); - this.ResolverMetaData.Setup(x => x.ExpectedReturnType).Returns(graphMethod.ExpectedReturnType); - this.ResolverMetaData.Setup(x => x.Method).Returns(graphMethod.Method); - this.ResolverMetaData.Setup(x => x.IsAsyncField).Returns(graphMethod.IsAsyncField); - this.ResolverMetaData.Setup(x => x.Name).Returns(graphMethod.Name); - this.ResolverMetaData.Setup(x => x.InternalFullName).Returns(graphMethod.InternalFullName); - this.ResolverMetaData.Setup(x => x.InternalName).Returns(graphMethod.InternalName); - this.ResolverMetaData.Setup(x => x.Route).Returns(graphMethod.Route); - this.ResolverMetaData.Setup(x => x.Arguments).Returns(graphMethod.Arguments); + this.ResolverMetaData.Setup(x => x.ParentInternalFullName).Returns(metaData.ParentInternalFullName); + this.ResolverMetaData.Setup(x => x.ParentInternalName).Returns(metaData.ParentInternalName); + this.ResolverMetaData.Setup(x => x.ParentObjectType).Returns(metaData.ParentObjectType); + this.ResolverMetaData.Setup(x => x.ObjectType).Returns(metaData.ObjectType); + this.ResolverMetaData.Setup(x => x.ExpectedReturnType).Returns(metaData.ExpectedReturnType); + this.ResolverMetaData.Setup(x => x.Method).Returns(metaData.Method); + this.ResolverMetaData.Setup(x => x.IsAsyncField).Returns(metaData.IsAsyncField); + this.ResolverMetaData.Setup(x => x.Name).Returns(metaData.Name); + this.ResolverMetaData.Setup(x => x.InternalFullName).Returns(metaData.InternalFullName); + this.ResolverMetaData.Setup(x => x.InternalName).Returns(metaData.InternalName); + this.ResolverMetaData.Setup(x => x.Route).Returns(metaData.Route); + this.ResolverMetaData.Setup(x => x.Arguments).Returns(metaData.Arguments); } /// diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/FieldMaker_StandardFieldTests.cs b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/FieldMaker_StandardFieldTests.cs index 58e5c19ad..5e4db2787 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/FieldMaker_StandardFieldTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/FieldMaker_StandardFieldTests.cs @@ -123,7 +123,9 @@ public void PropertyGraphField_DefaultValuesCheck() var obj = new Mock(); obj.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/Item0")); - obj.Setup(x => x.InternalFullName).Returns("Item0"); + obj.Setup(x => x.InternalFullName).Returns("LongItem0"); + obj.Setup(x => x.InternalName).Returns("Item0"); + obj.Setup(x => x.ObjectType).Returns(typeof(SimplePropertyObject)); var parent = obj.Object; var propInfo = typeof(SimplePropertyObject).GetProperty(nameof(SimplePropertyObject.Name)); @@ -140,10 +142,11 @@ public void PropertyGraphField_DefaultValuesCheck() [Test] public void PropertyGraphField_GraphName_OverridesDefaultName() { - var server = new TestServerBuilder().Build(); var obj = new Mock(); obj.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/Item0")); - obj.Setup(x => x.InternalFullName).Returns("Item0"); + obj.Setup(x => x.InternalFullName).Returns("LongItem0"); + obj.Setup(x => x.InternalName).Returns("Item0"); + obj.Setup(x => x.ObjectType).Returns(typeof(SimplePropertyObject)); var parent = obj.Object; var propInfo = typeof(SimplePropertyObject).GetProperty(nameof(SimplePropertyObject.Age)); @@ -166,7 +169,9 @@ public void PropertyGraphField_DirectivesAreAppliedToCreatedField() var server = new TestServerBuilder().Build(); var obj = new Mock(); obj.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/Item0")); - obj.Setup(x => x.InternalFullName).Returns("Item0"); + obj.Setup(x => x.InternalFullName).Returns("LongItem0"); + obj.Setup(x => x.InternalName).Returns("Item0"); + obj.Setup(x => x.ObjectType).Returns(typeof(SimplePropertyObject)); var parent = obj.Object; var propInfo = typeof(ObjectDirectiveTestItem).GetProperty(nameof(ObjectDirectiveTestItem.Prop1)); @@ -190,7 +195,9 @@ public void MethodGraphField_DirectivesAreAppliedToCreatedField() var server = new TestServerBuilder().Build(); var obj = new Mock(); obj.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/Item0")); - obj.Setup(x => x.InternalFullName).Returns("Item0"); + obj.Setup(x => x.InternalFullName).Returns("LongItem0"); + obj.Setup(x => x.InternalName).Returns("Item0"); + obj.Setup(x => x.ObjectType).Returns(typeof(ObjectDirectiveTestItem)); var parent = obj.Object; var methodInfo = typeof(ObjectDirectiveTestItem).GetMethod(nameof(ObjectDirectiveTestItem.Method1)); @@ -214,7 +221,9 @@ public void Arguments_DirectivesAreApplied() var server = new TestServerBuilder().Build(); var obj = new Mock(); obj.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/Item0")); - obj.Setup(x => x.InternalFullName).Returns("Item0"); + obj.Setup(x => x.InternalFullName).Returns("LongItem0"); + obj.Setup(x => x.InternalName).Returns("Item0"); + obj.Setup(x => x.ObjectType).Returns(typeof(ObjectDirectiveTestItem)); var parent = obj.Object; var methodInfo = typeof(ObjectDirectiveTestItem).GetMethod(nameof(ObjectDirectiveTestItem.MethodWithArgDirectives)); diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/ObjectPropertyResolverTests.cs b/src/unit-tests/graphql-aspnet-tests/Internal/ObjectPropertyResolverTests.cs index 2661e2c76..e8c73f5c1 100644 --- a/src/unit-tests/graphql-aspnet-tests/Internal/ObjectPropertyResolverTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Internal/ObjectPropertyResolverTests.cs @@ -67,7 +67,7 @@ public async Task TemplateIsInterface_SourceDataDoesImplementInterface_RendersCo var parentMock = new Mock(); parentMock.Setup(x => x.ObjectType).Returns(typeof(IResolverInterface)); - fieldContextBuilder.ResolverMetaData.Setup(x => x.Parent).Returns(parentMock.Object); + fieldContextBuilder.ResolverMetaData.Setup(x => x.ParentObjectType).Returns(parentMock.Object.ObjectType); var resolver = new ObjectPropertyGraphFieldResolver(fieldContextBuilder.ResolverMetaData.Object); var resolutionContext = fieldContextBuilder.CreateResolutionContext(); @@ -94,7 +94,7 @@ public async Task TemplateIsInterface_SourceDataDoesNotImplementInterface_FailsR var parentMock = new Mock(); parentMock.Setup(x => x.ObjectType).Returns(typeof(ITestInterface)); - fieldContextBuilder.ResolverMetaData.Setup(x => x.Parent).Returns(parentMock.Object); + fieldContextBuilder.ResolverMetaData.Setup(x => x.ParentObjectType).Returns(parentMock.Object.ObjectType); var resolver = new ObjectPropertyGraphFieldResolver(fieldContextBuilder.ResolverMetaData.Object); diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ActionMethodTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ActionMethodTemplateTests.cs index 8f2c66882..413790786 100644 --- a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ActionMethodTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ActionMethodTemplateTests.cs @@ -51,16 +51,14 @@ public void ActionTemplate_Parse_BasicPropertySets() var action = this.CreateActionTemplate(nameof(OneMethodController.MethodWithBasicAttribtributes)); action.ValidateOrThrow(); - var metadata = action.CreateResolverMetaData(); - Assert.AreEqual("MethodDescription", action.Description); Assert.AreEqual(typeof(OneMethodController), action.SourceObjectType); Assert.AreEqual(typeof(OneMethodController), action.Parent.ObjectType); Assert.AreEqual(SchemaItemCollections.Query, action.Route.RootCollection); Assert.AreEqual("[query]/path0/path1", action.Route.Path); Assert.AreEqual($"{nameof(OneMethodController)}.{nameof(OneMethodController.MethodWithBasicAttribtributes)}", action.InternalFullName); - Assert.AreEqual(methodInfo.ReflectedType, metadata.Parent.ObjectType); - Assert.AreEqual("path0", metadata.Parent.Name); + Assert.AreEqual(methodInfo.ReflectedType, action.Parent.ObjectType); + Assert.AreEqual("path0", action.Parent.Name); Assert.AreEqual(methodInfo, action.Method); Assert.AreEqual(0, action.Arguments.Count); Assert.IsFalse(action.Route.IsTopLevelField); diff --git a/src/unit-tests/graphql-aspnet-tests/Logging/ActionMethodModelStateValidatedLogEntryTests.cs b/src/unit-tests/graphql-aspnet-tests/Logging/ActionMethodModelStateValidatedLogEntryTests.cs index 4fd605d09..aa022046c 100644 --- a/src/unit-tests/graphql-aspnet-tests/Logging/ActionMethodModelStateValidatedLogEntryTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Logging/ActionMethodModelStateValidatedLogEntryTests.cs @@ -54,7 +54,7 @@ private void ValidateModelDictionaryToLogEntry( ActionMethodModelStateValidatedLogEntry logEntry) { Assert.AreEqual(fieldRequest.Id.ToString(), logEntry.PipelineRequestId); - Assert.AreEqual(graphMethod.Parent.ObjectType.FriendlyName(true), logEntry.ControllerName); + Assert.AreEqual(graphMethod.ParentInternalFullName, logEntry.ControllerName); Assert.AreEqual(graphMethod.Name, logEntry.ActionName); Assert.AreEqual(dictionary.IsValid, logEntry.ModelDataIsValid); diff --git a/src/unit-tests/graphql-aspnet-tests/Logging/GeneralEventLogEntryPropertyChecks.cs b/src/unit-tests/graphql-aspnet-tests/Logging/GeneralEventLogEntryPropertyChecks.cs index 544001ad0..fcb499cac 100644 --- a/src/unit-tests/graphql-aspnet-tests/Logging/GeneralEventLogEntryPropertyChecks.cs +++ b/src/unit-tests/graphql-aspnet-tests/Logging/GeneralEventLogEntryPropertyChecks.cs @@ -408,7 +408,7 @@ public void ActionMethodInvocationStartedLogEntry() Assert.AreEqual(LogEventIds.ControllerInvocationStarted.Id, entry.EventId); Assert.AreEqual(fieldRequest.Id.ToString(), entry.PipelineRequestId); - Assert.AreEqual(graphMethod.Parent.InternalFullName, entry.ControllerName); + Assert.AreEqual(graphMethod.ParentInternalFullName, entry.ControllerName); Assert.AreEqual(graphMethod.Name, entry.ActionName); Assert.AreEqual(graphMethod.Route.Path, entry.FieldPath); Assert.AreEqual(graphMethod.ObjectType.ToString(), entry.SourceObjectType); @@ -423,7 +423,7 @@ public void ActionMethodInvocationCompletedLogEntry() .AddType() .Build(); - var graphMethod = GraphQLTemplateHelper.CreateActionMethodTemplate(nameof(LogTestController.ExecuteField2)).CreateResolverMetaData(); + var metaData = GraphQLTemplateHelper.CreateActionMethodTemplate(nameof(LogTestController.ExecuteField2)).CreateResolverMetaData(); var package = server.CreateGraphTypeFieldContextBuilder( nameof(LogTestController.ExecuteField2)); var resolutionContext = package.CreateResolutionContext(); @@ -431,13 +431,13 @@ public void ActionMethodInvocationCompletedLogEntry() var result = new object(); - var entry = new ActionMethodInvocationCompletedLogEntry(graphMethod, fieldRequest, result); + var entry = new ActionMethodInvocationCompletedLogEntry(metaData, fieldRequest, result); Assert.AreEqual(LogEventIds.ControllerInvocationCompleted.Id, entry.EventId); Assert.AreEqual(fieldRequest.Id.ToString(), entry.PipelineRequestId); - Assert.AreEqual(graphMethod.Parent.InternalFullName, entry.ControllerName); - Assert.AreEqual(graphMethod.Name, entry.ActionName); - Assert.AreEqual(graphMethod.Route.Path, entry.FieldPath); + Assert.AreEqual(metaData.ParentInternalFullName, entry.ControllerName); + Assert.AreEqual(metaData.Name, entry.ActionName); + Assert.AreEqual(metaData.Route.Path, entry.FieldPath); Assert.AreEqual(result.GetType().FriendlyName(true), entry.ResultTypeName); Assert.IsNotNull(entry.ToString()); } @@ -449,7 +449,7 @@ public void ActionMethodInvocationExceptionLogEntry() .AddType() .Build(); - var graphMethod = GraphQLTemplateHelper.CreateActionMethodTemplate(nameof(LogTestController.ExecuteField2)).CreateResolverMetaData(); + var metaData = GraphQLTemplateHelper.CreateActionMethodTemplate(nameof(LogTestController.ExecuteField2)).CreateResolverMetaData(); var package = server.CreateGraphTypeFieldContextBuilder( nameof(LogTestController.ExecuteField2)); var fieldRequest = package.FieldRequest; @@ -458,12 +458,12 @@ public void ActionMethodInvocationExceptionLogEntry() var inner = new Exception("inner error"); var exception = new TargetInvocationException("invocation error message", inner); - var entry = new ActionMethodInvocationExceptionLogEntry(graphMethod, fieldRequest, exception); + var entry = new ActionMethodInvocationExceptionLogEntry(metaData, fieldRequest, exception); Assert.AreEqual(LogEventIds.ControllerInvocationException.Id, entry.EventId); Assert.AreEqual(fieldRequest.Id.ToString(), entry.PipelineRequestId); - Assert.AreEqual(graphMethod.Parent.InternalFullName, entry.ControllerTypeName); - Assert.AreEqual(graphMethod.Name, entry.ActionName); + Assert.AreEqual(metaData.ParentInternalFullName, entry.ControllerTypeName); + Assert.AreEqual(metaData.Name, entry.ActionName); Assert.IsNotNull(entry.ToString()); var exceptionEntry = entry.Exception as ExceptionLogItem; @@ -493,7 +493,7 @@ public void ActionMethodUnhandledExceptionLogEntry() Assert.AreEqual(LogEventIds.ControllerUnhandledException.Id, entry.EventId); Assert.AreEqual(fieldRequest.Id.ToString(), entry.PipelineRequestId); - Assert.AreEqual(metaData.Parent.InternalFullName, entry.ControllerTypeName); + Assert.AreEqual(metaData.ParentInternalFullName, entry.ControllerTypeName); Assert.AreEqual(metaData.Name, entry.ActionName); Assert.IsNotNull(entry.ToString()); From be0a9412022582ab75af1960d71ab1df2c280cc4 Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Sun, 2 Jul 2023 19:23:21 -0700 Subject: [PATCH 20/63] WIP, decoupled resolver metadata from gql args and abstracted param info --- .../InternalServerErrorGraphActionResult.cs | 5 +- .../RouteNotFoundGraphActionResult.cs | 10 ++- .../Controllers/GraphControllerBase.cs | 12 +-- .../Engine/TypeMakers/GraphArgumentMaker.cs | 2 +- .../Execution/ExecutionArgumentCollection.cs | 76 ++++++++++++++----- .../Execution/IExecutionArgumentCollection.cs | 8 ++ .../Execution/IGraphFieldResolverMetaData.cs | 24 +----- .../IGraphFieldResolverParameterMetaData.cs | 74 ++++++++++++++++++ ...ieldResolverParameterMetaDataCollection.cs | 28 +++++++ .../Internal/IGraphArgumentTemplate.cs | 3 + .../Schema/IGraphArgumentCollection.cs | 8 ++ .../Resolvers/FieldResolverMetaData.cs | 21 +---- .../FieldResolverParameterMetaData.cs | 58 ++++++++++++++ ...ieldResolverParameterMetaDataCollection.cs | 62 +++++++++++++++ .../ObjectMethodGraphFieldResolver.cs | 30 ++++---- .../ObjectPropertyGraphFieldResolver.cs | 12 +-- .../TypeTemplates/GraphArgumentTemplate.cs | 14 ++++ .../GraphDirectiveMethodTemplate.cs | 8 +- .../MethodGraphFieldTemplateBase.cs | 9 ++- .../PropertyGraphFieldTemplate.cs | 8 +- .../ActionMethodExceptionLogEntryBase.cs | 2 +- ...ActionMethodInvocationCompletedLogEntry.cs | 11 --- .../ActionMethodInvocationStartedLogEntry.cs | 13 +--- ...ActionMethodModelStateValidatedLogEntry.cs | 13 +--- .../InvokeDirectiveResolverMiddleware.cs | 2 + .../GraphFieldArgumentCollection.cs | 14 ++++ .../Schemas/TypeSystem/MethodGraphField.cs | 1 - .../FieldContextBuilder.cs | 5 +- .../TestServer.cs | 13 ++-- .../ActionResults/ActionResultTests.cs | 2 +- ...nMethodModelStateValidatedLogEntryTests.cs | 2 +- .../GeneralEventLogEntryPropertyChecks.cs | 10 +-- 32 files changed, 402 insertions(+), 158 deletions(-) create mode 100644 src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverParameterMetaData.cs create mode 100644 src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverParameterMetaDataCollection.cs create mode 100644 src/graphql-aspnet/Internal/Resolvers/FieldResolverParameterMetaData.cs create mode 100644 src/graphql-aspnet/Internal/Resolvers/FieldResolverParameterMetaDataCollection.cs diff --git a/src/graphql-aspnet/Controllers/ActionResults/InternalServerErrorGraphActionResult.cs b/src/graphql-aspnet/Controllers/ActionResults/InternalServerErrorGraphActionResult.cs index f8dff3dca..a0631e70a 100644 --- a/src/graphql-aspnet/Controllers/ActionResults/InternalServerErrorGraphActionResult.cs +++ b/src/graphql-aspnet/Controllers/ActionResults/InternalServerErrorGraphActionResult.cs @@ -54,9 +54,12 @@ public InternalServerErrorGraphActionResult(string errorMessage, Exception excep public InternalServerErrorGraphActionResult(IGraphFieldResolverMetaData action, Exception exception) { _action = action; - _errorMessage = $"An unhandled exception was thrown during the execution of field '{_action?.Name ?? "-unknown-"}'."; + _errorMessage = $"An unhandled exception was thrown during the execution of an action. See inner exception for details."; _exception = exception; + + if (_exception == null) + _exception = new Exception($"The action method '{action?.InternalFullName}' failed to complete successfully but did not record an exception."); } /// diff --git a/src/graphql-aspnet/Controllers/ActionResults/RouteNotFoundGraphActionResult.cs b/src/graphql-aspnet/Controllers/ActionResults/RouteNotFoundGraphActionResult.cs index b55c6072d..06d13ca8f 100644 --- a/src/graphql-aspnet/Controllers/ActionResults/RouteNotFoundGraphActionResult.cs +++ b/src/graphql-aspnet/Controllers/ActionResults/RouteNotFoundGraphActionResult.cs @@ -58,8 +58,16 @@ public Task CompleteAsync(SchemaItemResolutionContext context) { if (_invokeDef != null) { + string fieldName; + if (context is FieldResolutionContext frc) + fieldName = frc.Request.Field.Route.Path; + else if (context is DirectiveResolutionContext drc) + fieldName = drc.Request.Directive.Route.Path; + else + fieldName = "-unknown-"; + context.Messages.Critical( - $"The field '{_invokeDef.Name}' was not found or could not be invoked.", + $"The field '{fieldName}' was not found or could not be invoked.", Constants.ErrorCodes.INVALID_ROUTE, context.Request.Origin, _thrownException); diff --git a/src/graphql-aspnet/Controllers/GraphControllerBase.cs b/src/graphql-aspnet/Controllers/GraphControllerBase.cs index c04417c05..380a87f0b 100644 --- a/src/graphql-aspnet/Controllers/GraphControllerBase.cs +++ b/src/graphql-aspnet/Controllers/GraphControllerBase.cs @@ -39,18 +39,18 @@ public abstract class GraphControllerBase /// /// Invoke the specified action method as an asynchronous operation. /// - /// The action to invoke. + /// The action to invoke. /// The invocation context to process. /// Task<System.Object>. [GraphSkip] internal virtual async Task InvokeActionAsync( - IGraphFieldResolverMetaData actionToInvoke, + IGraphFieldResolverMetaData actionMetadata, SchemaItemResolutionContext schemaItemContext) { // deconstruct the context for processing Validation.ThrowIfNull(schemaItemContext, nameof(schemaItemContext)); _schemaItemContext = schemaItemContext; - _action = actionToInvoke; + _action = actionMetadata; // ensure a field request is available var fieldRequest = schemaItemContext?.Request; @@ -90,7 +90,7 @@ internal virtual async Task InvokeActionAsync( { // given all the checking and parsing this should be imnpossible, but just in case invokeReturn = new InternalServerErrorGraphActionResult( - $"The action '{_action.Route.Path}' is defined " + + $"The action '{_action.InternalName}' on controller '{_action.ParentInternalName}' is defined " + $"as asyncronous but it did not return a {typeof(Task)}."); } } @@ -138,13 +138,13 @@ protected virtual object CreateAndInvokeAction(IGraphFieldResolverMetaData metho { if (methodMetadata.Method.DeclaringType != this.GetType()) { - throw new TargetException($"Unable to invoke action '{_action.Route.Path}' on controller '{this.GetType().FriendlyName()}'. The controller " + + throw new TargetException($"Unable to invoke action '{_action.InternalName}' on controller '{this.GetType().FriendlyName()}'. The controller " + "does not own the method."); } if (methodMetadata.Method.IsStatic) { - throw new TargetException($"Unable to invoke action '{_action.Route.Path}' on controller '{this.GetType().FriendlyName()}'. The method " + + throw new TargetException($"Unable to invoke action '{_action.InternalName}' on controller '{this.GetType().FriendlyName()}'. The method " + "is static and cannot be directly invoked on this controller instance."); } diff --git a/src/graphql-aspnet/Engine/TypeMakers/GraphArgumentMaker.cs b/src/graphql-aspnet/Engine/TypeMakers/GraphArgumentMaker.cs index 8c09f7d55..e916d068b 100644 --- a/src/graphql-aspnet/Engine/TypeMakers/GraphArgumentMaker.cs +++ b/src/graphql-aspnet/Engine/TypeMakers/GraphArgumentMaker.cs @@ -46,7 +46,7 @@ public GraphArgumentCreationResult CreateArgument(ISchemaItem owner, IGraphArgum template.Route, template.ArgumentModifiers, template.DeclaredArgumentName, - template.InternalFullName, + template.InternalName, template.ObjectType, template.HasDefaultValue, template.DefaultValue, diff --git a/src/graphql-aspnet/Execution/ExecutionArgumentCollection.cs b/src/graphql-aspnet/Execution/ExecutionArgumentCollection.cs index 9b48f463f..17c05b328 100644 --- a/src/graphql-aspnet/Execution/ExecutionArgumentCollection.cs +++ b/src/graphql-aspnet/Execution/ExecutionArgumentCollection.cs @@ -16,7 +16,6 @@ namespace GraphQL.AspNet.Execution using GraphQL.AspNet.Execution.Contexts; using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Interfaces.Execution; - using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Schemas.TypeSystem; /// @@ -27,6 +26,7 @@ namespace GraphQL.AspNet.Execution internal class ExecutionArgumentCollection : IExecutionArgumentCollection { private readonly Dictionary _arguments; + private readonly GraphDirectiveExecutionContext _directiveContext; private readonly GraphFieldExecutionContext _fieldContext; /// @@ -43,7 +43,7 @@ public ExecutionArgumentCollection(int? capacity = null) /// /// Initializes a new instance of the class. /// - /// The argument list. + /// The argument list keyed by the argument's name in the graph. /// The field context. private ExecutionArgumentCollection( IDictionary argumentList, @@ -53,6 +53,19 @@ private ExecutionArgumentCollection( _fieldContext = fieldContext; } + /// + /// Initializes a new instance of the class. + /// + /// The argument list keyed by the argument's name in the graph. + /// The directive context. + private ExecutionArgumentCollection( + IDictionary argumentList, + GraphDirectiveExecutionContext directiveContext) + { + _arguments = new Dictionary(argumentList); + _directiveContext = directiveContext; + } + /// public void Add(ExecutionArgument argument) { @@ -63,7 +76,14 @@ public void Add(ExecutionArgument argument) /// public IExecutionArgumentCollection ForContext(GraphFieldExecutionContext fieldContext) { - return new ExecutionArgumentCollection(_arguments, fieldContext); + return new ExecutionArgumentCollection(_arguments, fieldContext); + } + + + /// + public IExecutionArgumentCollection ForContext(GraphDirectiveExecutionContext directiveContext) + { + return new ExecutionArgumentCollection(_arguments, directiveContext); } /// @@ -85,31 +105,49 @@ public bool TryGetArgument(string argumentName, out TType argumentValue) } /// - public object[] PrepareArguments(IGraphFieldResolverMetaData graphMethod) + public object[] PrepareArguments(IGraphFieldResolverMetaData resolverMetadata) { + Validation.ThrowIfNull(resolverMetadata, nameof(resolverMetadata)); + var preparedParams = new List(); - var paramInfos = graphMethod.Parameters; - for (var i = 0; i < graphMethod.Arguments.Count; i++) + for (var i = 0; i < resolverMetadata.Parameters.Count; i++) { - var argTemplate = graphMethod.Arguments[i]; - object passedValue = this.ResolveParameterFromArgumentTemplate(argTemplate); - if (passedValue == null && !argTemplate.TypeExpression.IsNullable) + var parameter = resolverMetadata.Parameters[i]; + object passedValue = this.ResolveParameterFromMetadata(parameter); + + var fieldArgument = _fieldContext? + .Request + .Field + .Arguments + .FindArgumentByInternalName(parameter.InternalName); + + fieldArgument = fieldArgument ?? + _directiveContext? + .Request + .Directive + .Arguments + .FindArgumentByInternalName(parameter.InternalName); + + if (fieldArgument == null) + throw new GraphExecutionException($"Argument '{parameter.InternalName}' was not found on its expected parent."); + + if (passedValue == null && !fieldArgument.TypeExpression.IsNullable) { // technically shouldn't be throwable given the validation routines // but captured here as a saftey net for users // doing custom extensions or implementations throw new GraphExecutionException( - $"The parameter '{argTemplate.Name}' for field '{graphMethod.Route.Path}' could not be resolved from the query document " + + $"The parameter '{parameter.InternalName}' for field '{_fieldContext?.Request?.Field?.Route.Path}' could not be resolved from the query document " + "or variable collection and no default value was found."); } // ensure compatible list types between the internally // tracked data and the target type of the method being invoked // i.e. convert List => T[] when needed - if (argTemplate.TypeExpression.IsListOfItems) + if (fieldArgument.TypeExpression.IsListOfItems) { - var listMangler = new ListMangler(paramInfos[i].ParameterType); + var listMangler = new ListMangler(parameter.ExpectedType); var result = listMangler.Convert(passedValue); passedValue = result.Data; } @@ -120,12 +158,7 @@ public object[] PrepareArguments(IGraphFieldResolverMetaData graphMethod) return preparedParams.ToArray(); } - /// - /// Attempts to deserialize a parameter value from the graph ql context supplied. - /// - /// The argument definition. - /// System.Object. - private object ResolveParameterFromArgumentTemplate(IGraphArgumentTemplate argDefinition) + private object ResolveParameterFromMetadata(IGraphFieldResolverParameterMetaData argDefinition) { if (argDefinition == null) return null; @@ -136,9 +169,10 @@ private object ResolveParameterFromArgumentTemplate(IGraphArgumentTemplate argDe if (argDefinition.ArgumentModifiers.IsCancellationToken()) return _fieldContext?.CancellationToken ?? default; - return this.ContainsKey(argDefinition.DeclaredArgumentName) - ? this[argDefinition.DeclaredArgumentName].Value - : argDefinition.DefaultValue; + if (this.ContainsKey(argDefinition.InternalName)) + return this[argDefinition.InternalName].Value; + + return argDefinition.DefaultValue; } /// diff --git a/src/graphql-aspnet/Interfaces/Execution/IExecutionArgumentCollection.cs b/src/graphql-aspnet/Interfaces/Execution/IExecutionArgumentCollection.cs index d86ffef80..56068c652 100644 --- a/src/graphql-aspnet/Interfaces/Execution/IExecutionArgumentCollection.cs +++ b/src/graphql-aspnet/Interfaces/Execution/IExecutionArgumentCollection.cs @@ -27,6 +27,14 @@ public interface IExecutionArgumentCollection : IReadOnlyDictionaryIExecutionArgumentCollection. IExecutionArgumentCollection ForContext(GraphFieldExecutionContext fieldExecutionContext); + /// + /// Augments the collection with a source data object for a specific field execution and returns + /// a copy of itself with that data attached. + /// + /// The directive context being executed. + /// IExecutionArgumentCollection. + IExecutionArgumentCollection ForContext(GraphDirectiveExecutionContext directiveContext); + /// /// Adds the specified argument to the collection. /// diff --git a/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverMetaData.cs b/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverMetaData.cs index 15ab9b139..51eb3c18b 100644 --- a/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverMetaData.cs +++ b/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverMetaData.cs @@ -10,10 +10,7 @@ namespace GraphQL.AspNet.Interfaces.Execution { using System; - using System.Collections.Generic; using System.Reflection; - using GraphQL.AspNet.Interfaces.Internal; - using GraphQL.AspNet.Schemas.Structural; /// /// A data package describing the details necessary to @@ -44,13 +41,6 @@ public interface IGraphFieldResolverMetaData /// The method to be invoked. MethodInfo Method { get; } - /// - /// Gets the raw parameters that exist on the - /// that must be supplied at invocation. - /// - /// The parameters of the target . - IReadOnlyList Parameters { get; } - /// /// Gets a value indicating whether the method described by this instance should be /// invoked asyncronously. @@ -58,12 +48,6 @@ public interface IGraphFieldResolverMetaData /// true if the method is asynchronous; otherwise, false. bool IsAsyncField { get; } - /// - /// Gets the method's field name in the object graph. - /// - /// This method's name in the object graph. - string Name { get; } - /// /// Gets the fully qualified name, including namespace, of this item as it exists in the /// .NET code (e.g. Namespace.ObjectType.MethodName). @@ -99,16 +83,10 @@ public interface IGraphFieldResolverMetaData /// The name of the parent. string ParentInternalFullName { get; } - /// - /// Gets the unique route that points to the field in the object graph. - /// - /// The route. - SchemaItemPath Route { get; } - /// /// Gets the templatized field arguments representing the field (if any). /// /// The arguments defined on this field. - IReadOnlyList Arguments { get; } + IGraphFieldResolverParameterMetaDataCollection Parameters { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverParameterMetaData.cs b/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverParameterMetaData.cs new file mode 100644 index 000000000..511f84a4a --- /dev/null +++ b/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverParameterMetaData.cs @@ -0,0 +1,74 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Interfaces.Execution +{ + using System; + using System.Reflection; + using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Schemas.TypeSystem; + + /// + /// A metadata object that describes a single parameter passed to a resolver for execution. + /// + /// + /// This metadata object is expressed in terms of the implementation method. That is, .NET + /// terms not GraphQL terms. + /// + public interface IGraphFieldResolverParameterMetaData + { + /// + /// Gets the parameter info that defines the argument. + /// + /// The method to be invoked. + ParameterInfo ParameterInfo { get; } + + /// + /// Gets the type of data expected to be passed to this parameter when its target + /// method is invoked. + /// + /// The expected type of data this parameter can accept. + Type ExpectedType { get; } + + /// + /// Gets the fully qualified name, including namespace, of this item as it exists in the + /// .NET code (e.g. Namespace.ObjectType.MethodName). + /// + /// The fully qualified name given to this item. + string InternalFullName { get; } + + /// + /// Gets the name that defines this item within the .NET code of the application; + /// typically a method name or property name. + /// + /// The internal name given to this item. + string InternalName { get; } + + /// + /// Gets the set of argument modifiers created for this parameter via the template that created + /// it. + /// + /// The argument modifiers. + GraphArgumentModifiers ArgumentModifiers { get; } + + /// + /// Gets the default value assigned to this parameter, if any. + /// + /// The default value. + object DefaultValue { get; } + + /// + /// Gets the concrete type that represents this parameter in a graphql graph. If this + /// parameter is a list this will represent the object type of a singular instance of the + /// item nested within the list. + /// + /// The type of the object that represents this parameter in an object graph. + Type ObjectType { get; } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverParameterMetaDataCollection.cs b/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverParameterMetaDataCollection.cs new file mode 100644 index 000000000..c9ac40c95 --- /dev/null +++ b/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverParameterMetaDataCollection.cs @@ -0,0 +1,28 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Interfaces.Execution +{ + using System.Collections.Generic; + using System.Reflection; + + /// + /// A set of metadata items for the parameters of a given resolver. + /// + public interface IGraphFieldResolverParameterMetaDataCollection : IReadOnlyList + { + /// + /// Gets the with the specified parameter name. This + /// name is case sensitive and should match the parameter declaration in the source code. + /// + /// Name of the parameter as it exists in source code. + /// IGraphFieldResolverParameterMetaData. + IGraphFieldResolverParameterMetaData this[string parameterName] { get; } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Internal/IGraphArgumentTemplate.cs b/src/graphql-aspnet/Interfaces/Internal/IGraphArgumentTemplate.cs index bcce097a0..78ee7a346 100644 --- a/src/graphql-aspnet/Interfaces/Internal/IGraphArgumentTemplate.cs +++ b/src/graphql-aspnet/Interfaces/Internal/IGraphArgumentTemplate.cs @@ -10,6 +10,7 @@ namespace GraphQL.AspNet.Interfaces.Internal { using System; + using GraphQL.AspNet.Interfaces.Execution; using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Schemas.TypeSystem; @@ -18,6 +19,8 @@ namespace GraphQL.AspNet.Interfaces.Internal /// public interface IGraphArgumentTemplate : ISchemaItemTemplate { + IGraphFieldResolverParameterMetaData CreateResolverMetaData(); + /// /// Gets the parent method this parameter belongs to. /// diff --git a/src/graphql-aspnet/Interfaces/Schema/IGraphArgumentCollection.cs b/src/graphql-aspnet/Interfaces/Schema/IGraphArgumentCollection.cs index ab3206900..9eaced09f 100644 --- a/src/graphql-aspnet/Interfaces/Schema/IGraphArgumentCollection.cs +++ b/src/graphql-aspnet/Interfaces/Schema/IGraphArgumentCollection.cs @@ -73,6 +73,14 @@ IGraphArgument AddArgument( /// IGraphArgument. IGraphArgument FindArgument(string argumentName); + /// + /// Finds the name of the argument by internally declared name. e.g. the name of the parameter + /// on a C# method. + /// + /// The internal name of the argument. + /// IGraphArgument. + IGraphArgument FindArgumentByInternalName(string internalName); + /// /// Gets the with the specified name. Argument /// names are case sensitive and should match the public name as its defined on the target schema. diff --git a/src/graphql-aspnet/Internal/Resolvers/FieldResolverMetaData.cs b/src/graphql-aspnet/Internal/Resolvers/FieldResolverMetaData.cs index a2efe02af..25b7d7b34 100644 --- a/src/graphql-aspnet/Internal/Resolvers/FieldResolverMetaData.cs +++ b/src/graphql-aspnet/Internal/Resolvers/FieldResolverMetaData.cs @@ -26,13 +26,10 @@ internal class FieldResolverMetaData : IGraphFieldResolverMetaData { public FieldResolverMetaData( MethodInfo method, - IEnumerable parameters, - IEnumerable arguments, + IGraphFieldResolverParameterMetaDataCollection parameters, Type expectedReturnType, Type objectType, - SchemaItemPath route, bool isAsyncField, - string name, string internalName, string internalFullName, Type parentObjectType, @@ -40,16 +37,13 @@ public FieldResolverMetaData( string parentInternalFullName) { this.Method = Validation.ThrowIfNullOrReturn(method, nameof(method)); - this.Route = Validation.ThrowIfNullOrReturn(route, nameof(route)); this.ObjectType = Validation.ThrowIfNullOrReturn(objectType, nameof(objectType)); this.ExpectedReturnType = Validation.ThrowIfNullOrReturn(expectedReturnType, nameof(expectedReturnType)); this.IsAsyncField = isAsyncField; - this.Parameters = new List(parameters ?? Enumerable.Empty()); - this.Arguments = new List(arguments ?? Enumerable.Empty()); + this.Parameters = Validation.ThrowIfNullOrReturn(parameters, nameof(parameters)); - this.Name = Validation.ThrowIfNullWhiteSpaceOrReturn(name, nameof(name)); this.InternalName = Validation.ThrowIfNullWhiteSpaceOrReturn(internalName, nameof(internalName)); this.InternalFullName = Validation.ThrowIfNullWhiteSpaceOrReturn(internalFullName, nameof(internalFullName)); @@ -67,9 +61,6 @@ public FieldResolverMetaData( /// public bool IsAsyncField { get; } - /// - public string Name { get; } - /// public string InternalFullName { get; } @@ -80,13 +71,7 @@ public FieldResolverMetaData( public Type ObjectType { get; } /// - public IReadOnlyList Parameters { get; } - - /// - public SchemaItemPath Route { get; } - - /// - public IReadOnlyList Arguments { get; } + public IGraphFieldResolverParameterMetaDataCollection Parameters { get; } /// public string ParentInternalName { get; } diff --git a/src/graphql-aspnet/Internal/Resolvers/FieldResolverParameterMetaData.cs b/src/graphql-aspnet/Internal/Resolvers/FieldResolverParameterMetaData.cs new file mode 100644 index 000000000..45c7dc390 --- /dev/null +++ b/src/graphql-aspnet/Internal/Resolvers/FieldResolverParameterMetaData.cs @@ -0,0 +1,58 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Internal.Resolvers +{ + using System; + using System.Reflection; + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Interfaces.Execution; + using GraphQL.AspNet.Schemas.TypeSystem; + + internal class FieldResolverParameterMetaData : IGraphFieldResolverParameterMetaData + { + public FieldResolverParameterMetaData( + ParameterInfo paramInfo, + Type objectType, + string internalName, + string internalFullName, + GraphArgumentModifiers modifiers, + object defaultValue = null) + { + this.ParameterInfo = Validation.ThrowIfNullOrReturn(paramInfo, nameof(paramInfo)); + this.ExpectedType = this.ParameterInfo.ParameterType; + this.ObjectType = Validation.ThrowIfNullOrReturn(objectType, nameof(objectType)); + this.InternalName = Validation.ThrowIfNullWhiteSpaceOrReturn(internalName, nameof(internalName)); + this.InternalFullName = Validation.ThrowIfNullWhiteSpaceOrReturn(internalFullName, nameof(internalFullName)); + this.DefaultValue = defaultValue; + this.ArgumentModifiers = modifiers; + } + + /// + public ParameterInfo ParameterInfo { get; } + + /// + public string InternalFullName { get; } + + /// + public string InternalName { get; } + + /// + public GraphArgumentModifiers ArgumentModifiers { get; } + + /// + public object DefaultValue { get; } + + /// + public Type ObjectType { get; } + + /// + public Type ExpectedType { get; } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Internal/Resolvers/FieldResolverParameterMetaDataCollection.cs b/src/graphql-aspnet/Internal/Resolvers/FieldResolverParameterMetaDataCollection.cs new file mode 100644 index 000000000..273ea23af --- /dev/null +++ b/src/graphql-aspnet/Internal/Resolvers/FieldResolverParameterMetaDataCollection.cs @@ -0,0 +1,62 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Internal.Resolvers +{ + using System.Collections; + using System.Collections.Generic; + using System.Linq; + using GraphQL.AspNet.Interfaces.Execution; + + /// + /// A collection of parameter metadata that can be accessed by index in its parent method or by name. + /// + internal class FieldResolverParameterMetaDataCollection : IGraphFieldResolverParameterMetaDataCollection + { + private List _parameters; + private Dictionary _parametersByName; + + /// + /// Initializes a new instance of the class. + /// + /// The parameters to include in this collection. + public FieldResolverParameterMetaDataCollection(IEnumerable parameters = null) + { + parameters = parameters ?? Enumerable.Empty(); + + _parameters = new List(parameters); + + _parametersByName = new Dictionary(_parameters.Count); + + foreach (var arg in _parameters) + _parametersByName.Add(arg.ParameterInfo.Name, arg); + } + + /// + public IEnumerator GetEnumerator() + { + return _parameters.GetEnumerator(); + } + + /// + IEnumerator IEnumerable.GetEnumerator() + { + return this.GetEnumerator(); + } + + /// + public IGraphFieldResolverParameterMetaData this[string parameterName] => _parametersByName[parameterName]; + + /// + public IGraphFieldResolverParameterMetaData this[int index] => _parameters[index]; + + /// + public int Count => _parameters.Count; + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Internal/Resolvers/ObjectMethodGraphFieldResolver.cs b/src/graphql-aspnet/Internal/Resolvers/ObjectMethodGraphFieldResolver.cs index 6564237d9..c18c9e51a 100644 --- a/src/graphql-aspnet/Internal/Resolvers/ObjectMethodGraphFieldResolver.cs +++ b/src/graphql-aspnet/Internal/Resolvers/ObjectMethodGraphFieldResolver.cs @@ -26,17 +26,17 @@ namespace GraphQL.AspNet.Internal.Resolvers /// internal class ObjectMethodGraphFieldResolver : IGraphFieldResolver { - private readonly IGraphFieldResolverMetaData _graphMethod; + private readonly IGraphFieldResolverMetaData _resolverMetadata; private readonly MethodInfo _methodInfo; /// /// Initializes a new instance of the class. /// - /// A resolver method that points to a .NET method. - public ObjectMethodGraphFieldResolver(IGraphFieldResolverMetaData graphMethod) + /// A resolver method that points to a .NET method. + public ObjectMethodGraphFieldResolver(IGraphFieldResolverMetaData resolverMetadata) { - _graphMethod = Validation.ThrowIfNullOrReturn(graphMethod, nameof(graphMethod)); - _methodInfo = _graphMethod.Method; + _resolverMetadata = Validation.ThrowIfNullOrReturn(resolverMetadata, nameof(resolverMetadata)); + _methodInfo = _resolverMetadata.Method; } /// @@ -47,7 +47,7 @@ public virtual async Task ResolveAsync(FieldResolutionContext context, Cancellat { context.Messages.Critical( "No source data was provided to the field resolver " + - $"for '{_graphMethod.Route.Path}'. Unable to complete the request.", + $"for '{context.Request.Field.Route.Path}'. Unable to complete the request.", Constants.ErrorCodes.INVALID_OBJECT, context.Request.Origin); @@ -59,12 +59,12 @@ public virtual async Task ResolveAsync(FieldResolutionContext context, Cancellat { context.Messages.Critical( "The source data provided to the field resolver " + - $"for '{_graphMethod.Route.Path}' could not be coerced into the expected source graph type. See exception for details.", + $"for '{context.Request.Field.Route.Path}' could not be coerced into the expected source graph type. See exception for details.", Constants.ErrorCodes.INVALID_OBJECT, context.Request.Origin, new GraphExecutionException( - $"The method '{_graphMethod.InternalFullName}' expected source data of type " + - $"'{_graphMethod.ParentObjectType.FriendlyName()}' but received '{sourceData.GetType().FriendlyName()}' " + + $"The method '{_resolverMetadata.InternalFullName}' expected source data of type " + + $"'{_resolverMetadata.ParentObjectType.FriendlyName()}' but received '{sourceData.GetType().FriendlyName()}' " + "which is not compatible.")); return; @@ -74,17 +74,17 @@ public virtual async Task ResolveAsync(FieldResolutionContext context, Cancellat { object data = null; - var paramSet = context.Arguments.PrepareArguments(_graphMethod); - var invoker = InstanceFactory.CreateInstanceMethodInvoker(_graphMethod.Method); + var paramSet = context.Arguments.PrepareArguments(_resolverMetadata); + var invoker = InstanceFactory.CreateInstanceMethodInvoker(_resolverMetadata.Method); var invokableObject = context.Arguments.SourceData as object; var invokeReturn = invoker(ref invokableObject, paramSet); - if (_graphMethod.IsAsyncField) + if (_resolverMetadata.IsAsyncField) { if (invokeReturn is Task task) { await task.ConfigureAwait(false); - data = task.ResultOfTypeOrNull(_graphMethod.ExpectedReturnType); + data = task.ResultOfTypeOrNull(_resolverMetadata.ExpectedReturnType); } } else @@ -104,7 +104,7 @@ public virtual async Task ResolveAsync(FieldResolutionContext context, Cancellat catch (Exception ex) { context.Messages.Critical( - $"An unknown error occured atttempting to resolve the field '{_graphMethod.Route.Path}'. " + + $"An unknown error occured atttempting to resolve the field '{context.Request.Field.Route.Path}'. " + "See exception for details.", Constants.ErrorCodes.UNHANDLED_EXCEPTION, context.Request.Origin, @@ -113,6 +113,6 @@ public virtual async Task ResolveAsync(FieldResolutionContext context, Cancellat } /// - public Type ObjectType => _graphMethod.ObjectType; + public Type ObjectType => _resolverMetadata.ObjectType; } } \ No newline at end of file diff --git a/src/graphql-aspnet/Internal/Resolvers/ObjectPropertyGraphFieldResolver.cs b/src/graphql-aspnet/Internal/Resolvers/ObjectPropertyGraphFieldResolver.cs index cfcbc2aca..7b3bcb142 100644 --- a/src/graphql-aspnet/Internal/Resolvers/ObjectPropertyGraphFieldResolver.cs +++ b/src/graphql-aspnet/Internal/Resolvers/ObjectPropertyGraphFieldResolver.cs @@ -46,7 +46,7 @@ public async Task ResolveAsync(FieldResolutionContext context, CancellationToken { context.Messages.Critical( "No source data was provided to the field resolver " + - $"for '{_resolverMetadata.Name}'. Unable to complete the request.", + $"for '{context.Request.Field.Route.Path}'. Unable to complete the request.", Constants.ErrorCodes.INVALID_OBJECT, context.Request.Origin); @@ -62,7 +62,7 @@ public async Task ResolveAsync(FieldResolutionContext context, CancellationToken { context.Messages.Critical( "The source data provided to the field resolver " + - $"for '{_resolverMetadata.Route.Path}' could not be coerced into the expected source graph type. See exception for details.", + $"for '{context.Request.Field.Route.Path}' could not be coerced into the expected source graph type. See exception for details.", Constants.ErrorCodes.INVALID_OBJECT, context.Request.Origin, new GraphExecutionException( @@ -77,7 +77,7 @@ public async Task ResolveAsync(FieldResolutionContext context, CancellationToken { context.Messages.Critical( "The source data provided to the field resolver " + - $"for '{_resolverMetadata.Route.Path}' could not be coerced into the expected source graph type. See exception for details.", + $"for '{context.Request.Field.Route.Path}' could not be coerced into the expected source graph type. See exception for details.", Constants.ErrorCodes.INVALID_OBJECT, context.Request.Origin, new GraphExecutionException( @@ -106,11 +106,11 @@ public async Task ResolveAsync(FieldResolutionContext context, CancellationToken { context.Messages.Critical( "The source data provided to the field resolver " + - $"for '{_resolverMetadata.Route.Path}' could not be coerced into the expected source graph type. See exception for details.", + $"for '{context.Request.Field.Route.Path}' could not be coerced into the expected source graph type. See exception for details.", Constants.ErrorCodes.INVALID_OBJECT, context.Request.Origin, new GraphExecutionException( - $"The method '{_resolverMetadata.Route.Path}' is defined " + + $"The method '{context.Request.Field.Route.Path}' is defined " + $"as asyncronous but it did not return a {typeof(Task)}.")); invokeReturn = null; } @@ -128,7 +128,7 @@ public async Task ResolveAsync(FieldResolutionContext context, CancellationToken catch (Exception ex) { context.Messages.Critical( - $"An unknown error occured atttempting to resolve the field '{_resolverMetadata.Route.Path}'. See exception for details.", + $"An unknown error occured atttempting to resolve the field '{context.Request.Field.Route.Path}'. See exception for details.", Constants.ErrorCodes.UNHANDLED_EXCEPTION, context.Request.Origin, ex); diff --git a/src/graphql-aspnet/Internal/TypeTemplates/GraphArgumentTemplate.cs b/src/graphql-aspnet/Internal/TypeTemplates/GraphArgumentTemplate.cs index f031a5b3d..3af25c4ea 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/GraphArgumentTemplate.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/GraphArgumentTemplate.cs @@ -20,7 +20,9 @@ namespace GraphQL.AspNet.Internal.TypeTemplates using GraphQL.AspNet.Common; using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Execution.Exceptions; + using GraphQL.AspNet.Interfaces.Execution; using GraphQL.AspNet.Interfaces.Internal; + using GraphQL.AspNet.Internal.Resolvers; using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; @@ -225,6 +227,18 @@ public void ValidateOrThrow() directive.ValidateOrThrow(); } + /// + public IGraphFieldResolverParameterMetaData CreateResolverMetaData() + { + return new FieldResolverParameterMetaData( + this.Parameter, + this.ObjectType, + this.InternalName, + this.InternalFullName, + this.ArgumentModifiers, + this.DefaultValue); + } + /// public string Name => this.Route.Name; diff --git a/src/graphql-aspnet/Internal/TypeTemplates/GraphDirectiveMethodTemplate.cs b/src/graphql-aspnet/Internal/TypeTemplates/GraphDirectiveMethodTemplate.cs index d7fc824de..990ee6021 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/GraphDirectiveMethodTemplate.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/GraphDirectiveMethodTemplate.cs @@ -195,15 +195,15 @@ public IEnumerable RetrieveRequiredTypes() internal IGraphFieldResolverMetaData CreateResolverMetaData() { + var paramSet = new FieldResolverParameterMetaDataCollection( + this.Arguments.Select(x => x.CreateResolverMetaData())); + return new FieldResolverMetaData( this.Method, - this.Parameters, - this.Arguments, + paramSet, this.ExpectedReturnType, this.ObjectType, - this.Route, this.IsAsyncField, - this.Name, this.InternalName, this.InternalFullName, this.Parent.ObjectType, diff --git a/src/graphql-aspnet/Internal/TypeTemplates/MethodGraphFieldTemplateBase.cs b/src/graphql-aspnet/Internal/TypeTemplates/MethodGraphFieldTemplateBase.cs index 674035c1b..21fb19f08 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/MethodGraphFieldTemplateBase.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/MethodGraphFieldTemplateBase.cs @@ -106,17 +106,18 @@ public override IGraphFieldResolver CreateResolver() return new ObjectMethodGraphFieldResolver(this.CreateResolverMetaData()); } + /// public override IGraphFieldResolverMetaData CreateResolverMetaData() { + var paramSet = new FieldResolverParameterMetaDataCollection( + this.Arguments.Select(x => x.CreateResolverMetaData())); + return new FieldResolverMetaData( this.Method, - this.Parameters, - this.Arguments, + paramSet, this.ExpectedReturnType, this.ObjectType, - this.Route, this.IsAsyncField, - this.Name, this.InternalName, this.InternalFullName, this.Parent.ObjectType, diff --git a/src/graphql-aspnet/Internal/TypeTemplates/PropertyGraphFieldTemplate.cs b/src/graphql-aspnet/Internal/TypeTemplates/PropertyGraphFieldTemplate.cs index 6c8eac890..3c9915b46 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/PropertyGraphFieldTemplate.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/PropertyGraphFieldTemplate.cs @@ -116,15 +116,15 @@ public override IGraphFieldResolver CreateResolver() public override IGraphFieldResolverMetaData CreateResolverMetaData() { + var paramSet = new FieldResolverParameterMetaDataCollection( + this.Arguments.Select(x => x.CreateResolverMetaData())); + return new FieldResolverMetaData( this.Method, - this.Parameters, - this.Arguments, + paramSet, this.ExpectedReturnType, this.ObjectType, - this.Route, this.IsAsyncField, - this.Name, this.InternalName, this.InternalFullName, this.Parent.ObjectType, diff --git a/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodExceptionLogEntryBase.cs b/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodExceptionLogEntryBase.cs index f0098dc9f..802e54edc 100644 --- a/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodExceptionLogEntryBase.cs +++ b/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodExceptionLogEntryBase.cs @@ -37,7 +37,7 @@ protected ActionMethodExceptionLogEntryBase( { this.PipelineRequestId = request?.Id.ToString(); this.ControllerTypeName = method?.ParentInternalFullName; - this.ActionName = method?.Name; + this.ActionName = method?.InternalName; this.Exception = new ExceptionLogItem(exception); } diff --git a/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodInvocationCompletedLogEntry.cs b/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodInvocationCompletedLogEntry.cs index 0833f7c5f..d5bae4d27 100644 --- a/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodInvocationCompletedLogEntry.cs +++ b/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodInvocationCompletedLogEntry.cs @@ -33,7 +33,6 @@ public ActionMethodInvocationCompletedLogEntry(IGraphFieldResolverMetaData metho this.PipelineRequestId = request?.Id.ToString(); this.ControllerName = method?.ParentInternalFullName; this.ActionName = method?.InternalName; - this.FieldPath = method?.Route?.Path; this.ResultTypeName = result?.GetType().FriendlyName(true); _shortControllerName = method?.ParentInternalName; } @@ -69,16 +68,6 @@ public string ActionName private set => this.SetProperty(LogPropertyNames.ACTION_NAME, value); } - /// - /// Gets the path, in the target schema, of the action. - /// - /// The action name. - public string FieldPath - { - get => this.GetProperty(LogPropertyNames.SCHEMA_ITEM_PATH); - private set => this.SetProperty(LogPropertyNames.SCHEMA_ITEM_PATH, value); - } - /// /// Gets the name of the data that was returned. If the method /// returned a the type of the action result is recorded. diff --git a/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodInvocationStartedLogEntry.cs b/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodInvocationStartedLogEntry.cs index d87fbf09a..334240715 100644 --- a/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodInvocationStartedLogEntry.cs +++ b/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodInvocationStartedLogEntry.cs @@ -30,8 +30,7 @@ public ActionMethodInvocationStartedLogEntry(IGraphFieldResolverMetaData method, { this.PipelineRequestId = request?.Id.ToString(); this.ControllerName = method?.ParentInternalFullName; - this.ActionName = method?.Name; - this.FieldPath = method?.Route?.Path; + this.ActionName = method?.InternalName; this.SourceObjectType = method?.ObjectType?.ToString(); this.IsAsync = method?.IsAsyncField; _shortControllerName = method?.ParentInternalName; @@ -68,16 +67,6 @@ public string ActionName private set => this.SetProperty(LogPropertyNames.ACTION_NAME, value); } - /// - /// Gets the path, in the target schema, of the action. - /// - /// The action name. - public string FieldPath - { - get => this.GetProperty(LogPropertyNames.SCHEMA_ITEM_PATH); - private set => this.SetProperty(LogPropertyNames.SCHEMA_ITEM_PATH, value); - } - /// /// Gets the name of the expected source data object to this /// action. diff --git a/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodModelStateValidatedLogEntry.cs b/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodModelStateValidatedLogEntry.cs index 151410522..eb1b6f2fe 100644 --- a/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodModelStateValidatedLogEntry.cs +++ b/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodModelStateValidatedLogEntry.cs @@ -39,8 +39,7 @@ public ActionMethodModelStateValidatedLogEntry( { this.PipelineRequestId = request?.Id.ToString(); this.ControllerName = method?.ParentInternalFullName; - this.ActionName = method?.Name; - this.FieldPath = method?.Route?.Path; + this.ActionName = method?.InternalName; this.ModelDataIsValid = modelState?.IsValid; _shortControllerName = method?.ParentInternalName; @@ -91,16 +90,6 @@ public string ActionName private set => this.SetProperty(LogPropertyNames.ACTION_NAME, value); } - /// - /// Gets the path, in the target schema, of the action. - /// - /// The action name. - public string FieldPath - { - get => this.GetProperty(LogPropertyNames.SCHEMA_ITEM_PATH); - private set => this.SetProperty(LogPropertyNames.SCHEMA_ITEM_PATH, value); - } - /// /// Gets a value indicating whether the collective sum of model data is in a valid state /// when its passed to the method for execution. diff --git a/src/graphql-aspnet/Middleware/DirectiveExecution/Components/InvokeDirectiveResolverMiddleware.cs b/src/graphql-aspnet/Middleware/DirectiveExecution/Components/InvokeDirectiveResolverMiddleware.cs index 066a4a3e5..4a266437a 100644 --- a/src/graphql-aspnet/Middleware/DirectiveExecution/Components/InvokeDirectiveResolverMiddleware.cs +++ b/src/graphql-aspnet/Middleware/DirectiveExecution/Components/InvokeDirectiveResolverMiddleware.cs @@ -44,6 +44,8 @@ public async Task InvokeAsync(GraphDirectiveExecutionContext context, GraphMiddl } else { + executionArguments = executionArguments.ForContext(context); + var resolutionContext = new DirectiveResolutionContext( context.Schema, context, diff --git a/src/graphql-aspnet/Schemas/Structural/GraphFieldArgumentCollection.cs b/src/graphql-aspnet/Schemas/Structural/GraphFieldArgumentCollection.cs index 519cb6692..a9238dd49 100644 --- a/src/graphql-aspnet/Schemas/Structural/GraphFieldArgumentCollection.cs +++ b/src/graphql-aspnet/Schemas/Structural/GraphFieldArgumentCollection.cs @@ -26,6 +26,7 @@ internal class GraphFieldArgumentCollection : IGraphArgumentCollection { private readonly ISchemaItem _owner; private readonly OrderedDictionary _arguments; + private readonly Dictionary _argumentByInternalName; private IGraphArgument _sourceArgument; /// @@ -37,13 +38,17 @@ public GraphFieldArgumentCollection(ISchemaItem owner) { _owner = Validation.ThrowIfNullOrReturn(owner, nameof(owner)); _arguments = new OrderedDictionary(StringComparer.Ordinal); + _argumentByInternalName = new Dictionary(); } /// public IGraphArgument AddArgument(IGraphArgument argument) { Validation.ThrowIfNull(argument, nameof(argument)); + _arguments.Add(argument.Name, argument); + _argumentByInternalName.Add(argument.InternalName, argument); + if (argument.ArgumentModifiers.IsSourceParameter() && _sourceArgument == null) _sourceArgument = argument; @@ -125,6 +130,15 @@ public IGraphArgument FindArgument(string argumentName) return null; } + /// + public IGraphArgument FindArgumentByInternalName(string internalName) + { + if (_argumentByInternalName.ContainsKey(internalName)) + return _argumentByInternalName[internalName]; + + return null; + } + /// public IGraphArgument this[string argumentName] => _arguments[argumentName]; diff --git a/src/graphql-aspnet/Schemas/TypeSystem/MethodGraphField.cs b/src/graphql-aspnet/Schemas/TypeSystem/MethodGraphField.cs index 13c0b0666..649d2aac7 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/MethodGraphField.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/MethodGraphField.cs @@ -71,7 +71,6 @@ public MethodGraphField( this.UpdateResolver(resolver, mode); this.Publish = true; - } /// diff --git a/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/FieldContextBuilder.cs b/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/FieldContextBuilder.cs index 211a6667d..9cf59ea53 100644 --- a/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/FieldContextBuilder.cs +++ b/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/FieldContextBuilder.cs @@ -107,11 +107,10 @@ public FieldContextBuilder( this.ResolverMetaData.Setup(x => x.ExpectedReturnType).Returns(metaData.ExpectedReturnType); this.ResolverMetaData.Setup(x => x.Method).Returns(metaData.Method); this.ResolverMetaData.Setup(x => x.IsAsyncField).Returns(metaData.IsAsyncField); - this.ResolverMetaData.Setup(x => x.Name).Returns(metaData.Name); + this.ResolverMetaData.Setup(x => x.InternalName).Returns(metaData.InternalName); this.ResolverMetaData.Setup(x => x.InternalFullName).Returns(metaData.InternalFullName); this.ResolverMetaData.Setup(x => x.InternalName).Returns(metaData.InternalName); - this.ResolverMetaData.Setup(x => x.Route).Returns(metaData.Route); - this.ResolverMetaData.Setup(x => x.Arguments).Returns(metaData.Arguments); + this.ResolverMetaData.Setup(x => x.Parameters).Returns(metaData.Parameters); } /// diff --git a/src/unit-tests/graphql-aspnet-testframework/TestServer.cs b/src/unit-tests/graphql-aspnet-testframework/TestServer.cs index f01ebd6ee..57e7ed9b8 100644 --- a/src/unit-tests/graphql-aspnet-testframework/TestServer.cs +++ b/src/unit-tests/graphql-aspnet-testframework/TestServer.cs @@ -341,14 +341,14 @@ public virtual FieldContextBuilder CreateGraphTypeFieldContextBuilder(str throw new InvalidOperationException($"The target graph type '{graphType.Name}' does not contain a field named '{fieldName}'."); } - var graphMethod = this.CreateInvokableReference(fieldName, typeKind); + var metaData = this.CreateResolverMetadata(fieldName, typeKind); var builder = new FieldContextBuilder( this.ServiceProvider, _userSecurityContext, field, this.Schema, - graphMethod); + metaData); builder.AddSourceData(sourceData); @@ -364,7 +364,7 @@ public virtual FieldContextBuilder CreateGraphTypeFieldContextBuilder(str /// Name of the field. /// The type kind to resolve the field as (only necessary for input object types). /// IGraphMethod. - public virtual IGraphFieldResolverMetaData CreateInvokableReference(string fieldName, TypeKind? typeKind = null) + public virtual IGraphFieldResolverMetaData CreateResolverMetadata(string fieldName, TypeKind? typeKind = null) { var template = GraphQLTemplateHelper.CreateGraphTypeTemplate(typeKind); var fieldContainer = template as IGraphTypeFieldTemplateContainer; @@ -383,13 +383,13 @@ public virtual IGraphFieldResolverMetaData CreateInvokableReference throw new InvalidOperationException($"The provided type '{typeof(TObjectType).FriendlyName()}' does not " + $"contain a field named '{fieldName}'."); } - var method = fieldTemplate.CreateResolverMetaData(); - if (method == null) + var metaData = fieldTemplate.CreateResolverMetaData(); + if (metaData == null) { throw new InvalidOperationException($"The field named '{fieldName}' on the provided type '{typeof(TObjectType).FriendlyName()}' " + $"does not represent an invokable {typeof(IGraphFieldResolverMetaData)}. Operation cannot proceed."); } - return method; + return metaData; } /// @@ -424,6 +424,7 @@ public virtual GraphDirectiveExecutionContext CreateDirectiveExecutionContext x.DirectivePhase).Returns(phase); directiveRequest.Setup(x => x.InvocationContext).Returns(invocationContext.Object); directiveRequest.Setup(x => x.DirectiveTarget).Returns(directiveTarget); + directiveRequest.Setup(x => x.Directive).Returns(targetDirective); invocationContext.Setup(x => x.Location).Returns(location); invocationContext.Setup(x => x.Arguments).Returns(argCollection); diff --git a/src/unit-tests/graphql-aspnet-tests/Controllers/ActionResults/ActionResultTests.cs b/src/unit-tests/graphql-aspnet-tests/Controllers/ActionResults/ActionResultTests.cs index 470cd03f6..c4f6f0ab3 100644 --- a/src/unit-tests/graphql-aspnet-tests/Controllers/ActionResults/ActionResultTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Controllers/ActionResults/ActionResultTests.cs @@ -178,7 +178,7 @@ public async Task RouteNotFound_ViaGraphAction_YieldsNegativeResult() Assert.IsTrue(context.IsCancelled); Assert.AreEqual(1, context.Messages.Count); Assert.AreEqual(Constants.ErrorCodes.INVALID_ROUTE, context.Messages[0].Code); - Assert.IsTrue(context.Messages[0].Message.Contains(action.Name)); + Assert.IsTrue(context.Messages[0].Message.Contains(action.InternalName)); } [Test] diff --git a/src/unit-tests/graphql-aspnet-tests/Logging/ActionMethodModelStateValidatedLogEntryTests.cs b/src/unit-tests/graphql-aspnet-tests/Logging/ActionMethodModelStateValidatedLogEntryTests.cs index aa022046c..bc135115c 100644 --- a/src/unit-tests/graphql-aspnet-tests/Logging/ActionMethodModelStateValidatedLogEntryTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Logging/ActionMethodModelStateValidatedLogEntryTests.cs @@ -55,7 +55,7 @@ private void ValidateModelDictionaryToLogEntry( { Assert.AreEqual(fieldRequest.Id.ToString(), logEntry.PipelineRequestId); Assert.AreEqual(graphMethod.ParentInternalFullName, logEntry.ControllerName); - Assert.AreEqual(graphMethod.Name, logEntry.ActionName); + Assert.AreEqual(graphMethod.InternalName, logEntry.ActionName); Assert.AreEqual(dictionary.IsValid, logEntry.ModelDataIsValid); foreach (var kvp in dictionary) diff --git a/src/unit-tests/graphql-aspnet-tests/Logging/GeneralEventLogEntryPropertyChecks.cs b/src/unit-tests/graphql-aspnet-tests/Logging/GeneralEventLogEntryPropertyChecks.cs index fcb499cac..0b0dd24ff 100644 --- a/src/unit-tests/graphql-aspnet-tests/Logging/GeneralEventLogEntryPropertyChecks.cs +++ b/src/unit-tests/graphql-aspnet-tests/Logging/GeneralEventLogEntryPropertyChecks.cs @@ -409,8 +409,7 @@ public void ActionMethodInvocationStartedLogEntry() Assert.AreEqual(LogEventIds.ControllerInvocationStarted.Id, entry.EventId); Assert.AreEqual(fieldRequest.Id.ToString(), entry.PipelineRequestId); Assert.AreEqual(graphMethod.ParentInternalFullName, entry.ControllerName); - Assert.AreEqual(graphMethod.Name, entry.ActionName); - Assert.AreEqual(graphMethod.Route.Path, entry.FieldPath); + Assert.AreEqual(graphMethod.InternalName, entry.ActionName); Assert.AreEqual(graphMethod.ObjectType.ToString(), entry.SourceObjectType); Assert.AreEqual(graphMethod.IsAsyncField, entry.IsAsync); Assert.IsNotNull(entry.ToString()); @@ -436,8 +435,7 @@ public void ActionMethodInvocationCompletedLogEntry() Assert.AreEqual(LogEventIds.ControllerInvocationCompleted.Id, entry.EventId); Assert.AreEqual(fieldRequest.Id.ToString(), entry.PipelineRequestId); Assert.AreEqual(metaData.ParentInternalFullName, entry.ControllerName); - Assert.AreEqual(metaData.Name, entry.ActionName); - Assert.AreEqual(metaData.Route.Path, entry.FieldPath); + Assert.AreEqual(metaData.InternalName, entry.ActionName); Assert.AreEqual(result.GetType().FriendlyName(true), entry.ResultTypeName); Assert.IsNotNull(entry.ToString()); } @@ -463,7 +461,7 @@ public void ActionMethodInvocationExceptionLogEntry() Assert.AreEqual(LogEventIds.ControllerInvocationException.Id, entry.EventId); Assert.AreEqual(fieldRequest.Id.ToString(), entry.PipelineRequestId); Assert.AreEqual(metaData.ParentInternalFullName, entry.ControllerTypeName); - Assert.AreEqual(metaData.Name, entry.ActionName); + Assert.AreEqual(metaData.InternalName, entry.ActionName); Assert.IsNotNull(entry.ToString()); var exceptionEntry = entry.Exception as ExceptionLogItem; @@ -494,7 +492,7 @@ public void ActionMethodUnhandledExceptionLogEntry() Assert.AreEqual(LogEventIds.ControllerUnhandledException.Id, entry.EventId); Assert.AreEqual(fieldRequest.Id.ToString(), entry.PipelineRequestId); Assert.AreEqual(metaData.ParentInternalFullName, entry.ControllerTypeName); - Assert.AreEqual(metaData.Name, entry.ActionName); + Assert.AreEqual(metaData.InternalName, entry.ActionName); Assert.IsNotNull(entry.ToString()); var exceptionEntry = entry.Exception as ExceptionLogItem; From 49b80f6a27ab11399e25e77385cb1bad48d72dbe Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Mon, 3 Jul 2023 13:41:35 -0700 Subject: [PATCH 21/63] WIP, removed objectType from resolver metadata declarations --- .../Execution/ExecutionArgumentCollection.cs | 2 +- .../Execution/IGraphFieldResolver.cs | 7 ------ .../Execution/IGraphFieldResolverMetaData.cs | 6 ----- .../IGraphFieldResolverParameterMetaData.cs | 11 ++-------- .../Interfaces/Schema/IGraphFieldBase.cs | 5 +++-- .../Resolvers/ExtendedGraphFieldResolver.cs | 3 --- .../Resolvers/FieldResolverMetaData.cs | 22 +++++++++---------- .../FieldResolverParameterMetaData.cs | 9 ++++---- ...tionGraphFieldResolver{TSource,TReturn}.cs | 3 --- .../GraphControllerActionResolver.cs | 3 --- .../Schema_TypeGraphFieldResolver.cs | 3 --- .../Type_EnumValuesGraphFieldResolver.cs | 3 --- .../ObjectMethodGraphFieldResolver.cs | 3 --- .../ObjectPropertyGraphFieldResolver.cs | 3 --- .../TypeTemplates/GraphArgumentTemplate.cs | 1 - .../GraphDirectiveMethodTemplate.cs | 1 - .../MethodGraphFieldTemplateBase.cs | 1 - .../PropertyGraphFieldTemplate.cs | 1 - .../ActionMethodInvocationStartedLogEntry.cs | 6 ++++- .../Fields/Introspection_SchemaField.cs | 2 ++ .../Fields/Introspection_TypeGraphField.cs | 2 ++ .../Fields/Introspection_TypeNameMetaField.cs | 5 ++++- .../Introspection/Introspection_TypeType.cs | 4 ++++ .../Schemas/TypeSystem/MethodGraphField.cs | 14 +++++------- .../FieldContextBuilder.cs | 6 +++-- .../Execution/GeneralQueryExecutionTests2.cs | 2 +- .../GeneralEventLogEntryPropertyChecks.cs | 1 - .../Schemas/GraphSchemaManagerTests.cs | 1 - 28 files changed, 49 insertions(+), 81 deletions(-) diff --git a/src/graphql-aspnet/Execution/ExecutionArgumentCollection.cs b/src/graphql-aspnet/Execution/ExecutionArgumentCollection.cs index 17c05b328..8d61ae430 100644 --- a/src/graphql-aspnet/Execution/ExecutionArgumentCollection.cs +++ b/src/graphql-aspnet/Execution/ExecutionArgumentCollection.cs @@ -144,7 +144,7 @@ public object[] PrepareArguments(IGraphFieldResolverMetaData resolverMetadata) // ensure compatible list types between the internally // tracked data and the target type of the method being invoked - // i.e. convert List => T[] when needed + // e.g. convert List => T[] when needed if (fieldArgument.TypeExpression.IsListOfItems) { var listMangler = new ListMangler(parameter.ExpectedType); diff --git a/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolver.cs b/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolver.cs index db4f1f8a1..b2a6a0e7c 100644 --- a/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolver.cs +++ b/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolver.cs @@ -29,12 +29,5 @@ public interface IGraphFieldResolver /// The cancel token monitoring the execution of a graph request. /// Task<IGraphPipelineResponse>. Task ResolveAsync(FieldResolutionContext context, CancellationToken cancelToken = default); - - /// - /// Gets the concrete type this resolver attempts to create as a during its invocation (the data type it returns). - /// If this resolver may generate a list, this type should represent a single list item. (i.e. 'string' not 'List{string}'). - /// - /// The type of the return. - Type ObjectType { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverMetaData.cs b/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverMetaData.cs index 51eb3c18b..6ea8f2865 100644 --- a/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverMetaData.cs +++ b/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverMetaData.cs @@ -22,12 +22,6 @@ namespace GraphQL.AspNet.Interfaces.Execution /// public interface IGraphFieldResolverMetaData { - /// - /// Gets the singular concrete type that represents the graph type returned by the resolver. - /// - /// The concrete object type that represents the graph type returned by the resolver. - Type ObjectType { get; } - /// /// Gets the type, unwrapped of any tasks, that this graph method should return upon completion. This value /// represents the implementation return type as opposed to the expected graph type represented by . diff --git a/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverParameterMetaData.cs b/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverParameterMetaData.cs index 511f84a4a..1ad385ae9 100644 --- a/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverParameterMetaData.cs +++ b/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverParameterMetaData.cs @@ -15,7 +15,8 @@ namespace GraphQL.AspNet.Interfaces.Execution using GraphQL.AspNet.Schemas.TypeSystem; /// - /// A metadata object that describes a single parameter passed to a resolver for execution. + /// A metadata object containing parsed and computed values related to a single parameter + /// on a C# method that is used a a resolver to a graph field. /// /// /// This metadata object is expressed in terms of the implementation method. That is, .NET @@ -62,13 +63,5 @@ public interface IGraphFieldResolverParameterMetaData /// /// The default value. object DefaultValue { get; } - - /// - /// Gets the concrete type that represents this parameter in a graphql graph. If this - /// parameter is a list this will represent the object type of a singular instance of the - /// item nested within the list. - /// - /// The type of the object that represents this parameter in an object graph. - Type ObjectType { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Schema/IGraphFieldBase.cs b/src/graphql-aspnet/Interfaces/Schema/IGraphFieldBase.cs index d37946ad5..a223a67e6 100644 --- a/src/graphql-aspnet/Interfaces/Schema/IGraphFieldBase.cs +++ b/src/graphql-aspnet/Interfaces/Schema/IGraphFieldBase.cs @@ -31,9 +31,10 @@ public interface IGraphFieldBase : ITypedSchemaItem, ISchemaItem GraphTypeExpression TypeExpression { get; } /// - /// Gets .NET type of the method or property that generated this field as it was declared in code. + /// Gets .NET return type of the method or property that generated this field as it was declared in code. This + /// type may include task wrappers etc. /// - /// The type of the declared return. + /// The .NET declared type returned from this field. public Type DeclaredReturnType { get; } /// diff --git a/src/graphql-aspnet/Internal/Resolvers/ExtendedGraphFieldResolver.cs b/src/graphql-aspnet/Internal/Resolvers/ExtendedGraphFieldResolver.cs index 8c9fdb3fc..f76b17e78 100644 --- a/src/graphql-aspnet/Internal/Resolvers/ExtendedGraphFieldResolver.cs +++ b/src/graphql-aspnet/Internal/Resolvers/ExtendedGraphFieldResolver.cs @@ -45,8 +45,5 @@ public async Task ResolveAsync(FieldResolutionContext context, CancellationToken await _primaryResolver.ResolveAsync(context, cancelToken).ConfigureAwait(false); await _extension.Invoke(context, cancelToken).ConfigureAwait(false); } - - /// - public Type ObjectType => _primaryResolver.ObjectType; } } \ No newline at end of file diff --git a/src/graphql-aspnet/Internal/Resolvers/FieldResolverMetaData.cs b/src/graphql-aspnet/Internal/Resolvers/FieldResolverMetaData.cs index 25b7d7b34..e330f3653 100644 --- a/src/graphql-aspnet/Internal/Resolvers/FieldResolverMetaData.cs +++ b/src/graphql-aspnet/Internal/Resolvers/FieldResolverMetaData.cs @@ -7,20 +7,25 @@ // License: MIT // ************************************************************* +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + namespace GraphQL.AspNet.Internal.Resolvers { using System; - using System.Collections.Generic; - using System.Linq; using System.Reflection; using GraphQL.AspNet.Common; using GraphQL.AspNet.Interfaces.Execution; - using GraphQL.AspNet.Interfaces.Internal; - using GraphQL.AspNet.Schemas.Structural; /// - /// A concrete class that implements . Used by the templating - /// engine to generate invocation info for any method or property. + /// A metadata object containing parsed and computed values related to + /// C# method that is used a a resolver to a graph field. /// internal class FieldResolverMetaData : IGraphFieldResolverMetaData { @@ -28,7 +33,6 @@ public FieldResolverMetaData( MethodInfo method, IGraphFieldResolverParameterMetaDataCollection parameters, Type expectedReturnType, - Type objectType, bool isAsyncField, string internalName, string internalFullName, @@ -38,7 +42,6 @@ public FieldResolverMetaData( { this.Method = Validation.ThrowIfNullOrReturn(method, nameof(method)); - this.ObjectType = Validation.ThrowIfNullOrReturn(objectType, nameof(objectType)); this.ExpectedReturnType = Validation.ThrowIfNullOrReturn(expectedReturnType, nameof(expectedReturnType)); this.IsAsyncField = isAsyncField; @@ -67,9 +70,6 @@ public FieldResolverMetaData( /// public string InternalName { get; } - /// - public Type ObjectType { get; } - /// public IGraphFieldResolverParameterMetaDataCollection Parameters { get; } diff --git a/src/graphql-aspnet/Internal/Resolvers/FieldResolverParameterMetaData.cs b/src/graphql-aspnet/Internal/Resolvers/FieldResolverParameterMetaData.cs index 45c7dc390..bf31d8034 100644 --- a/src/graphql-aspnet/Internal/Resolvers/FieldResolverParameterMetaData.cs +++ b/src/graphql-aspnet/Internal/Resolvers/FieldResolverParameterMetaData.cs @@ -15,11 +15,14 @@ namespace GraphQL.AspNet.Internal.Resolvers using GraphQL.AspNet.Interfaces.Execution; using GraphQL.AspNet.Schemas.TypeSystem; + /// + /// A metadata object containing parsed and computed values related to a single parameter + /// on a C# method that is used a a resolver to a graph field. + /// internal class FieldResolverParameterMetaData : IGraphFieldResolverParameterMetaData { public FieldResolverParameterMetaData( ParameterInfo paramInfo, - Type objectType, string internalName, string internalFullName, GraphArgumentModifiers modifiers, @@ -27,7 +30,6 @@ public FieldResolverParameterMetaData( { this.ParameterInfo = Validation.ThrowIfNullOrReturn(paramInfo, nameof(paramInfo)); this.ExpectedType = this.ParameterInfo.ParameterType; - this.ObjectType = Validation.ThrowIfNullOrReturn(objectType, nameof(objectType)); this.InternalName = Validation.ThrowIfNullWhiteSpaceOrReturn(internalName, nameof(internalName)); this.InternalFullName = Validation.ThrowIfNullWhiteSpaceOrReturn(internalFullName, nameof(internalFullName)); this.DefaultValue = defaultValue; @@ -49,9 +51,6 @@ public FieldResolverParameterMetaData( /// public object DefaultValue { get; } - /// - public Type ObjectType { get; } - /// public Type ExpectedType { get; } } diff --git a/src/graphql-aspnet/Internal/Resolvers/FunctionGraphFieldResolver{TSource,TReturn}.cs b/src/graphql-aspnet/Internal/Resolvers/FunctionGraphFieldResolver{TSource,TReturn}.cs index af07d3efe..dd9167e9c 100644 --- a/src/graphql-aspnet/Internal/Resolvers/FunctionGraphFieldResolver{TSource,TReturn}.cs +++ b/src/graphql-aspnet/Internal/Resolvers/FunctionGraphFieldResolver{TSource,TReturn}.cs @@ -46,8 +46,5 @@ public async Task ResolveAsync(FieldResolutionContext context, CancellationToken var data = await _func(context?.Arguments.SourceData as TSource).ConfigureAwait(false); context.Result = data; } - - /// - public Type ObjectType => typeof(TReturn); } } \ No newline at end of file diff --git a/src/graphql-aspnet/Internal/Resolvers/GraphControllerActionResolver.cs b/src/graphql-aspnet/Internal/Resolvers/GraphControllerActionResolver.cs index df4140fa4..ec28eb7a1 100644 --- a/src/graphql-aspnet/Internal/Resolvers/GraphControllerActionResolver.cs +++ b/src/graphql-aspnet/Internal/Resolvers/GraphControllerActionResolver.cs @@ -74,8 +74,5 @@ public async Task ResolveAsync(FieldResolutionContext context, CancellationToken // in what ever manner is appropriate for the result itself await result.CompleteAsync(context).ConfigureAwait(false); } - - /// - public Type ObjectType => _actionResolverMetaData.ObjectType; } } \ No newline at end of file diff --git a/src/graphql-aspnet/Internal/Resolvers/Introspeection/Schema_TypeGraphFieldResolver.cs b/src/graphql-aspnet/Internal/Resolvers/Introspeection/Schema_TypeGraphFieldResolver.cs index e2259db3c..420ffab32 100644 --- a/src/graphql-aspnet/Internal/Resolvers/Introspeection/Schema_TypeGraphFieldResolver.cs +++ b/src/graphql-aspnet/Internal/Resolvers/Introspeection/Schema_TypeGraphFieldResolver.cs @@ -57,8 +57,5 @@ public Task ResolveAsync(FieldResolutionContext resolutionContext, CancellationT return Task.CompletedTask; } - - /// - public Type ObjectType => typeof(IntrospectedType); } } \ No newline at end of file diff --git a/src/graphql-aspnet/Internal/Resolvers/Introspeection/Type_EnumValuesGraphFieldResolver.cs b/src/graphql-aspnet/Internal/Resolvers/Introspeection/Type_EnumValuesGraphFieldResolver.cs index 77ee80b02..ed7dac066 100644 --- a/src/graphql-aspnet/Internal/Resolvers/Introspeection/Type_EnumValuesGraphFieldResolver.cs +++ b/src/graphql-aspnet/Internal/Resolvers/Introspeection/Type_EnumValuesGraphFieldResolver.cs @@ -51,8 +51,5 @@ public Task ResolveAsync(FieldResolutionContext resolutionContext, CancellationT return Task.CompletedTask; } - - /// - public Type ObjectType => typeof(IntrospectedEnumValue); } } \ No newline at end of file diff --git a/src/graphql-aspnet/Internal/Resolvers/ObjectMethodGraphFieldResolver.cs b/src/graphql-aspnet/Internal/Resolvers/ObjectMethodGraphFieldResolver.cs index c18c9e51a..0c766d905 100644 --- a/src/graphql-aspnet/Internal/Resolvers/ObjectMethodGraphFieldResolver.cs +++ b/src/graphql-aspnet/Internal/Resolvers/ObjectMethodGraphFieldResolver.cs @@ -111,8 +111,5 @@ public virtual async Task ResolveAsync(FieldResolutionContext context, Cancellat ex); } } - - /// - public Type ObjectType => _resolverMetadata.ObjectType; } } \ No newline at end of file diff --git a/src/graphql-aspnet/Internal/Resolvers/ObjectPropertyGraphFieldResolver.cs b/src/graphql-aspnet/Internal/Resolvers/ObjectPropertyGraphFieldResolver.cs index 7b3bcb142..3a8413de6 100644 --- a/src/graphql-aspnet/Internal/Resolvers/ObjectPropertyGraphFieldResolver.cs +++ b/src/graphql-aspnet/Internal/Resolvers/ObjectPropertyGraphFieldResolver.cs @@ -134,8 +134,5 @@ public async Task ResolveAsync(FieldResolutionContext context, CancellationToken ex); } } - - /// - public Type ObjectType => _resolverMetadata.ObjectType; } } \ No newline at end of file diff --git a/src/graphql-aspnet/Internal/TypeTemplates/GraphArgumentTemplate.cs b/src/graphql-aspnet/Internal/TypeTemplates/GraphArgumentTemplate.cs index 3af25c4ea..892ce1bbd 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/GraphArgumentTemplate.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/GraphArgumentTemplate.cs @@ -232,7 +232,6 @@ public IGraphFieldResolverParameterMetaData CreateResolverMetaData() { return new FieldResolverParameterMetaData( this.Parameter, - this.ObjectType, this.InternalName, this.InternalFullName, this.ArgumentModifiers, diff --git a/src/graphql-aspnet/Internal/TypeTemplates/GraphDirectiveMethodTemplate.cs b/src/graphql-aspnet/Internal/TypeTemplates/GraphDirectiveMethodTemplate.cs index 990ee6021..038d1fa30 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/GraphDirectiveMethodTemplate.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/GraphDirectiveMethodTemplate.cs @@ -202,7 +202,6 @@ internal IGraphFieldResolverMetaData CreateResolverMetaData() this.Method, paramSet, this.ExpectedReturnType, - this.ObjectType, this.IsAsyncField, this.InternalName, this.InternalFullName, diff --git a/src/graphql-aspnet/Internal/TypeTemplates/MethodGraphFieldTemplateBase.cs b/src/graphql-aspnet/Internal/TypeTemplates/MethodGraphFieldTemplateBase.cs index 21fb19f08..72c060597 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/MethodGraphFieldTemplateBase.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/MethodGraphFieldTemplateBase.cs @@ -116,7 +116,6 @@ public override IGraphFieldResolverMetaData CreateResolverMetaData() this.Method, paramSet, this.ExpectedReturnType, - this.ObjectType, this.IsAsyncField, this.InternalName, this.InternalFullName, diff --git a/src/graphql-aspnet/Internal/TypeTemplates/PropertyGraphFieldTemplate.cs b/src/graphql-aspnet/Internal/TypeTemplates/PropertyGraphFieldTemplate.cs index 3c9915b46..e3cbefbee 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/PropertyGraphFieldTemplate.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/PropertyGraphFieldTemplate.cs @@ -123,7 +123,6 @@ public override IGraphFieldResolverMetaData CreateResolverMetaData() this.Method, paramSet, this.ExpectedReturnType, - this.ObjectType, this.IsAsyncField, this.InternalName, this.InternalFullName, diff --git a/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodInvocationStartedLogEntry.cs b/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodInvocationStartedLogEntry.cs index 334240715..a466e7532 100644 --- a/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodInvocationStartedLogEntry.cs +++ b/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodInvocationStartedLogEntry.cs @@ -10,6 +10,7 @@ namespace GraphQL.AspNet.Logging.GeneralEvents { using System; + using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Interfaces.Execution; /// @@ -31,7 +32,10 @@ public ActionMethodInvocationStartedLogEntry(IGraphFieldResolverMetaData method, this.PipelineRequestId = request?.Id.ToString(); this.ControllerName = method?.ParentInternalFullName; this.ActionName = method?.InternalName; - this.SourceObjectType = method?.ObjectType?.ToString(); + + if (request is IGraphFieldRequest gfr) + this.SourceObjectType = gfr.InvocationContext?.ExpectedSourceType?.FriendlyName(true); + this.IsAsync = method?.IsAsyncField; _shortControllerName = method?.ParentInternalName; } diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_SchemaField.cs b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_SchemaField.cs index c8e830fd7..aa5247d06 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_SchemaField.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_SchemaField.cs @@ -40,6 +40,8 @@ public Introspection_SchemaField(IntrospectedSchema schema) new GraphTypeExpression(Constants.ReservedNames.SCHEMA_TYPE), FIELD_PATH, nameof(Introspection_SchemaField), + typeof(IntrospectedSchema), + typeof(IntrospectedSchema), resolver: new FunctionGraphFieldResolver((x) => schema.AsCompletedTask())) { this.IntrospectedSchema = Validation.ThrowIfNullOrReturn(schema, nameof(schema)); diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_TypeGraphField.cs b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_TypeGraphField.cs index adb1f0853..cfd9705f8 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_TypeGraphField.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_TypeGraphField.cs @@ -38,6 +38,8 @@ public Introspection_TypeGraphField(IntrospectedSchema schema) new GraphTypeExpression(Constants.ReservedNames.TYPE_TYPE), FIELD_PATH, nameof(Introspection_TypeGraphField), + objectType: typeof(IntrospectedType), + declaredReturnType: typeof(IntrospectedType), mode: FieldResolutionMode.PerSourceItem, resolver: new Schema_TypeGraphFieldResolver(schema)) { diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_TypeNameMetaField.cs b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_TypeNameMetaField.cs index 1ed51e251..0e0377f9a 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_TypeNameMetaField.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_TypeNameMetaField.cs @@ -39,7 +39,10 @@ public Introspection_TypeNameMetaField(string graphTypeName) Constants.ReservedNames.TYPENAME_FIELD, new GraphTypeExpression(Constants.ScalarNames.STRING, MetaGraphTypes.IsNotNull), FIELD_PATH, - nameof(Introspection_TypeNameMetaField)) + nameof(Introspection_TypeNameMetaField), + typeof(string), + typeof(string), + FieldResolutionMode.PerSourceItem) { Validation.ThrowIfNull(graphTypeName, nameof(graphTypeName)); this.UpdateResolver(new FunctionGraphFieldResolver((obj) => graphTypeName.AsCompletedTask()), FieldResolutionMode.PerSourceItem); diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_TypeType.cs b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_TypeType.cs index 175b03085..0afcd06ea 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_TypeType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_TypeType.cs @@ -60,6 +60,8 @@ public Introspection_TypeType() new GraphTypeExpression(Constants.ReservedNames.FIELD_TYPE, MetaGraphTypes.IsList, MetaGraphTypes.IsNotNull), new IntrospectedRoutePath(SchemaItemCollections.Types, this.Name, "fields"), "Introspection_TypeType_Fields", + objectType: typeof(IEnumerable), + declaredReturnType: typeof(IEnumerable), mode: FieldResolutionMode.PerSourceItem, resolver: new Type_TypeGraphFieldResolver()) { @@ -97,6 +99,8 @@ public Introspection_TypeType() new GraphTypeExpression(Constants.ReservedNames.ENUM_VALUE_TYPE, MetaGraphTypes.IsList, MetaGraphTypes.IsNotNull), new IntrospectedRoutePath(SchemaItemCollections.Types, this.Name, Constants.ReservedNames.ENUM_VALUE_TYPE), "Introspection_TypeType_EnumValues", + objectType: typeof(IEnumerable), + declaredReturnType: typeof(IEnumerable), mode: FieldResolutionMode.PerSourceItem, resolver: new Type_EnumValuesGraphFieldResolver()) { diff --git a/src/graphql-aspnet/Schemas/TypeSystem/MethodGraphField.cs b/src/graphql-aspnet/Schemas/TypeSystem/MethodGraphField.cs index 649d2aac7..3bb807437 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/MethodGraphField.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/MethodGraphField.cs @@ -50,8 +50,8 @@ public MethodGraphField( GraphTypeExpression typeExpression, SchemaItemPath route, string declaredMethodName, - Type objectType = null, - Type declaredReturnType = null, + Type objectType, + Type declaredReturnType, FieldResolutionMode mode = FieldResolutionMode.PerSourceItem, IGraphFieldResolver resolver = null, IEnumerable securityPolicies = null, @@ -61,14 +61,15 @@ public MethodGraphField( this.TypeExpression = Validation.ThrowIfNullOrReturn(typeExpression, nameof(typeExpression)); this.Route = Validation.ThrowIfNullOrReturn(route, nameof(route)); this.Arguments = new GraphFieldArgumentCollection(this); - this.ObjectType = objectType; - this.DeclaredReturnType = declaredReturnType; - this.InternalName = declaredMethodName; + this.ObjectType = Validation.ThrowIfNullOrReturn(objectType, nameof(objectType)); + this.DeclaredReturnType = Validation.ThrowIfNullOrReturn(declaredReturnType, nameof(declaredReturnType)); + this.InternalName = Validation.ThrowIfNullWhiteSpaceOrReturn(declaredMethodName, nameof(declaredMethodName)); this.AppliedDirectives = directives?.Clone(this) ?? new AppliedDirectiveCollection(this); this.SecurityGroups = new AppliedSecurityPolicyGroups(securityPolicies); + this.IsLeaf = GraphQLProviders.ScalarProvider.IsLeaf(this.ObjectType); this.UpdateResolver(resolver, mode); this.Publish = true; } @@ -79,9 +80,6 @@ public void UpdateResolver(IGraphFieldResolver newResolver, FieldResolutionMode? this.Resolver = newResolver; if (mode.HasValue) this.Mode = mode.Value; - - var unrwrappedType = GraphValidation.EliminateWrappersFromCoreType(this.Resolver?.ObjectType); - this.IsLeaf = this.Resolver?.ObjectType != null && GraphQLProviders.ScalarProvider.IsLeaf(unrwrappedType); } /// diff --git a/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/FieldContextBuilder.cs b/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/FieldContextBuilder.cs index 9cf59ea53..22c584209 100644 --- a/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/FieldContextBuilder.cs +++ b/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/FieldContextBuilder.cs @@ -72,7 +72,10 @@ public FieldContextBuilder( if (!Validation.IsCastable(metaData.ParentObjectType) && !Validation.IsCastable(metaData.ParentObjectType)) { - expectedInputType = metaData.ObjectType; + if (graphField.Parent is IInterfaceGraphType iif) + expectedInputType = iif.ObjectType; + else if (graphField.Parent is IObjectGraphType ogt) + expectedInputType = ogt.ObjectType; } _mockFieldDocumentPart = new Mock(); @@ -103,7 +106,6 @@ public FieldContextBuilder( this.ResolverMetaData.Setup(x => x.ParentInternalFullName).Returns(metaData.ParentInternalFullName); this.ResolverMetaData.Setup(x => x.ParentInternalName).Returns(metaData.ParentInternalName); this.ResolverMetaData.Setup(x => x.ParentObjectType).Returns(metaData.ParentObjectType); - this.ResolverMetaData.Setup(x => x.ObjectType).Returns(metaData.ObjectType); this.ResolverMetaData.Setup(x => x.ExpectedReturnType).Returns(metaData.ExpectedReturnType); this.ResolverMetaData.Setup(x => x.Method).Returns(metaData.Method); this.ResolverMetaData.Setup(x => x.IsAsyncField).Returns(metaData.IsAsyncField); diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionTests2.cs b/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionTests2.cs index f80d0b7cb..5a2cf77ad 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionTests2.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionTests2.cs @@ -144,7 +144,7 @@ public async Task TypeNameOnAUnionReturn_YieldsResults() .AddQueryText(@"query { retrieveUnion { ... on TwoPropertyObject { - property1 + property1 property2 } __typename diff --git a/src/unit-tests/graphql-aspnet-tests/Logging/GeneralEventLogEntryPropertyChecks.cs b/src/unit-tests/graphql-aspnet-tests/Logging/GeneralEventLogEntryPropertyChecks.cs index 0b0dd24ff..7bef9f034 100644 --- a/src/unit-tests/graphql-aspnet-tests/Logging/GeneralEventLogEntryPropertyChecks.cs +++ b/src/unit-tests/graphql-aspnet-tests/Logging/GeneralEventLogEntryPropertyChecks.cs @@ -410,7 +410,6 @@ public void ActionMethodInvocationStartedLogEntry() Assert.AreEqual(fieldRequest.Id.ToString(), entry.PipelineRequestId); Assert.AreEqual(graphMethod.ParentInternalFullName, entry.ControllerName); Assert.AreEqual(graphMethod.InternalName, entry.ActionName); - Assert.AreEqual(graphMethod.ObjectType.ToString(), entry.SourceObjectType); Assert.AreEqual(graphMethod.IsAsyncField, entry.IsAsync); Assert.IsNotNull(entry.ToString()); } diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GraphSchemaManagerTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GraphSchemaManagerTests.cs index 51d8a0311..b047d91f0 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/GraphSchemaManagerTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GraphSchemaManagerTests.cs @@ -120,7 +120,6 @@ public void AddSingleQueryAction_NestedRouting_EnsureFieldStructure() var actionField = firstFieldType.Fields["path2"]; Assert.IsNotNull(actionField); Assert.IsNotNull(actionField.Resolver as GraphControllerActionResolver); - Assert.AreEqual(typeof(TwoPropertyObjectV2), ((GraphControllerActionResolver)actionField.Resolver).ObjectType); } [Test] From eb860a3861ae640dd845ad9f1315b162f0b88cbe Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Mon, 3 Jul 2023 15:04:56 -0700 Subject: [PATCH 22/63] WIP --- .../Controllers/RuntimeFieldExecutionController.cs | 10 +++++----- .../Internal/Resolvers/FieldResolverMetaData.cs | 9 --------- .../Resolvers/GraphControllerRouteFieldResolver.cs | 3 --- .../Introspeection/Type_TypeGraphFieldResolver.cs | 3 --- 4 files changed, 5 insertions(+), 20 deletions(-) diff --git a/src/graphql-aspnet/Controllers/RuntimeFieldExecutionController.cs b/src/graphql-aspnet/Controllers/RuntimeFieldExecutionController.cs index de4d53097..aa8c365fa 100644 --- a/src/graphql-aspnet/Controllers/RuntimeFieldExecutionController.cs +++ b/src/graphql-aspnet/Controllers/RuntimeFieldExecutionController.cs @@ -21,19 +21,19 @@ namespace GraphQL.AspNet.Controllers internal sealed class RuntimeFieldExecutionController : GraphController { /// - protected override object CreateAndInvokeAction(IGraphFieldResolverMetaData resolver, object[] invocationArguments) + protected override object CreateAndInvokeAction(IGraphFieldResolverMetaData metadata, object[] invocationArguments) { // minimal api resolvers are allowed to be static since there is no // extra context to setup or make available such as 'this.User' etc. - if (resolver.Method.IsStatic) + if (metadata.Method.IsStatic) { - var invoker = InstanceFactory.CreateStaticMethodInvoker(resolver.Method); + var invoker = InstanceFactory.CreateStaticMethodInvoker(metadata.Method); return invoker(invocationArguments); } else { - var invoker = InstanceFactory.CreateInstanceMethodInvoker(resolver.Method); - var instance = InstanceFactory.CreateInstance(resolver.Method.DeclaringType); + var invoker = InstanceFactory.CreateInstanceMethodInvoker(metadata.Method); + var instance = InstanceFactory.CreateInstance(metadata.Method.DeclaringType); return invoker(ref instance, invocationArguments); } } diff --git a/src/graphql-aspnet/Internal/Resolvers/FieldResolverMetaData.cs b/src/graphql-aspnet/Internal/Resolvers/FieldResolverMetaData.cs index e330f3653..cdd4db402 100644 --- a/src/graphql-aspnet/Internal/Resolvers/FieldResolverMetaData.cs +++ b/src/graphql-aspnet/Internal/Resolvers/FieldResolverMetaData.cs @@ -7,15 +7,6 @@ // License: MIT // ************************************************************* -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - namespace GraphQL.AspNet.Internal.Resolvers { using System; diff --git a/src/graphql-aspnet/Internal/Resolvers/GraphControllerRouteFieldResolver.cs b/src/graphql-aspnet/Internal/Resolvers/GraphControllerRouteFieldResolver.cs index c32d61b59..ce76963ed 100644 --- a/src/graphql-aspnet/Internal/Resolvers/GraphControllerRouteFieldResolver.cs +++ b/src/graphql-aspnet/Internal/Resolvers/GraphControllerRouteFieldResolver.cs @@ -43,8 +43,5 @@ public Task ResolveAsync(FieldResolutionContext context, CancellationToken cance context.Result = _dataObject; return Task.CompletedTask; } - - /// - public Type ObjectType => typeof(object); } } \ No newline at end of file diff --git a/src/graphql-aspnet/Internal/Resolvers/Introspeection/Type_TypeGraphFieldResolver.cs b/src/graphql-aspnet/Internal/Resolvers/Introspeection/Type_TypeGraphFieldResolver.cs index 38c03f13a..73748508a 100644 --- a/src/graphql-aspnet/Internal/Resolvers/Introspeection/Type_TypeGraphFieldResolver.cs +++ b/src/graphql-aspnet/Internal/Resolvers/Introspeection/Type_TypeGraphFieldResolver.cs @@ -51,8 +51,5 @@ public Task ResolveAsync(FieldResolutionContext context, CancellationToken cance return Task.CompletedTask; } - - /// - public Type ObjectType => typeof(IntrospectedField); } } \ No newline at end of file From 16dff9bc8444c4ab9e0fcd3c6e07b9c0b3ee6e47 Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Mon, 3 Jul 2023 17:57:42 -0700 Subject: [PATCH 23/63] WIP, removed argument modifiers from graphargument Also: * decoupled directive resolver methods from templates * removed non-schema arguments from the schema data (only exists in resovler meta data) --- .../starwars-common/starwars-common.csproj | 2 +- .../SubscriptionMethodGraphField.cs | 11 +-- .../graphql-aspnet-subscriptions.csproj | 8 -- .../InputModel/ModelStateGenerator.cs | 7 +- .../Engine/TypeMakers/DirectiveMaker.cs | 9 +- .../Engine/TypeMakers/GraphArgumentMaker.cs | 1 - .../Engine/TypeMakers/GraphFieldMaker.cs | 9 +- .../Execution/ExecutionArgumentCollection.cs | 84 +++++++++++-------- .../Execution/ExecutionArgumentGenerator.cs | 29 +++---- .../InputArguments/ArgumentGenerator.cs | 3 +- ...MustBeSuppliedOrHaveDefaultValueOnField.cs | 6 -- ...BeSuppliedOrHaveDefaultValueOnDirective.cs | 6 -- .../Execution/IGraphDirectiveResolver.cs | 10 +++ .../Execution/IGraphFieldResolver.cs | 9 +- .../Execution/IGraphFieldResolverMetaData.cs | 3 +- ...ieldResolverParameterMetaDataCollection.cs | 16 +++- .../Internal/IGraphArgumentTemplate.cs | 4 + .../Internal/IGraphFieldTemplate.cs | 5 ++ .../Interfaces/Schema/IGraphArgument.cs | 7 -- .../Schema/IGraphArgumentCollection.cs | 6 -- .../Interfaces/Schema/ITypedSchemaItem.cs | 2 +- .../Resolvers/ExtendedGraphFieldResolver.cs | 3 + .../Resolvers/FieldResolverMetaData.cs | 14 ++++ .../FieldResolverParameterMetaData.cs | 10 +++ ...ieldResolverParameterMetaDataCollection.cs | 24 +++++- ...tionGraphFieldResolver{TSource,TReturn}.cs | 5 ++ .../GraphControllerActionResolver.cs | 11 +-- .../GraphControllerRouteFieldResolver.cs | 5 ++ .../Resolvers/GraphDirectiveActionResolver.cs | 29 ++++--- .../Resolvers/InputObjectValueResolver.cs | 2 +- .../InternalFieldResolverMetaData.cs | 54 ++++++++++++ .../Schema_TypeGraphFieldResolver.cs | 5 ++ .../Type_EnumValuesGraphFieldResolver.cs | 4 + .../Type_TypeGraphFieldResolver.cs | 3 + .../ObjectMethodGraphFieldResolver.cs | 20 +++-- .../ObjectPropertyGraphFieldResolver.cs | 27 +++--- .../TypeTemplates/GraphArgumentTemplate.cs | 16 +++- .../GraphDirectiveMethodTemplate.cs | 16 ++-- .../GraphDirectiveMethodTemplateContainer.cs | 16 ++++ .../TypeTemplates/GraphDirectiveTemplate.cs | 3 +- .../MethodGraphFieldTemplateBase.cs | 9 +- .../PropertyGraphFieldTemplate.cs | 10 ++- .../ExecutionDirectiveAppliedLogEntry.cs | 2 +- .../TypeSystemDirectiveAppliedLogEntry.cs | 2 +- .../ProcessChildFieldsMiddleware.cs | 2 +- .../BaseSchemaItemValidator.cs | 3 + .../GraphArgumentValidator.cs | 4 +- .../Schemas/SchemaLanguageGenerator.cs | 4 +- .../GraphFieldArgumentCollection.cs | 25 ++---- .../Schemas/TypeSystem/Directive.cs | 4 +- .../Schemas/TypeSystem/EnumGraphType.cs | 4 +- .../TypeSystem/GraphArgumentModifiers.cs | 6 +- .../GraphArgumentModifiersExtensions.cs | 11 +++ .../Schemas/TypeSystem/GraphFieldArgument.cs | 17 ++-- .../Schemas/TypeSystem/GraphOperation.cs | 2 +- .../Schemas/TypeSystem/InputGraphField.cs | 4 +- .../TypeSystem/InputObjectGraphType.cs | 4 +- .../Schemas/TypeSystem/InterfaceGraphType.cs | 4 +- .../BaseIntrospectionObjectType.cs | 2 +- .../Model/IntrospectedDirective.cs | 2 +- .../Introspection/Model/IntrospectedField.cs | 4 +- .../Schemas/TypeSystem/MethodGraphField.cs | 10 +-- .../Schemas/TypeSystem/ObjectGraphType.cs | 4 +- .../Schemas/TypeSystem/PropertyGraphField.cs | 2 +- .../TypeSystem/Scalars/ScalarGraphTypeBase.cs | 4 +- .../Schemas/TypeSystem/VirtualGraphField.cs | 4 +- .../TypeSystem/VirtualGraphFieldArgument.cs | 18 ++-- .../TypeSystem/VirtualObjectGraphType.cs | 2 +- src/graphql-aspnet/graphql-aspnet.csproj | 9 -- src/library-common.props | 20 +---- .../GraphModelStateDictionaryTests.cs | 1 - .../ScalarTestBase.cs | 4 +- .../TypeMakers/FieldMaker_InputFieldTests.cs | 16 ++-- .../FieldMaker_StandardFieldTests.cs | 1 - .../Execution/GeneralQueryExecutionTests.cs | 2 +- .../ToUpperWrapperResolver.cs | 4 +- .../Templating/ArgumentTemplateTests.cs | 1 + ...nMethodModelStateValidatedLogEntryTests.cs | 1 - .../GeneralEventLogEntryPropertyChecks.cs | 8 +- .../Schemas/GraphFieldArgumentCloningTests.cs | 4 +- .../Schemas/GraphFieldCloningTests.cs | 6 +- 81 files changed, 449 insertions(+), 301 deletions(-) create mode 100644 src/graphql-aspnet/Internal/Resolvers/InternalFieldResolverMetaData.cs diff --git a/src/ancillary-projects/starwars/starwars-common/starwars-common.csproj b/src/ancillary-projects/starwars/starwars-common/starwars-common.csproj index 4a9c2fff7..23f7d4083 100644 --- a/src/ancillary-projects/starwars/starwars-common/starwars-common.csproj +++ b/src/ancillary-projects/starwars/starwars-common/starwars-common.csproj @@ -1,7 +1,7 @@  - net7.0;net6.0;netstandard2.0; + net7.0;net6.0; latest $(NoWarn);1701;1702;1705;1591;NU1603 GraphQL.AspNet.StarwarsAPI.Common diff --git a/src/graphql-aspnet-subscriptions/Schemas/TypeSystem/SubscriptionMethodGraphField.cs b/src/graphql-aspnet-subscriptions/Schemas/TypeSystem/SubscriptionMethodGraphField.cs index bd26e60e5..d4d10764c 100644 --- a/src/graphql-aspnet-subscriptions/Schemas/TypeSystem/SubscriptionMethodGraphField.cs +++ b/src/graphql-aspnet-subscriptions/Schemas/TypeSystem/SubscriptionMethodGraphField.cs @@ -27,19 +27,20 @@ public class SubscriptionMethodGraphField : MethodGraphField, ISubscriptionGraph /// Name of the field in the type declaration.. /// The meta data about how this type field is implemented. /// The formal route to this field in the object graph. - /// Name of the declared method. + /// The fully qualified name of the method this field respresents, as it was declared + /// in C# code. /// The .NET type of the item or items that represent the graph type returned by this field. /// The .NET type as it was declared on the property which generated this field.. /// The execution mode of this field. /// The resolver. - /// The security policies. + /// The security policies applied to this field. /// Alterante name of the event that has been assigned to this field. /// The directives to be applied to this field when its added to a schema. public SubscriptionMethodGraphField( string fieldName, GraphTypeExpression typeExpression, SchemaItemPath route, - string declaredMethodName, + string internalFullName, Type objectType = null, Type declaredReturnType = null, Execution.FieldResolutionMode mode = Execution.FieldResolutionMode.PerSourceItem, @@ -47,7 +48,7 @@ public SubscriptionMethodGraphField( IEnumerable securityPolicies = null, string eventName = null, IAppliedDirectiveCollection directives = null) - : base(fieldName, typeExpression, route, declaredMethodName, objectType, declaredReturnType, mode, resolver, securityPolicies, directives) + : base(fieldName, typeExpression, route, internalFullName, objectType, declaredReturnType, mode, resolver, securityPolicies, directives) { this.EventName = eventName; } @@ -59,7 +60,7 @@ protected override MethodGraphField CreateNewInstance(IGraphType parent) this.Name, this.TypeExpression.Clone(), parent.Route.CreateChild(this.Name), - this.InternalName, + this.InternalFullName, this.ObjectType, this.DeclaredReturnType, this.Mode, diff --git a/src/graphql-aspnet-subscriptions/graphql-aspnet-subscriptions.csproj b/src/graphql-aspnet-subscriptions/graphql-aspnet-subscriptions.csproj index c19029b6f..ab7590b5f 100644 --- a/src/graphql-aspnet-subscriptions/graphql-aspnet-subscriptions.csproj +++ b/src/graphql-aspnet-subscriptions/graphql-aspnet-subscriptions.csproj @@ -21,12 +21,4 @@ - - - - - - - - \ No newline at end of file diff --git a/src/graphql-aspnet/Controllers/InputModel/ModelStateGenerator.cs b/src/graphql-aspnet/Controllers/InputModel/ModelStateGenerator.cs index dd26064d8..b7e670653 100644 --- a/src/graphql-aspnet/Controllers/InputModel/ModelStateGenerator.cs +++ b/src/graphql-aspnet/Controllers/InputModel/ModelStateGenerator.cs @@ -77,15 +77,10 @@ public InputModelStateDictionary CreateStateDictionary(IEnumerable - /// Processes an input object's attribute validation items. - /// - /// The input. - /// InputModelStateEntry. private InputModelStateEntry ValidateSingleArgument(ExecutionArgument input) { var entry = new InputModelStateEntry(input); - if (input.Value == null || input.Argument.ArgumentModifiers.IsSourceParameter()) + if (input.Value == null) { entry.ValidationState = InputModelValidationState.Skipped; return entry; diff --git a/src/graphql-aspnet/Engine/TypeMakers/DirectiveMaker.cs b/src/graphql-aspnet/Engine/TypeMakers/DirectiveMaker.cs index 0dff0a81b..86981e3e8 100644 --- a/src/graphql-aspnet/Engine/TypeMakers/DirectiveMaker.cs +++ b/src/graphql-aspnet/Engine/TypeMakers/DirectiveMaker.cs @@ -72,10 +72,13 @@ public GraphTypeCreationResult CreateGraphType(Type concreteType) var argMaker = new GraphArgumentMaker(_schema); foreach (var argTemplate in template.Arguments) { - var argumentResult = argMaker.CreateArgument(directive, argTemplate); - directive.Arguments.AddArgument(argumentResult.Argument); + if (argTemplate.ArgumentModifiers.IsPartOfTheSchema()) + { + var argumentResult = argMaker.CreateArgument(directive, argTemplate); + directive.Arguments.AddArgument(argumentResult.Argument); - result.MergeDependents(argumentResult); + result.MergeDependents(argumentResult); + } } result.GraphType = directive; diff --git a/src/graphql-aspnet/Engine/TypeMakers/GraphArgumentMaker.cs b/src/graphql-aspnet/Engine/TypeMakers/GraphArgumentMaker.cs index e916d068b..042932eee 100644 --- a/src/graphql-aspnet/Engine/TypeMakers/GraphArgumentMaker.cs +++ b/src/graphql-aspnet/Engine/TypeMakers/GraphArgumentMaker.cs @@ -44,7 +44,6 @@ public GraphArgumentCreationResult CreateArgument(ISchemaItem owner, IGraphArgum formatter.FormatFieldName(template.Name), template.TypeExpression.CloneTo(formatter.FormatGraphTypeName(template.TypeExpression.TypeName)), template.Route, - template.ArgumentModifiers, template.DeclaredArgumentName, template.InternalName, template.ObjectType, diff --git a/src/graphql-aspnet/Engine/TypeMakers/GraphFieldMaker.cs b/src/graphql-aspnet/Engine/TypeMakers/GraphFieldMaker.cs index 65e62092b..81eb05a95 100644 --- a/src/graphql-aspnet/Engine/TypeMakers/GraphFieldMaker.cs +++ b/src/graphql-aspnet/Engine/TypeMakers/GraphFieldMaker.cs @@ -73,10 +73,13 @@ public virtual GraphFieldCreationResult CreateField(IGraphFieldTemp foreach (var argTemplate in template.Arguments) { - var argumentResult = argumentMaker.CreateArgument(field, argTemplate); - field.Arguments.AddArgument(argumentResult.Argument); + if (argTemplate.ArgumentModifiers.IsPartOfTheSchema()) + { + var argumentResult = argumentMaker.CreateArgument(field, argTemplate); + field.Arguments.AddArgument(argumentResult.Argument); - result.MergeDependents(argumentResult); + result.MergeDependents(argumentResult); + } } } diff --git a/src/graphql-aspnet/Execution/ExecutionArgumentCollection.cs b/src/graphql-aspnet/Execution/ExecutionArgumentCollection.cs index 8d61ae430..9e7052998 100644 --- a/src/graphql-aspnet/Execution/ExecutionArgumentCollection.cs +++ b/src/graphql-aspnet/Execution/ExecutionArgumentCollection.cs @@ -79,7 +79,6 @@ public IExecutionArgumentCollection ForContext(GraphFieldExecutionContext fieldC return new ExecutionArgumentCollection(_arguments, fieldContext); } - /// public IExecutionArgumentCollection ForContext(GraphDirectiveExecutionContext directiveContext) { @@ -114,42 +113,48 @@ public object[] PrepareArguments(IGraphFieldResolverMetaData resolverMetadata) for (var i = 0; i < resolverMetadata.Parameters.Count; i++) { var parameter = resolverMetadata.Parameters[i]; - object passedValue = this.ResolveParameterFromMetadata(parameter); - - var fieldArgument = _fieldContext? - .Request - .Field - .Arguments - .FindArgumentByInternalName(parameter.InternalName); - - fieldArgument = fieldArgument ?? - _directiveContext? - .Request - .Directive - .Arguments - .FindArgumentByInternalName(parameter.InternalName); - if (fieldArgument == null) - throw new GraphExecutionException($"Argument '{parameter.InternalName}' was not found on its expected parent."); - - if (passedValue == null && !fieldArgument.TypeExpression.IsNullable) - { - // technically shouldn't be throwable given the validation routines - // but captured here as a saftey net for users - // doing custom extensions or implementations - throw new GraphExecutionException( - $"The parameter '{parameter.InternalName}' for field '{_fieldContext?.Request?.Field?.Route.Path}' could not be resolved from the query document " + - "or variable collection and no default value was found."); - } + object passedValue = this.ResolveParameterFromMetadata(parameter); - // ensure compatible list types between the internally - // tracked data and the target type of the method being invoked - // e.g. convert List => T[] when needed - if (fieldArgument.TypeExpression.IsListOfItems) + if (parameter.ArgumentModifiers.IsPartOfTheSchema()) { - var listMangler = new ListMangler(parameter.ExpectedType); - var result = listMangler.Convert(passedValue); - passedValue = result.Data; + // additional checks and coersion if this the value is + // being supplied from a query + var graphArgument = _fieldContext? + .Request + .Field + .Arguments + .FindArgumentByInternalName(parameter.InternalName); + + graphArgument = graphArgument ?? + _directiveContext? + .Request + .Directive + .Arguments + .FindArgumentByInternalName(parameter.InternalName); + + if (graphArgument == null) + throw new GraphExecutionException($"Argument '{parameter.InternalName}' was not found on its expected parent."); + + if (passedValue == null && !graphArgument.TypeExpression.IsNullable) + { + // technically shouldn't be throwable given the validation routines + // but captured here as a saftey net for users + // doing custom extensions or implementations + throw new GraphExecutionException( + $"The parameter '{parameter.InternalName}' for field '{_fieldContext?.Request?.Field?.Route.Path}' could not be resolved from the query document " + + "or variable collection and no default value was found."); + } + + // ensure compatible list types between the internally + // tracked data and the target type of the method being invoked + // e.g. convert List => T[] when needed + if (graphArgument.TypeExpression.IsListOfItems) + { + var listMangler = new ListMangler(parameter.ExpectedType); + var result = listMangler.Convert(passedValue); + passedValue = result.Data; + } } preparedParams.Add(passedValue); @@ -169,6 +174,17 @@ private object ResolveParameterFromMetadata(IGraphFieldResolverParameterMetaData if (argDefinition.ArgumentModifiers.IsCancellationToken()) return _fieldContext?.CancellationToken ?? default; + if (argDefinition.ArgumentModifiers.IsInjected()) + { + if (_fieldContext != null) + return _fieldContext.ServiceProvider.GetService(argDefinition.ExpectedType); + + if (_directiveContext != null) + return _directiveContext.ServiceProvider.GetService(argDefinition.ExpectedType); + + return null; + } + if (this.ContainsKey(argDefinition.InternalName)) return this[argDefinition.InternalName].Value; diff --git a/src/graphql-aspnet/Execution/ExecutionArgumentGenerator.cs b/src/graphql-aspnet/Execution/ExecutionArgumentGenerator.cs index 6d6ef6735..8c336efd5 100644 --- a/src/graphql-aspnet/Execution/ExecutionArgumentGenerator.cs +++ b/src/graphql-aspnet/Execution/ExecutionArgumentGenerator.cs @@ -54,25 +54,20 @@ public static bool TryConvert( var argDefinition = arg.Argument; var resolvedValue = arg.Value.Resolve(variableData); - // no schema arguments are internally controlled - // the resolved value is the value we want - if (argDefinition.ArgumentModifiers.IsPartOfTheSchema()) + // its possible for a non-nullable variable to receive a + // null value due to a variable supplying null + // trap it and fail out the execution if so + // see: https://spec.graphql.org/October2021/#sel-GALbLHNCCBCGIp9O + if (resolvedValue == null && argDefinition.TypeExpression.IsNonNullable) { - // its possible for a non-nullable variable to receive a - // null value due to a variable supplying null - // trap it and fail out the execution if so - // see: https://spec.graphql.org/October2021/#sel-GALbLHNCCBCGIp9O - if (resolvedValue == null && argDefinition.TypeExpression.IsNonNullable) - { - messages.Critical( - $"The value supplied to argument '{argDefinition.Name}' was but its expected type expression " + - $"is {argDefinition.TypeExpression}.", - Constants.ErrorCodes.INVALID_ARGUMENT_VALUE, - arg.Origin); + messages.Critical( + $"The value supplied to argument '{argDefinition.Name}' was but its expected type expression " + + $"is {argDefinition.TypeExpression}.", + Constants.ErrorCodes.INVALID_ARGUMENT_VALUE, + arg.Origin); - successful = false; - continue; - } + successful = false; + continue; } collection.Add(new ExecutionArgument(arg.Argument, resolvedValue)); diff --git a/src/graphql-aspnet/Execution/QueryPlans/InputArguments/ArgumentGenerator.cs b/src/graphql-aspnet/Execution/QueryPlans/InputArguments/ArgumentGenerator.cs index 8066b8866..147b6e073 100644 --- a/src/graphql-aspnet/Execution/QueryPlans/InputArguments/ArgumentGenerator.cs +++ b/src/graphql-aspnet/Execution/QueryPlans/InputArguments/ArgumentGenerator.cs @@ -55,8 +55,7 @@ public ArgumentGenerationResult CreateInputArgument( if (!suppliedArgumentData.ContainsKey(argumentDefinition.Name)) { - if (argumentDefinition.IsRequired - && argumentDefinition.ArgumentModifiers.IsPartOfTheSchema()) + if (argumentDefinition.IsRequired) { // this should be an impossible scenario due to validation middleware // However, the pipeline can be changed by the developer so we must diff --git a/src/graphql-aspnet/Execution/RulesEngine/RuleSets/DocumentValidation/FieldSelectionSteps/Rule_5_4_2_1_RequiredArgumentMustBeSuppliedOrHaveDefaultValueOnField.cs b/src/graphql-aspnet/Execution/RulesEngine/RuleSets/DocumentValidation/FieldSelectionSteps/Rule_5_4_2_1_RequiredArgumentMustBeSuppliedOrHaveDefaultValueOnField.cs index 442ceb536..f5b9ed001 100644 --- a/src/graphql-aspnet/Execution/RulesEngine/RuleSets/DocumentValidation/FieldSelectionSteps/Rule_5_4_2_1_RequiredArgumentMustBeSuppliedOrHaveDefaultValueOnField.cs +++ b/src/graphql-aspnet/Execution/RulesEngine/RuleSets/DocumentValidation/FieldSelectionSteps/Rule_5_4_2_1_RequiredArgumentMustBeSuppliedOrHaveDefaultValueOnField.cs @@ -32,12 +32,6 @@ public override bool Execute(DocumentValidationContext context) var suppliedArguments = fieldSelection.Arguments; foreach (var argument in fieldSelection.Field.Arguments) { - // any argument flaged as being a source input (such as for type extensions) - // or internal (such as subscription event sources) - // and can be skipped when validating query document - if (argument.ArgumentModifiers.IsNotPartOfTheSchema()) - continue; - if (argument.IsRequired && !suppliedArguments.ContainsKey(argument.Name.AsMemory())) { diff --git a/src/graphql-aspnet/Execution/RulesEngine/RuleSets/DocumentValidation/QueryDirectiveSteps/Rule_5_4_2_1_RequiredArgumentMustBeSuppliedOrHaveDefaultValueOnDirective.cs b/src/graphql-aspnet/Execution/RulesEngine/RuleSets/DocumentValidation/QueryDirectiveSteps/Rule_5_4_2_1_RequiredArgumentMustBeSuppliedOrHaveDefaultValueOnDirective.cs index 8110f8a23..17cd1ad4b 100644 --- a/src/graphql-aspnet/Execution/RulesEngine/RuleSets/DocumentValidation/QueryDirectiveSteps/Rule_5_4_2_1_RequiredArgumentMustBeSuppliedOrHaveDefaultValueOnDirective.cs +++ b/src/graphql-aspnet/Execution/RulesEngine/RuleSets/DocumentValidation/QueryDirectiveSteps/Rule_5_4_2_1_RequiredArgumentMustBeSuppliedOrHaveDefaultValueOnDirective.cs @@ -37,12 +37,6 @@ public override bool Execute(DocumentValidationContext context) // inspect all declared arguments from the schema foreach (var argument in directive.Arguments) { - // any argument flaged as being a source input (such as for type extensions) - // or internal (such as subscription event sources) - // and can be skipped when validating query document - if (argument.ArgumentModifiers.IsNotPartOfTheSchema()) - continue; - if (argument.IsRequired && !suppliedArgs.ContainsKey(argument.Name.AsMemory())) { this.ValidationError( diff --git a/src/graphql-aspnet/Interfaces/Execution/IGraphDirectiveResolver.cs b/src/graphql-aspnet/Interfaces/Execution/IGraphDirectiveResolver.cs index 9f5ad4bec..88b1c78fb 100644 --- a/src/graphql-aspnet/Interfaces/Execution/IGraphDirectiveResolver.cs +++ b/src/graphql-aspnet/Interfaces/Execution/IGraphDirectiveResolver.cs @@ -9,9 +9,11 @@ namespace GraphQL.AspNet.Interfaces.Execution { + using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using GraphQL.AspNet.Execution.Contexts; + using GraphQL.AspNet.Schemas.TypeSystem; /// /// A resolver that can process requests to invoke a directive and produce a result. @@ -26,5 +28,13 @@ public interface IGraphDirectiveResolver /// The cancel token monitoring the execution of a graph request. /// Task. Task ResolveAsync(DirectiveResolutionContext directiveRequest, CancellationToken cancelToken = default); + + /// + /// Gets the metadata set that describes this instance's implementation in the source code. The resolver will + /// use this data to properly instantiate and invoke the configured object methods, Func, dynamic delegates or properties + /// as appropriate. + /// + /// The resolver's metadata collection. + IReadOnlyDictionary MetaData { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolver.cs b/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolver.cs index b2a6a0e7c..aeb381b27 100644 --- a/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolver.cs +++ b/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolver.cs @@ -9,7 +9,6 @@ namespace GraphQL.AspNet.Interfaces.Execution { - using System; using System.Threading; using System.Threading.Tasks; using GraphQL.AspNet.Execution.Contexts; @@ -29,5 +28,13 @@ public interface IGraphFieldResolver /// The cancel token monitoring the execution of a graph request. /// Task<IGraphPipelineResponse>. Task ResolveAsync(FieldResolutionContext context, CancellationToken cancelToken = default); + + /// + /// Gets the metadata that describes this instances implementation in the source code. The resolver will + /// use this data to properly instantiate and invoke the configured object methods, Func, dynamic delegates or properties + /// as appropriate. + /// + /// The resolver's metadata collection. + IGraphFieldResolverMetaData MetaData { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverMetaData.cs b/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverMetaData.cs index 6ea8f2865..4eba0a0a6 100644 --- a/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverMetaData.cs +++ b/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverMetaData.cs @@ -24,7 +24,8 @@ public interface IGraphFieldResolverMetaData { /// /// Gets the type, unwrapped of any tasks, that this graph method should return upon completion. This value - /// represents the implementation return type as opposed to the expected graph type represented by . + /// represents the implementation return type that is needed by the runtime to be success. It may differ from the + /// declared return type of in the case of returning interfaces. /// /// The expected type of data returned by this method. Type ExpectedReturnType { get; } diff --git a/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverParameterMetaDataCollection.cs b/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverParameterMetaDataCollection.cs index c9ac40c95..1dbbbd060 100644 --- a/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverParameterMetaDataCollection.cs +++ b/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverParameterMetaDataCollection.cs @@ -10,13 +10,20 @@ namespace GraphQL.AspNet.Interfaces.Execution { using System.Collections.Generic; - using System.Reflection; /// /// A set of metadata items for the parameters of a given resolver. /// public interface IGraphFieldResolverParameterMetaDataCollection : IReadOnlyList { + /// + /// Attempts to find a parameter by its declared name in source code. This name is case sensitive. + /// If not found, null is returned. + /// + /// Name of the parameter as it exists in source code. + /// IGraphFieldResolverParameterMetaData. + IGraphFieldResolverParameterMetaData FindByName(string parameterName); + /// /// Gets the with the specified parameter name. This /// name is case sensitive and should match the parameter declaration in the source code. @@ -24,5 +31,12 @@ public interface IGraphFieldResolverParameterMetaDataCollection : IReadOnlyList< /// Name of the parameter as it exists in source code. /// IGraphFieldResolverParameterMetaData. IGraphFieldResolverParameterMetaData this[string parameterName] { get; } + + /// + /// Gets the parameter that is to be filled with the value that is supplying source data for the + /// field that will be resolved. (e.g. the result of the nearest ancestor in the query. + /// + /// The source parameter metadata item. + IGraphFieldResolverParameterMetaData SourceParameter { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Internal/IGraphArgumentTemplate.cs b/src/graphql-aspnet/Interfaces/Internal/IGraphArgumentTemplate.cs index 78ee7a346..424aa6ef9 100644 --- a/src/graphql-aspnet/Interfaces/Internal/IGraphArgumentTemplate.cs +++ b/src/graphql-aspnet/Interfaces/Internal/IGraphArgumentTemplate.cs @@ -19,6 +19,10 @@ namespace GraphQL.AspNet.Interfaces.Internal /// public interface IGraphArgumentTemplate : ISchemaItemTemplate { + /// + /// Creates a metadata object representing the parameter parsed by this template. + /// + /// IGraphFieldResolverParameterMetaData. IGraphFieldResolverParameterMetaData CreateResolverMetaData(); /// diff --git a/src/graphql-aspnet/Interfaces/Internal/IGraphFieldTemplate.cs b/src/graphql-aspnet/Interfaces/Internal/IGraphFieldTemplate.cs index 9fb8f68c0..736c000fa 100644 --- a/src/graphql-aspnet/Interfaces/Internal/IGraphFieldTemplate.cs +++ b/src/graphql-aspnet/Interfaces/Internal/IGraphFieldTemplate.cs @@ -27,6 +27,11 @@ public interface IGraphFieldTemplate : IGraphFieldTemplateBase, ISecureItem /// IGraphFieldResolver. IGraphFieldResolver CreateResolver(); + /// + /// Creates the metadata object that describes the resolver that would be invoked at runtime + /// to fulfil a request the field. + /// + /// IGraphFieldResolverMetaData. IGraphFieldResolverMetaData CreateResolverMetaData(); /// diff --git a/src/graphql-aspnet/Interfaces/Schema/IGraphArgument.cs b/src/graphql-aspnet/Interfaces/Schema/IGraphArgument.cs index 9a12c3b96..9309e2e10 100644 --- a/src/graphql-aspnet/Interfaces/Schema/IGraphArgument.cs +++ b/src/graphql-aspnet/Interfaces/Schema/IGraphArgument.cs @@ -10,7 +10,6 @@ namespace GraphQL.AspNet.Interfaces.Schema { using GraphQL.AspNet.Schemas; - using GraphQL.AspNet.Schemas.TypeSystem; /// /// An argument/input value that can be applied to a field. @@ -24,12 +23,6 @@ public interface IGraphArgument : ITypedSchemaItem, IDefaultValueSchemaItem, ISc /// IGraphField. IGraphArgument Clone(ISchemaItem parent); - /// - /// Gets the argument modifiers that modify how this argument is interpreted by the runtime. - /// - /// The argument modifiers. - GraphArgumentModifiers ArgumentModifiers { get; } - /// /// Gets the type expression that represents the data of this argument (i.e. the '[SomeType!]' /// declaration used in schema definition language.) diff --git a/src/graphql-aspnet/Interfaces/Schema/IGraphArgumentCollection.cs b/src/graphql-aspnet/Interfaces/Schema/IGraphArgumentCollection.cs index 9eaced09f..bb03714d6 100644 --- a/src/graphql-aspnet/Interfaces/Schema/IGraphArgumentCollection.cs +++ b/src/graphql-aspnet/Interfaces/Schema/IGraphArgumentCollection.cs @@ -102,11 +102,5 @@ IGraphArgument AddArgument( /// /// The count. int Count { get; } - - /// - /// Gets the singular argument that is to recieve source data for the field resolution. - /// - /// The source data argument. - IGraphArgument SourceDataArgument { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Schema/ITypedSchemaItem.cs b/src/graphql-aspnet/Interfaces/Schema/ITypedSchemaItem.cs index f6e1e5d2c..f399d2832 100644 --- a/src/graphql-aspnet/Interfaces/Schema/ITypedSchemaItem.cs +++ b/src/graphql-aspnet/Interfaces/Schema/ITypedSchemaItem.cs @@ -34,6 +34,6 @@ public interface ITypedSchemaItem : ISchemaItem /// Object Property: MyProject.Widget.Name
. /// /// The fully qualiified, internal name of this schema item. - string InternalName { get; } + string InternalFullName { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Internal/Resolvers/ExtendedGraphFieldResolver.cs b/src/graphql-aspnet/Internal/Resolvers/ExtendedGraphFieldResolver.cs index f76b17e78..2471e6b98 100644 --- a/src/graphql-aspnet/Internal/Resolvers/ExtendedGraphFieldResolver.cs +++ b/src/graphql-aspnet/Internal/Resolvers/ExtendedGraphFieldResolver.cs @@ -45,5 +45,8 @@ public async Task ResolveAsync(FieldResolutionContext context, CancellationToken await _primaryResolver.ResolveAsync(context, cancelToken).ConfigureAwait(false); await _extension.Invoke(context, cancelToken).ConfigureAwait(false); } + + /// + public IGraphFieldResolverMetaData MetaData => _primaryResolver.MetaData; } } \ No newline at end of file diff --git a/src/graphql-aspnet/Internal/Resolvers/FieldResolverMetaData.cs b/src/graphql-aspnet/Internal/Resolvers/FieldResolverMetaData.cs index cdd4db402..e250d1144 100644 --- a/src/graphql-aspnet/Internal/Resolvers/FieldResolverMetaData.cs +++ b/src/graphql-aspnet/Internal/Resolvers/FieldResolverMetaData.cs @@ -20,6 +20,20 @@ namespace GraphQL.AspNet.Internal.Resolvers ///
internal class FieldResolverMetaData : IGraphFieldResolverMetaData { + /// + /// Initializes a new instance of the class. + /// + /// The method info will be invoked to fulfill the resolver. + /// The parameters metadata collection related to this resolver method. + /// Expected type of the data to be returned by the method. May be different + /// from concrete return types (e.g. expecting an interface but actually returning a concrete type that implements that interface). + /// if set to true the invoked method is asyncronous. + /// The name of the resolver method or property as it exists in source code. + /// the full name of the resolver method or propert, with namespace and parent owning class, + /// as it exists in source code. + /// The type of the .NET class or struct where the resolver method is declared. + /// The name of the .NET class or struct where the resolver method is declared. + /// The full name of the .NET class or struct, including namespace, where the resolver method is declared. public FieldResolverMetaData( MethodInfo method, IGraphFieldResolverParameterMetaDataCollection parameters, diff --git a/src/graphql-aspnet/Internal/Resolvers/FieldResolverParameterMetaData.cs b/src/graphql-aspnet/Internal/Resolvers/FieldResolverParameterMetaData.cs index bf31d8034..31ab7fc37 100644 --- a/src/graphql-aspnet/Internal/Resolvers/FieldResolverParameterMetaData.cs +++ b/src/graphql-aspnet/Internal/Resolvers/FieldResolverParameterMetaData.cs @@ -21,6 +21,16 @@ namespace GraphQL.AspNet.Internal.Resolvers ///
internal class FieldResolverParameterMetaData : IGraphFieldResolverParameterMetaData { + /// + /// Initializes a new instance of the class. + /// + /// The parameter info for a single parameter within a resolver method. + /// The name of the parameter as its declared in source code. + /// The full name of the parameter, including namespace, owning object and declared method, as it exists in source code. + /// Any modifier attributes for this parameter discovered via templating or set + /// at runtime by the target schema. + /// The default value assigned to this parameter in source code when the parameter + /// was declared. public FieldResolverParameterMetaData( ParameterInfo paramInfo, string internalName, diff --git a/src/graphql-aspnet/Internal/Resolvers/FieldResolverParameterMetaDataCollection.cs b/src/graphql-aspnet/Internal/Resolvers/FieldResolverParameterMetaDataCollection.cs index 273ea23af..4a67017c8 100644 --- a/src/graphql-aspnet/Internal/Resolvers/FieldResolverParameterMetaDataCollection.cs +++ b/src/graphql-aspnet/Internal/Resolvers/FieldResolverParameterMetaDataCollection.cs @@ -13,6 +13,7 @@ namespace GraphQL.AspNet.Internal.Resolvers using System.Collections.Generic; using System.Linq; using GraphQL.AspNet.Interfaces.Execution; + using GraphQL.AspNet.Schemas.TypeSystem; /// /// A collection of parameter metadata that can be accessed by index in its parent method or by name. @@ -34,8 +35,24 @@ public FieldResolverParameterMetaDataCollection(IEnumerable(_parameters.Count); - foreach (var arg in _parameters) - _parametersByName.Add(arg.ParameterInfo.Name, arg); + foreach (var paramItem in _parameters) + { + _parametersByName.Add(paramItem.ParameterInfo.Name, paramItem); + if (paramItem.ArgumentModifiers.IsSourceParameter()) + this.SourceParameter = paramItem; + } + } + + /// + public IGraphFieldResolverParameterMetaData FindByName(string parameterName) + { + if (parameterName == null) + return null; + + if (_parametersByName.ContainsKey(parameterName)) + return _parametersByName[parameterName]; + + return null; } /// @@ -58,5 +75,8 @@ IEnumerator IEnumerable.GetEnumerator() /// public int Count => _parameters.Count; + + /// + public IGraphFieldResolverParameterMetaData SourceParameter { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Internal/Resolvers/FunctionGraphFieldResolver{TSource,TReturn}.cs b/src/graphql-aspnet/Internal/Resolvers/FunctionGraphFieldResolver{TSource,TReturn}.cs index dd9167e9c..2079f2abc 100644 --- a/src/graphql-aspnet/Internal/Resolvers/FunctionGraphFieldResolver{TSource,TReturn}.cs +++ b/src/graphql-aspnet/Internal/Resolvers/FunctionGraphFieldResolver{TSource,TReturn}.cs @@ -10,6 +10,7 @@ namespace GraphQL.AspNet.Internal.Resolvers { using System; + using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; using GraphQL.AspNet.Common; @@ -38,6 +39,7 @@ internal class FunctionGraphFieldResolver : IGraphFieldResolve public FunctionGraphFieldResolver(Func> func) { _func = Validation.ThrowIfNullOrReturn(func, nameof(func)); + this.MetaData = InternalFieldResolverMetaData.CreateMetadata(this.GetType()); } /// @@ -46,5 +48,8 @@ public async Task ResolveAsync(FieldResolutionContext context, CancellationToken var data = await _func(context?.Arguments.SourceData as TSource).ConfigureAwait(false); context.Result = data; } + + /// + public IGraphFieldResolverMetaData MetaData { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Internal/Resolvers/GraphControllerActionResolver.cs b/src/graphql-aspnet/Internal/Resolvers/GraphControllerActionResolver.cs index ec28eb7a1..b6276e959 100644 --- a/src/graphql-aspnet/Internal/Resolvers/GraphControllerActionResolver.cs +++ b/src/graphql-aspnet/Internal/Resolvers/GraphControllerActionResolver.cs @@ -26,8 +26,6 @@ namespace GraphQL.AspNet.Internal.Resolvers /// internal class GraphControllerActionResolver : GraphControllerActionResolverBase, IGraphFieldResolver { - private readonly IGraphFieldResolverMetaData _actionResolverMetaData; - /// /// Initializes a new instance of the class. /// @@ -35,7 +33,7 @@ internal class GraphControllerActionResolver : GraphControllerActionResolverBase /// method that this resolver will invoke. public GraphControllerActionResolver(IGraphFieldResolverMetaData actionResolverMetadata) { - _actionResolverMetaData = Validation.ThrowIfNullOrReturn(actionResolverMetadata, nameof(actionResolverMetadata)); + this.MetaData = Validation.ThrowIfNullOrReturn(actionResolverMetadata, nameof(actionResolverMetadata)); } /// @@ -48,7 +46,7 @@ public async Task ResolveAsync(FieldResolutionContext context, CancellationToken // create a scoped controller instance for this invocation var controller = context .ServiceProvider? - .GetService(_actionResolverMetaData.ParentObjectType) as GraphController; + .GetService(this.MetaData.ParentObjectType) as GraphController; if (controller == null) { @@ -59,7 +57,7 @@ public async Task ResolveAsync(FieldResolutionContext context, CancellationToken else { // invoke the right action method and set a result. - var task = controller.InvokeActionAsync(_actionResolverMetaData, context); + var task = controller.InvokeActionAsync(this.MetaData, context); var returnedItem = await task.ConfigureAwait(false); result = this.EnsureGraphActionResult(returnedItem); } @@ -74,5 +72,8 @@ public async Task ResolveAsync(FieldResolutionContext context, CancellationToken // in what ever manner is appropriate for the result itself await result.CompleteAsync(context).ConfigureAwait(false); } + + /// + public IGraphFieldResolverMetaData MetaData { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Internal/Resolvers/GraphControllerRouteFieldResolver.cs b/src/graphql-aspnet/Internal/Resolvers/GraphControllerRouteFieldResolver.cs index ce76963ed..71036ddd4 100644 --- a/src/graphql-aspnet/Internal/Resolvers/GraphControllerRouteFieldResolver.cs +++ b/src/graphql-aspnet/Internal/Resolvers/GraphControllerRouteFieldResolver.cs @@ -35,6 +35,8 @@ public GraphControllerRouteFieldResolver(VirtualResolvedObject dataObject) { Validation.ThrowIfNull(dataObject, nameof(dataObject)); _dataObject = dataObject; + + this.MetaData = InternalFieldResolverMetaData.CreateMetadata(this.GetType()); } /// @@ -43,5 +45,8 @@ public Task ResolveAsync(FieldResolutionContext context, CancellationToken cance context.Result = _dataObject; return Task.CompletedTask; } + + /// + public IGraphFieldResolverMetaData MetaData { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Internal/Resolvers/GraphDirectiveActionResolver.cs b/src/graphql-aspnet/Internal/Resolvers/GraphDirectiveActionResolver.cs index 460efc688..46b27a839 100644 --- a/src/graphql-aspnet/Internal/Resolvers/GraphDirectiveActionResolver.cs +++ b/src/graphql-aspnet/Internal/Resolvers/GraphDirectiveActionResolver.cs @@ -10,6 +10,7 @@ namespace GraphQL.AspNet.Internal.Resolvers { using System; + using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using GraphQL.AspNet.Common; @@ -21,6 +22,7 @@ namespace GraphQL.AspNet.Internal.Resolvers using GraphQL.AspNet.Interfaces.Controllers; using GraphQL.AspNet.Interfaces.Execution; using GraphQL.AspNet.Interfaces.Internal; + using GraphQL.AspNet.Schemas.TypeSystem; /// /// A special resolver specifically for invoking controller actions @@ -29,41 +31,39 @@ namespace GraphQL.AspNet.Internal.Resolvers /// internal class GraphDirectiveActionResolver : GraphControllerActionResolverBase, IGraphDirectiveResolver { - private readonly IGraphDirectiveTemplate _directiveTemplate; - /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// The directive template from which this resolver will - /// query for lifecycle methods. - public GraphDirectiveActionResolver(IGraphDirectiveTemplate directiveTemplate) + /// The directive metadata items, per location, + /// that this resolver will use for executing the directive. + public GraphDirectiveActionResolver(IReadOnlyDictionary directiveMetadataItems) { - _directiveTemplate = Validation.ThrowIfNullOrReturn(directiveTemplate, nameof(directiveTemplate)); + this.MetaData = Validation.ThrowIfNullOrReturn(directiveMetadataItems, nameof(directiveMetadataItems)); } /// public async Task ResolveAsync(DirectiveResolutionContext context, CancellationToken cancelToken = default) { - var action = _directiveTemplate.FindMetaData(context.Request.InvocationContext.Location); - // if no action is found skip processing of this directive - if (action == null) + if (!this.MetaData.ContainsKey(context.Request.InvocationContext.Location)) return; + var action = this.MetaData[context.Request.InvocationContext.Location]; + IGraphActionResult result; try { // create a directive instance for this invocation var directive = context .ServiceProvider? - .GetService(_directiveTemplate.ObjectType) as GraphDirective; + .GetService(action.ParentObjectType) as GraphDirective; if (directive == null) { // fallback: attempt to create the directive if it has no constructor parameters try { - directive = InstanceFactory.CreateInstance(_directiveTemplate.ObjectType) as GraphDirective; + directive = InstanceFactory.CreateInstance(action.ParentObjectType) as GraphDirective; } catch (InvalidOperationException) { @@ -74,7 +74,7 @@ public async Task ResolveAsync(DirectiveResolutionContext context, CancellationT if (directive == null) { result = new RouteNotFoundGraphActionResult( - $"The directive '{_directiveTemplate.InternalFullName}' " + + $"The directive '{action.InternalFullName}' " + "was not found in the scoped service provider. Any directives that have constructor parameters " + $"must also be registered to the service provider; Try using '{nameof(SchemaOptions.AddGraphType)}' " + $"with the type of your directive at startup."); @@ -98,5 +98,8 @@ public async Task ResolveAsync(DirectiveResolutionContext context, CancellationT // in what ever manner is appropriate for the result itself await result.CompleteAsync(context); } + + /// + public IReadOnlyDictionary MetaData { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Internal/Resolvers/InputObjectValueResolver.cs b/src/graphql-aspnet/Internal/Resolvers/InputObjectValueResolver.cs index c2f73605a..7534ff1b2 100644 --- a/src/graphql-aspnet/Internal/Resolvers/InputObjectValueResolver.cs +++ b/src/graphql-aspnet/Internal/Resolvers/InputObjectValueResolver.cs @@ -105,7 +105,7 @@ public object Resolve(IResolvableValueItem resolvableItem, IResolvedVariableColl var actualField = _graphType.Fields.FindField(inputField.Key); if (actualField != null) { - propSetter = _propSetters.ContainsKey(actualField.InternalName) ? _propSetters[actualField.InternalName] : null; + propSetter = _propSetters.ContainsKey(actualField.InternalFullName) ? _propSetters[actualField.InternalFullName] : null; } if (resolver == null || propSetter == null) diff --git a/src/graphql-aspnet/Internal/Resolvers/InternalFieldResolverMetaData.cs b/src/graphql-aspnet/Internal/Resolvers/InternalFieldResolverMetaData.cs new file mode 100644 index 000000000..cac314c97 --- /dev/null +++ b/src/graphql-aspnet/Internal/Resolvers/InternalFieldResolverMetaData.cs @@ -0,0 +1,54 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Internal.Resolvers +{ + using System; + using System.Linq; + using System.Reflection; + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Common.Extensions; + using GraphQL.AspNet.Interfaces.Execution; + + /// + /// A helper class for generating valid metadata for introspection and other internal value resolvers + /// + internal static class InternalFieldResolverMetaData + { + /// + /// Creates a metadata item for a method that will function correctly for any calls, checks or log entries. This + /// metadata points to a method that would never be invoked. + /// + /// The type that will masqurade as "owning" the resolver. + /// IGraphFieldResolverMetaData. + public static IGraphFieldResolverMetaData CreateMetadata(Type owningType) + { + Validation.ThrowIfNull(owningType, nameof(owningType)); + + var methodInfo = typeof(InternalFieldResolverMetaData) + .GetMethod(nameof(InternalValueResolver), BindingFlags.Static | BindingFlags.NonPublic); + + return new FieldResolverMetaData( + methodInfo, + new FieldResolverParameterMetaDataCollection(), + typeof(int), + false, + nameof(InternalValueResolver), + $"{owningType.FriendlyName(true)}.{nameof(InternalValueResolver)}", + owningType, + owningType.FriendlyName(), + owningType.FriendlyName(true)); + } + + private static int InternalValueResolver() + { + return 0; + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Internal/Resolvers/Introspeection/Schema_TypeGraphFieldResolver.cs b/src/graphql-aspnet/Internal/Resolvers/Introspeection/Schema_TypeGraphFieldResolver.cs index 420ffab32..452bb3d81 100644 --- a/src/graphql-aspnet/Internal/Resolvers/Introspeection/Schema_TypeGraphFieldResolver.cs +++ b/src/graphql-aspnet/Internal/Resolvers/Introspeection/Schema_TypeGraphFieldResolver.cs @@ -33,6 +33,8 @@ internal class Schema_TypeGraphFieldResolver : IGraphFieldResolver public Schema_TypeGraphFieldResolver(IntrospectedSchema schema) { _schema = Validation.ThrowIfNullOrReturn(schema, nameof(schema)); + + this.MetaData = InternalFieldResolverMetaData.CreateMetadata(this.GetType()); } /// @@ -57,5 +59,8 @@ public Task ResolveAsync(FieldResolutionContext resolutionContext, CancellationT return Task.CompletedTask; } + + /// + public IGraphFieldResolverMetaData MetaData { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Internal/Resolvers/Introspeection/Type_EnumValuesGraphFieldResolver.cs b/src/graphql-aspnet/Internal/Resolvers/Introspeection/Type_EnumValuesGraphFieldResolver.cs index ed7dac066..5e0d86f9f 100644 --- a/src/graphql-aspnet/Internal/Resolvers/Introspeection/Type_EnumValuesGraphFieldResolver.cs +++ b/src/graphql-aspnet/Internal/Resolvers/Introspeection/Type_EnumValuesGraphFieldResolver.cs @@ -27,6 +27,7 @@ internal class Type_EnumValuesGraphFieldResolver : IGraphFieldResolver ///
public Type_EnumValuesGraphFieldResolver() { + this.MetaData = InternalFieldResolverMetaData.CreateMetadata(this.GetType()); } /// @@ -51,5 +52,8 @@ public Task ResolveAsync(FieldResolutionContext resolutionContext, CancellationT return Task.CompletedTask; } + + /// + public IGraphFieldResolverMetaData MetaData { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Internal/Resolvers/Introspeection/Type_TypeGraphFieldResolver.cs b/src/graphql-aspnet/Internal/Resolvers/Introspeection/Type_TypeGraphFieldResolver.cs index 73748508a..360b4d47c 100644 --- a/src/graphql-aspnet/Internal/Resolvers/Introspeection/Type_TypeGraphFieldResolver.cs +++ b/src/graphql-aspnet/Internal/Resolvers/Introspeection/Type_TypeGraphFieldResolver.cs @@ -51,5 +51,8 @@ public Task ResolveAsync(FieldResolutionContext context, CancellationToken cance return Task.CompletedTask; } + + /// + public IGraphFieldResolverMetaData MetaData { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Internal/Resolvers/ObjectMethodGraphFieldResolver.cs b/src/graphql-aspnet/Internal/Resolvers/ObjectMethodGraphFieldResolver.cs index 0c766d905..ca9ec4736 100644 --- a/src/graphql-aspnet/Internal/Resolvers/ObjectMethodGraphFieldResolver.cs +++ b/src/graphql-aspnet/Internal/Resolvers/ObjectMethodGraphFieldResolver.cs @@ -26,7 +26,6 @@ namespace GraphQL.AspNet.Internal.Resolvers ///
internal class ObjectMethodGraphFieldResolver : IGraphFieldResolver { - private readonly IGraphFieldResolverMetaData _resolverMetadata; private readonly MethodInfo _methodInfo; /// @@ -35,8 +34,8 @@ internal class ObjectMethodGraphFieldResolver : IGraphFieldResolver /// A resolver method that points to a .NET method. public ObjectMethodGraphFieldResolver(IGraphFieldResolverMetaData resolverMetadata) { - _resolverMetadata = Validation.ThrowIfNullOrReturn(resolverMetadata, nameof(resolverMetadata)); - _methodInfo = _resolverMetadata.Method; + this.MetaData = Validation.ThrowIfNullOrReturn(resolverMetadata, nameof(resolverMetadata)); + _methodInfo = this.MetaData.Method; } /// @@ -63,8 +62,8 @@ public virtual async Task ResolveAsync(FieldResolutionContext context, Cancellat Constants.ErrorCodes.INVALID_OBJECT, context.Request.Origin, new GraphExecutionException( - $"The method '{_resolverMetadata.InternalFullName}' expected source data of type " + - $"'{_resolverMetadata.ParentObjectType.FriendlyName()}' but received '{sourceData.GetType().FriendlyName()}' " + + $"The method '{this.MetaData.InternalFullName}' expected source data of type " + + $"'{this.MetaData.ParentObjectType.FriendlyName()}' but received '{sourceData.GetType().FriendlyName()}' " + "which is not compatible.")); return; @@ -74,17 +73,17 @@ public virtual async Task ResolveAsync(FieldResolutionContext context, Cancellat { object data = null; - var paramSet = context.Arguments.PrepareArguments(_resolverMetadata); - var invoker = InstanceFactory.CreateInstanceMethodInvoker(_resolverMetadata.Method); + var paramSet = context.Arguments.PrepareArguments(this.MetaData); + var invoker = InstanceFactory.CreateInstanceMethodInvoker(this.MetaData.Method); var invokableObject = context.Arguments.SourceData as object; var invokeReturn = invoker(ref invokableObject, paramSet); - if (_resolverMetadata.IsAsyncField) + if (this.MetaData.IsAsyncField) { if (invokeReturn is Task task) { await task.ConfigureAwait(false); - data = task.ResultOfTypeOrNull(_resolverMetadata.ExpectedReturnType); + data = task.ResultOfTypeOrNull(this.MetaData.ExpectedReturnType); } } else @@ -111,5 +110,8 @@ public virtual async Task ResolveAsync(FieldResolutionContext context, Cancellat ex); } } + + /// + public IGraphFieldResolverMetaData MetaData { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Internal/Resolvers/ObjectPropertyGraphFieldResolver.cs b/src/graphql-aspnet/Internal/Resolvers/ObjectPropertyGraphFieldResolver.cs index 3a8413de6..03f6e410c 100644 --- a/src/graphql-aspnet/Internal/Resolvers/ObjectPropertyGraphFieldResolver.cs +++ b/src/graphql-aspnet/Internal/Resolvers/ObjectPropertyGraphFieldResolver.cs @@ -27,15 +27,13 @@ namespace GraphQL.AspNet.Internal.Resolvers [DebuggerDisplay("Prop Resolver: {_graphMethod.Name}")] internal class ObjectPropertyGraphFieldResolver : IGraphFieldResolver { - private readonly IGraphFieldResolverMetaData _resolverMetadata; - /// /// Initializes a new instance of the class. /// /// A set of metadata items that points to a .NET property getter. public ObjectPropertyGraphFieldResolver(IGraphFieldResolverMetaData resolverMetaData) { - _resolverMetadata = Validation.ThrowIfNullOrReturn(resolverMetaData, nameof(resolverMetaData)); + this.MetaData = Validation.ThrowIfNullOrReturn(resolverMetaData, nameof(resolverMetaData)); } /// @@ -56,9 +54,9 @@ public async Task ResolveAsync(FieldResolutionContext context, CancellationToken // valdidate the incoming source data to ensure its process-able by this property // resolver. If the data is being resolved through an interface or object reference // ensure the provided source data can be converted otherwise ensure the types match exactly. - if (_resolverMetadata.ParentObjectType.IsInterface || _resolverMetadata.ParentObjectType.IsClass) + if (this.MetaData.ParentObjectType.IsInterface || this.MetaData.ParentObjectType.IsClass) { - if (!Validation.IsCastable(sourceData.GetType(), _resolverMetadata.ParentObjectType)) + if (!Validation.IsCastable(sourceData.GetType(), this.MetaData.ParentObjectType)) { context.Messages.Critical( "The source data provided to the field resolver " + @@ -66,14 +64,14 @@ public async Task ResolveAsync(FieldResolutionContext context, CancellationToken Constants.ErrorCodes.INVALID_OBJECT, context.Request.Origin, new GraphExecutionException( - $"The property '{_resolverMetadata.InternalFullName}' expected source data that implements the interface " + - $"'{_resolverMetadata.ParentObjectType.FriendlyName()}' but received '{sourceData.GetType().FriendlyName()}' which " + + $"The property '{this.MetaData.InternalFullName}' expected source data that implements the interface " + + $"'{this.MetaData.ParentObjectType.FriendlyName()}' but received '{sourceData.GetType().FriendlyName()}' which " + "is not compatible.")); return; } } - else if (sourceData.GetType() != _resolverMetadata.ParentObjectType) + else if (sourceData.GetType() != this.MetaData.ParentObjectType) { context.Messages.Critical( "The source data provided to the field resolver " + @@ -81,8 +79,8 @@ public async Task ResolveAsync(FieldResolutionContext context, CancellationToken Constants.ErrorCodes.INVALID_OBJECT, context.Request.Origin, new GraphExecutionException( - $"The property '{_resolverMetadata.InternalFullName}' expected source data of type " + - $"'{_resolverMetadata.ParentObjectType.FriendlyName()}' but received '{sourceData.GetType().FriendlyName()}' " + + $"The property '{this.MetaData.InternalFullName}' expected source data of type " + + $"'{this.MetaData.ParentObjectType.FriendlyName()}' but received '{sourceData.GetType().FriendlyName()}' " + "which is not compatible.")); return; @@ -90,9 +88,9 @@ public async Task ResolveAsync(FieldResolutionContext context, CancellationToken try { - var invoker = InstanceFactory.CreateInstanceMethodInvoker(_resolverMetadata.Method); + var invoker = InstanceFactory.CreateInstanceMethodInvoker(this.MetaData.Method); var invokeReturn = invoker(ref sourceData, new object[0]); - if (_resolverMetadata.IsAsyncField) + if (this.MetaData.IsAsyncField) { if (invokeReturn is Task task) { @@ -100,7 +98,7 @@ public async Task ResolveAsync(FieldResolutionContext context, CancellationToken if (task.IsFaulted) throw task.UnwrapException(); - invokeReturn = task.ResultOfTypeOrNull(_resolverMetadata.ExpectedReturnType); + invokeReturn = task.ResultOfTypeOrNull(this.MetaData.ExpectedReturnType); } else { @@ -134,5 +132,8 @@ public async Task ResolveAsync(FieldResolutionContext context, CancellationToken ex); } } + + /// + public IGraphFieldResolverMetaData MetaData { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Internal/TypeTemplates/GraphArgumentTemplate.cs b/src/graphql-aspnet/Internal/TypeTemplates/GraphArgumentTemplate.cs index 892ce1bbd..c24c9501f 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/GraphArgumentTemplate.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/GraphArgumentTemplate.cs @@ -26,6 +26,7 @@ namespace GraphQL.AspNet.Internal.TypeTemplates using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; + using Microsoft.AspNetCore.Mvc; /// /// A template describing an argument declared a field. @@ -67,6 +68,12 @@ public virtual void Parse() if (string.IsNullOrWhiteSpace(name)) name = Constants.Routing.PARAMETER_META_NAME; + // determine if the user has explicitly said this is + // to be consumed from a DI container + var fromServicesAttrib = this.Parameter.SingleAttributeOfTypeOrDefault(); + if (fromServicesAttrib != null) + this.ArgumentModifiers = this.ArgumentModifiers | GraphArgumentModifiers.Injected; + name = name.Replace(Constants.Routing.PARAMETER_META_NAME, this.Parameter.Name); this.Route = new GraphArgumentFieldPath(this.Parent.Route, name); @@ -134,6 +141,12 @@ public virtual void Parse() /// System.Boolean. protected virtual bool IsSourceDataArgument() { + if (this.Parent.Arguments.Any(x => x.ArgumentModifiers.HasFlag(GraphArgumentModifiers.ParentFieldResult))) + return false; + + if (this.ArgumentModifiers.IsInjected()) + return false; + if (this.ObjectType == this.Parent.SourceObjectType) { var sourceType = this.ObjectType; @@ -142,9 +155,6 @@ protected virtual bool IsSourceDataArgument() sourceType = typeof(IEnumerable<>).MakeGenericType(sourceType); } - if (this.Parent.Arguments.Any(x => x.ArgumentModifiers.HasFlag(GraphArgumentModifiers.ParentFieldResult))) - return false; - return sourceType == this.DeclaredArgumentType; } diff --git a/src/graphql-aspnet/Internal/TypeTemplates/GraphDirectiveMethodTemplate.cs b/src/graphql-aspnet/Internal/TypeTemplates/GraphDirectiveMethodTemplate.cs index 038d1fa30..1642b5cf9 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/GraphDirectiveMethodTemplate.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/GraphDirectiveMethodTemplate.cs @@ -193,7 +193,8 @@ public IEnumerable RetrieveRequiredTypes() return list; } - internal IGraphFieldResolverMetaData CreateResolverMetaData() + /// + public IGraphFieldResolverMetaData CreateResolverMetaData() { var paramSet = new FieldResolverParameterMetaDataCollection( this.Arguments.Select(x => x.CreateResolverMetaData())); @@ -244,10 +245,10 @@ internal IGraphFieldResolverMetaData CreateResolverMetaData() /// public IReadOnlyList Arguments => _arguments; - /// + /// public Type ExpectedReturnType { get; protected set; } - /// + /// public bool IsAsyncField { get; protected set; } /// @@ -262,13 +263,16 @@ internal IGraphFieldResolverMetaData CreateResolverMetaData() /// public Type SourceObjectType => this.Parent?.ObjectType; - /// + /// public IGraphTypeTemplate Parent { get; } - /// + /// public MethodInfo Method { get; } - /// + /// + /// Gets the set of parameters declared on the . + /// + /// The parameters. public IReadOnlyList Parameters { get; } /// diff --git a/src/graphql-aspnet/Internal/TypeTemplates/GraphDirectiveMethodTemplateContainer.cs b/src/graphql-aspnet/Internal/TypeTemplates/GraphDirectiveMethodTemplateContainer.cs index f262446bb..78fe85242 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/GraphDirectiveMethodTemplateContainer.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/GraphDirectiveMethodTemplateContainer.cs @@ -163,6 +163,22 @@ public void ValidateOrThrow() } } + /// + /// Creates the a dictionary of metadata items, keyed by the location where each resolver + /// should execute.. + /// + /// IReadOnlyDictionary<DirectiveLocation, IGraphFieldResolverMetaData>. + public IReadOnlyDictionary CreateMetadataCollection() + { + var dicOut = new Dictionary(); + foreach (var kvp in _templateMap) + { + dicOut.Add(kvp.Key, kvp.Value.CreateResolverMetaData()); + } + + return dicOut; + } + /// /// Gets the total number of registrations tracked by this instance. /// diff --git a/src/graphql-aspnet/Internal/TypeTemplates/GraphDirectiveTemplate.cs b/src/graphql-aspnet/Internal/TypeTemplates/GraphDirectiveTemplate.cs index 01560599c..a092acdb9 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/GraphDirectiveTemplate.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/GraphDirectiveTemplate.cs @@ -114,7 +114,8 @@ public override void ValidateOrThrow() /// public IGraphDirectiveResolver CreateResolver() { - return new GraphDirectiveActionResolver(this); + var allMetadata = this.Methods.CreateMetadataCollection(); + return new GraphDirectiveActionResolver(allMetadata); } /// diff --git a/src/graphql-aspnet/Internal/TypeTemplates/MethodGraphFieldTemplateBase.cs b/src/graphql-aspnet/Internal/TypeTemplates/MethodGraphFieldTemplateBase.cs index 72c060597..3a54026ec 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/MethodGraphFieldTemplateBase.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/MethodGraphFieldTemplateBase.cs @@ -133,13 +133,13 @@ public override IGraphFieldResolverMetaData CreateResolverMetaData() /// public override IReadOnlyList Arguments => _arguments; - /// + /// public MethodInfo Method { get; } /// public override Type DeclaredReturnType => this.Method.ReturnType; - /// + /// public Type ExpectedReturnType { get; protected set; } /// @@ -148,7 +148,10 @@ public override IGraphFieldResolverMetaData CreateResolverMetaData() /// public override GraphFieldSource FieldSource => GraphFieldSource.Method; - /// + /// + /// Gets the set of parameters found on the target . + /// + /// The parameters. public IReadOnlyList Parameters { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Internal/TypeTemplates/PropertyGraphFieldTemplate.cs b/src/graphql-aspnet/Internal/TypeTemplates/PropertyGraphFieldTemplate.cs index e3cbefbee..0b5722249 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/PropertyGraphFieldTemplate.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/PropertyGraphFieldTemplate.cs @@ -114,6 +114,7 @@ public override IGraphFieldResolver CreateResolver() return new ObjectPropertyGraphFieldResolver(this.CreateResolverMetaData()); } + /// public override IGraphFieldResolverMetaData CreateResolverMetaData() { var paramSet = new FieldResolverParameterMetaDataCollection( @@ -134,7 +135,7 @@ public override IGraphFieldResolverMetaData CreateResolverMetaData() /// public override Type DeclaredReturnType => this.Property.PropertyType; - /// + /// public Type ExpectedReturnType { get; private set; } /// @@ -152,10 +153,13 @@ public override IGraphFieldResolverMetaData CreateResolverMetaData() /// The property. private PropertyInfo Property { get; } - /// + /// public MethodInfo Method { get; } - /// + /// + /// Gets the set of parameters defined by . + /// + /// The parameters. public IReadOnlyList Parameters { get; } /// diff --git a/src/graphql-aspnet/Logging/GeneralEvents/ExecutionDirectiveAppliedLogEntry.cs b/src/graphql-aspnet/Logging/GeneralEvents/ExecutionDirectiveAppliedLogEntry.cs index 15659b5ff..b83bbe7bd 100644 --- a/src/graphql-aspnet/Logging/GeneralEvents/ExecutionDirectiveAppliedLogEntry.cs +++ b/src/graphql-aspnet/Logging/GeneralEvents/ExecutionDirectiveAppliedLogEntry.cs @@ -35,7 +35,7 @@ public ExecutionDirectiveAppliedLogEntry(IDirective directiveApplied, IDocumentP this.SourceLineIndex = appliedTo?.SourceLocation.LineIndex ?? 0; this.DirectiveLocation = appliedTo?.AsDirectiveLocation().ToString() ?? "-unknown-"; this.DirectiveName = directiveApplied?.Name; - this.DirectiveInternalName = directiveApplied?.InternalName; + this.DirectiveInternalName = directiveApplied?.InternalFullName; } /// diff --git a/src/graphql-aspnet/Logging/GeneralEvents/TypeSystemDirectiveAppliedLogEntry.cs b/src/graphql-aspnet/Logging/GeneralEvents/TypeSystemDirectiveAppliedLogEntry.cs index c05cda001..63f85abbf 100644 --- a/src/graphql-aspnet/Logging/GeneralEvents/TypeSystemDirectiveAppliedLogEntry.cs +++ b/src/graphql-aspnet/Logging/GeneralEvents/TypeSystemDirectiveAppliedLogEntry.cs @@ -31,7 +31,7 @@ public TypeSystemDirectiveAppliedLogEntry(IDirective directiveApplied, ISchemaIt this.SchemaTypeName = typeof(TSchema).FriendlyName(true); this.SchemaItemPath = appliedTo?.Route?.Path; this.DirectiveName = directiveApplied?.Name; - this.DirectiveInternalName = directiveApplied?.InternalName; + this.DirectiveInternalName = directiveApplied?.InternalFullName; this.DirectiveLocation = appliedTo?.AsDirectiveLocation().ToString() ?? "-unknown-"; } diff --git a/src/graphql-aspnet/Middleware/FieldExecution/Components/ProcessChildFieldsMiddleware.cs b/src/graphql-aspnet/Middleware/FieldExecution/Components/ProcessChildFieldsMiddleware.cs index 9a508376d..f82688dff 100644 --- a/src/graphql-aspnet/Middleware/FieldExecution/Components/ProcessChildFieldsMiddleware.cs +++ b/src/graphql-aspnet/Middleware/FieldExecution/Components/ProcessChildFieldsMiddleware.cs @@ -365,7 +365,7 @@ private IEnumerable CreateChildExecutionContexts( // create a list to house the raw source data being passed for the batch // this is the IEnumerable required as an input to any batch resolver - var sourceArgumentType = childInvocationContext.Field.Arguments.SourceDataArgument?.ObjectType ?? typeof(object); + var sourceArgumentType = parentContext.Field.ObjectType ?? typeof(object); var sourceListType = typeof(List<>).MakeGenericType(sourceArgumentType); var sourceDataList = InstanceFactory.CreateInstance(sourceListType, sourceItemsToInclude.Count) as IList; diff --git a/src/graphql-aspnet/Schemas/SchemaItemValidators/BaseSchemaItemValidator.cs b/src/graphql-aspnet/Schemas/SchemaItemValidators/BaseSchemaItemValidator.cs index 716f70242..f6d642b7f 100644 --- a/src/graphql-aspnet/Schemas/SchemaItemValidators/BaseSchemaItemValidator.cs +++ b/src/graphql-aspnet/Schemas/SchemaItemValidators/BaseSchemaItemValidator.cs @@ -11,6 +11,9 @@ namespace GraphQL.AspNet.Schemas.SchemaItemValidators { using GraphQL.AspNet.Interfaces.Schema; + /// + /// A base class with common functionality used by many internal schema item validators. + /// internal abstract class BaseSchemaItemValidator : ISchemaItemValidator { /// diff --git a/src/graphql-aspnet/Schemas/SchemaItemValidators/GraphArgumentValidator.cs b/src/graphql-aspnet/Schemas/SchemaItemValidators/GraphArgumentValidator.cs index 12b83b368..045968d80 100644 --- a/src/graphql-aspnet/Schemas/SchemaItemValidators/GraphArgumentValidator.cs +++ b/src/graphql-aspnet/Schemas/SchemaItemValidators/GraphArgumentValidator.cs @@ -45,10 +45,10 @@ public override void ValidateOrThrow(ISchemaItem schemaItem, ISchema schema) $"'{typeof(IGraphArgument).FriendlyName()}' but got '{schema?.GetType().FriendlyName() ?? "-none-"}'"); } - if (argument.ArgumentModifiers.IsPartOfTheSchema() && argument.ObjectType.IsInterface) + if (argument.ObjectType.IsInterface) { throw new GraphTypeDeclarationException( - $"The item '{argument.InternalName}' declares an argument '{argument.Name}' of type '{argument.ObjectType.FriendlyName()}' " + + $"The item '{argument.InternalFullName}' declares an argument '{argument.Name}' of type '{argument.ObjectType.FriendlyName()}' " + $"which is an interface. Interfaces cannot be used as input arguments to any type."); } } diff --git a/src/graphql-aspnet/Schemas/SchemaLanguageGenerator.cs b/src/graphql-aspnet/Schemas/SchemaLanguageGenerator.cs index 250c68225..ac1486fd3 100644 --- a/src/graphql-aspnet/Schemas/SchemaLanguageGenerator.cs +++ b/src/graphql-aspnet/Schemas/SchemaLanguageGenerator.cs @@ -149,10 +149,10 @@ private string SerializeInputObject(object obj, IInputObjectGraphType inputObjec var getters = InstanceFactory.CreatePropertyGetterInvokerCollection(obj.GetType()); foreach (var field in inputObjectGraphType.Fields) { - if (!getters.ContainsKey(field.InternalName)) + if (!getters.ContainsKey(field.InternalFullName)) continue; - var getter = getters[field.InternalName]; + var getter = getters[field.InternalFullName]; builder.Append(field.Name); builder.Append(Constants.QueryLanguage.FieldValueSeperator); builder.Append(" "); diff --git a/src/graphql-aspnet/Schemas/Structural/GraphFieldArgumentCollection.cs b/src/graphql-aspnet/Schemas/Structural/GraphFieldArgumentCollection.cs index a9238dd49..a63c6388b 100644 --- a/src/graphql-aspnet/Schemas/Structural/GraphFieldArgumentCollection.cs +++ b/src/graphql-aspnet/Schemas/Structural/GraphFieldArgumentCollection.cs @@ -27,7 +27,6 @@ internal class GraphFieldArgumentCollection : IGraphArgumentCollection private readonly ISchemaItem _owner; private readonly OrderedDictionary _arguments; private readonly Dictionary _argumentByInternalName; - private IGraphArgument _sourceArgument; /// /// Initializes a new instance of the class. @@ -47,11 +46,7 @@ public IGraphArgument AddArgument(IGraphArgument argument) Validation.ThrowIfNull(argument, nameof(argument)); _arguments.Add(argument.Name, argument); - _argumentByInternalName.Add(argument.InternalName, argument); - - if (argument.ArgumentModifiers.IsSourceParameter() && _sourceArgument == null) - _sourceArgument = argument; - + _argumentByInternalName.Add(argument.InternalFullName, argument); return argument; } @@ -59,20 +54,20 @@ public IGraphArgument AddArgument(IGraphArgument argument) /// Adds the input argument to the growing collection. /// /// The name of the argument in the object graph. - /// Name of the argument as it was defined in the code. + /// The fully qualfiied name of the argument as it was defined in the code. /// The type expression representing how this value is represented in this graph schema. /// The concrete type this field is on the server. /// IGraphFieldArgument. public IGraphArgument AddArgument( string name, - string internalName, + string internalFullName, GraphTypeExpression typeExpression, Type concreteType) { var argument = new VirtualGraphFieldArgument( _owner, name, - internalName, + internalFullName, typeExpression, _owner.Route.CreateChild(name), concreteType, @@ -85,7 +80,7 @@ public IGraphArgument AddArgument( /// Adds the input argument to the growing collection. /// /// The name of the argument in the object graph. - /// Name of the argument as it was defined in the code. + /// The fully qualified name of the argument as it was defined in the code. /// The type expression representing how this value is represented in this graph schema. /// The concrete type this field is on the server. /// The default value to set for the argument. If null, indicates @@ -93,7 +88,7 @@ public IGraphArgument AddArgument( /// IGraphFieldArgument. public IGraphArgument AddArgument( string name, - string internalName, + string internalFullName, GraphTypeExpression typeExpression, Type concreteType, object defaultValue) @@ -101,13 +96,12 @@ public IGraphArgument AddArgument( var argument = new VirtualGraphFieldArgument( _owner, name, - internalName, + internalFullName, typeExpression, _owner.Route.CreateChild(name), concreteType, true, - defaultValue, - GraphArgumentModifiers.None); + defaultValue); return this.AddArgument(argument); } @@ -148,9 +142,6 @@ public IGraphArgument FindArgumentByInternalName(string internalName) /// public int Count => _arguments.Count; - /// - public IGraphArgument SourceDataArgument => _sourceArgument; - /// public IEnumerator GetEnumerator() { diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Directive.cs b/src/graphql-aspnet/Schemas/TypeSystem/Directive.cs index 4278f19cb..84bbad048 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Directive.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Directive.cs @@ -55,7 +55,7 @@ public Directive( this.Publish = true; this.Route = Validation.ThrowIfNullOrReturn(route, nameof(route)); this.ObjectType = Validation.ThrowIfNullOrReturn(directiveType, nameof(directiveType)); - this.InternalName = this.ObjectType.FriendlyName(); + this.InternalFullName = this.ObjectType.FriendlyName(); this.AppliedDirectives = new AppliedDirectiveCollection(this); this.IsRepeatable = isRepeatable; @@ -102,7 +102,7 @@ public bool ValidateObject(object item) public Type ObjectType { get; } /// - public string InternalName { get; } + public string InternalFullName { get; } /// public bool IsRepeatable { get; set; } diff --git a/src/graphql-aspnet/Schemas/TypeSystem/EnumGraphType.cs b/src/graphql-aspnet/Schemas/TypeSystem/EnumGraphType.cs index cc5074fb3..35faf8da1 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/EnumGraphType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/EnumGraphType.cs @@ -59,7 +59,7 @@ public EnumGraphType( this.Route = Validation.ThrowIfNullOrReturn(route, nameof(route)); this.SourceResolver = Validation.ThrowIfNullOrReturn(resolver, nameof(resolver)); - this.InternalName = this.ObjectType.FriendlyName(); + this.InternalFullName = this.ObjectType.FriendlyName(); this.Publish = true; this.AppliedDirectives = directives?.Clone(this) ?? new AppliedDirectiveCollection(this); @@ -111,7 +111,7 @@ public virtual bool ValidateObject(object item) public virtual Type ObjectType { get; } /// - public virtual string InternalName { get; } + public virtual string InternalFullName { get; } /// public virtual bool IsVirtual => false; diff --git a/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiers.cs b/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiers.cs index 8e19b2ec4..1d387226e 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiers.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiers.cs @@ -9,15 +9,15 @@ namespace GraphQL.AspNet.Schemas.TypeSystem { - using System; - /// /// A set of modifiers and flags that can be assigned to individual arguments on graph fields to modify their behavior /// during execution. /// - [Flags] public enum GraphArgumentModifiers { + // implementation note, this used to be a [Flags] enum + // kept numbering of previous usage to prevent clashing in other libraries. + /// /// No special modifications are needed. /// diff --git a/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiersExtensions.cs b/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiersExtensions.cs index bf8e4d3c5..e1a498a04 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiersExtensions.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiersExtensions.cs @@ -58,5 +58,16 @@ public static bool IsPartOfTheSchema(this GraphArgumentModifiers modifiers) { return modifiers == GraphArgumentModifiers.None; } + + /// + /// Determines whether the modifiers indicate that the argument is to be resolved from a DI + /// container as opposed to being passed ona query + /// + /// The modifiers to check. + /// true if the modifiers indicate the argument is to be resolved from a DI continer; otherwise, false. + public static bool IsInjected(this GraphArgumentModifiers modifiers) + { + return modifiers.HasFlag(GraphArgumentModifiers.Injected); + } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/TypeSystem/GraphFieldArgument.cs b/src/graphql-aspnet/Schemas/TypeSystem/GraphFieldArgument.cs index b42e276d7..2e32edf51 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/GraphFieldArgument.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/GraphFieldArgument.cs @@ -32,9 +32,8 @@ public class GraphFieldArgument : IGraphArgument /// Name of the argument. /// The type expression. /// The route path that identifies this argument. - /// The modifiers. /// Name of the parameter as it is declared in the source code. - /// The fully qualified internal name identifiying this argument. + /// The fully qualified internal name identifiying this argument. /// The concrete type of the object representing this argument. /// if set to true indicates that this /// argument has a default value assigned, even if that argument is null. @@ -47,9 +46,8 @@ public GraphFieldArgument( string argumentName, GraphTypeExpression typeExpression, SchemaItemPath route, - GraphArgumentModifiers modifiers, string parameterName, - string internalName, + string internalFullName, Type objectType, bool hasDefaultValue, object defaultValue = null, @@ -59,11 +57,10 @@ public GraphFieldArgument( this.Parent = Validation.ThrowIfNullOrReturn(parent, nameof(parent)); this.Name = Validation.ThrowIfNullWhiteSpaceOrReturn(argumentName, nameof(argumentName)); this.Route = Validation.ThrowIfNullOrReturn(route, nameof(route)); - this.InternalName = Validation.ThrowIfNullWhiteSpaceOrReturn(internalName, nameof(internalName)); + this.InternalFullName = Validation.ThrowIfNullWhiteSpaceOrReturn(internalFullName, nameof(internalFullName)); this.ParameterName = Validation.ThrowIfNullWhiteSpaceOrReturn(parameterName, nameof(parameterName)); this.TypeExpression = Validation.ThrowIfNullOrReturn(typeExpression, nameof(typeExpression)); this.ObjectType = Validation.ThrowIfNullOrReturn(objectType, nameof(objectType)); - this.ArgumentModifiers = modifiers; // by definition (rule 5.4.2.1) a nullable type expression on an argument implies // an optional field. that is to say it has an implicit default value of 'null' @@ -84,9 +81,8 @@ public IGraphArgument Clone(ISchemaItem parent) this.Name, this.TypeExpression.Clone(), parent.Route.CreateChild(this.Name), - this.ArgumentModifiers, this.ParameterName, - this.InternalName, + this.InternalFullName, this.ObjectType, this.HasDefaultValue, this.DefaultValue, @@ -100,9 +96,6 @@ public IGraphArgument Clone(ISchemaItem parent) /// public string Description { get; set; } - /// - public GraphArgumentModifiers ArgumentModifiers { get; } - /// public GraphTypeExpression TypeExpression { get; } @@ -116,7 +109,7 @@ public IGraphArgument Clone(ISchemaItem parent) public Type ObjectType { get; } /// - public string InternalName { get; } + public string InternalFullName { get; } /// public IAppliedDirectiveCollection AppliedDirectives { get; } diff --git a/src/graphql-aspnet/Schemas/TypeSystem/GraphOperation.cs b/src/graphql-aspnet/Schemas/TypeSystem/GraphOperation.cs index 492a55fc5..e607b234a 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/GraphOperation.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/GraphOperation.cs @@ -67,6 +67,6 @@ public IGraphField Extend(IGraphField newField) public Type ObjectType => typeof(GraphOperation); /// - public string InternalName => $"{typeof(GraphOperation).FriendlyName()}.{this.OperationType}"; + public string InternalFullName => $"{typeof(GraphOperation).FriendlyName()}.{this.OperationType}"; } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/TypeSystem/InputGraphField.cs b/src/graphql-aspnet/Schemas/TypeSystem/InputGraphField.cs index 584be400b..da8eeed96 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/InputGraphField.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/InputGraphField.cs @@ -67,7 +67,7 @@ public InputGraphField( this.AppliedDirectives = directives?.Clone(this) ?? new AppliedDirectiveCollection(this); - this.InternalName = declaredPropertyName; + this.InternalFullName = declaredPropertyName; this.HasDefaultValue = !isRequired; this.IsRequired = isRequired && this.TypeExpression.IsNonNullable; this.DefaultValue = defaultValue; @@ -113,7 +113,7 @@ public void AssignParent(IGraphType parent) /// is used in many exceptions and internal error messages. /// /// The fully qualified name of the proeprty this field was created from. - public string InternalName { get; } + public string InternalFullName { get; } /// public object DefaultValue { get; } diff --git a/src/graphql-aspnet/Schemas/TypeSystem/InputObjectGraphType.cs b/src/graphql-aspnet/Schemas/TypeSystem/InputObjectGraphType.cs index 8500732e7..501fdd9d9 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/InputObjectGraphType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/InputObjectGraphType.cs @@ -41,7 +41,7 @@ public InputObjectGraphType( { this.Name = Validation.ThrowIfNullWhiteSpaceOrReturn(name, nameof(name)); this.ObjectType = Validation.ThrowIfNullOrReturn(objectType, nameof(objectType)); - this.InternalName = this.ObjectType.FriendlyName(); + this.InternalFullName = this.ObjectType.FriendlyName(); this.Route = Validation.ThrowIfNullOrReturn(route, nameof(route)); this.AppliedDirectives = directives?.Clone(this) ?? new AppliedDirectiveCollection(this); this.Publish = true; @@ -68,7 +68,7 @@ public void AddField(IInputGraphField field) public Type ObjectType { get; } /// - public string InternalName { get; } + public string InternalFullName { get; } /// /// Gets the collection of fields, keyed on their name, of all the fields nested or contained within this field. diff --git a/src/graphql-aspnet/Schemas/TypeSystem/InterfaceGraphType.cs b/src/graphql-aspnet/Schemas/TypeSystem/InterfaceGraphType.cs index 7fd4bb213..6b91cb673 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/InterfaceGraphType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/InterfaceGraphType.cs @@ -43,7 +43,7 @@ public InterfaceGraphType( this.Name = Validation.ThrowIfNullOrReturn(name, nameof(name)); this.Route = Validation.ThrowIfNullOrReturn(route, nameof(route)); this.ObjectType = Validation.ThrowIfNullOrReturn(concreteType, nameof(concreteType)); - this.InternalName = this.ObjectType.FriendlyName(); + this.InternalFullName = this.ObjectType.FriendlyName(); this.InterfaceNames = new HashSet(); _fieldSet = new GraphFieldCollection(this); @@ -102,7 +102,7 @@ public bool ValidateObject(object item) public Type ObjectType { get; } /// - public virtual string InternalName { get; } + public virtual string InternalFullName { get; } /// public HashSet InterfaceNames { get; } diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/BaseIntrospectionObjectType.cs b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/BaseIntrospectionObjectType.cs index 6aad89827..42b6201d4 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/BaseIntrospectionObjectType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/BaseIntrospectionObjectType.cs @@ -47,6 +47,6 @@ public IGraphField Extend(IGraphField newField) public virtual Type ObjectType => this.GetType(); /// - public virtual string InternalName => this.ObjectType.FriendlyName(); + public virtual string InternalFullName => this.ObjectType.FriendlyName(); } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedDirective.cs b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedDirective.cs index b205a8b34..34e01c5e4 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedDirective.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedDirective.cs @@ -37,7 +37,7 @@ public IntrospectedDirective(IDirective directiveType) public override void Initialize(IntrospectedSchema introspectedSchema) { var list = new List(); - var directiveArguments = this.Directive.Arguments.Where(x => x.ArgumentModifiers.IsPartOfTheSchema()); + var directiveArguments = this.Directive.Arguments; foreach (var arg in directiveArguments) { var introspectedType = introspectedSchema.FindIntrospectedType(arg.TypeExpression.TypeName); diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedField.cs b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedField.cs index 766306c70..55c4e3f87 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedField.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedField.cs @@ -11,10 +11,8 @@ namespace GraphQL.AspNet.Schemas.TypeSystem.Introspection.Model { using System.Collections.Generic; using System.Diagnostics; - using System.Linq; using GraphQL.AspNet.Common; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Schemas.TypeSystem; /// /// A model object containing data for a '__Field' type @@ -42,7 +40,7 @@ public IntrospectedField(IGraphField field, IntrospectedType introspectedFieldOw public override void Initialize(IntrospectedSchema introspectedSchema) { var list = new List(); - foreach (var arg in _field.Arguments.Where(x => x.ArgumentModifiers.IsPartOfTheSchema())) + foreach (var arg in _field.Arguments) { var introspectedType = introspectedSchema.FindIntrospectedType(arg.TypeExpression.TypeName); introspectedType = Introspection.WrapBaseTypeWithModifiers(introspectedType, arg.TypeExpression); diff --git a/src/graphql-aspnet/Schemas/TypeSystem/MethodGraphField.cs b/src/graphql-aspnet/Schemas/TypeSystem/MethodGraphField.cs index 3bb807437..79e433a5a 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/MethodGraphField.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/MethodGraphField.cs @@ -37,7 +37,7 @@ public class MethodGraphField : IGraphField /// Name of the field in the graph. /// The meta data describing the type of data this field returns. /// The formal route to this field in the object graph. - /// Name of the method this field respresents, as it was declared + /// The fully qualified name of the method this field respresents, as it was declared /// in C# code. /// The .NET type of the item or items that represent the graph type returned by this field. /// The .NET type as it was declared on the property which generated this field.. @@ -49,7 +49,7 @@ public MethodGraphField( string fieldName, GraphTypeExpression typeExpression, SchemaItemPath route, - string declaredMethodName, + string internalFullName, Type objectType, Type declaredReturnType, FieldResolutionMode mode = FieldResolutionMode.PerSourceItem, @@ -63,7 +63,7 @@ public MethodGraphField( this.Arguments = new GraphFieldArgumentCollection(this); this.ObjectType = Validation.ThrowIfNullOrReturn(objectType, nameof(objectType)); this.DeclaredReturnType = Validation.ThrowIfNullOrReturn(declaredReturnType, nameof(declaredReturnType)); - this.InternalName = Validation.ThrowIfNullWhiteSpaceOrReturn(declaredMethodName, nameof(declaredMethodName)); + this.InternalFullName = Validation.ThrowIfNullWhiteSpaceOrReturn(internalFullName, nameof(internalFullName)); this.AppliedDirectives = directives?.Clone(this) ?? new AppliedDirectiveCollection(this); @@ -152,7 +152,7 @@ protected virtual MethodGraphField CreateNewInstance(IGraphType parent) this.Name, this.TypeExpression.Clone(), parent.Route.CreateChild(this.Name), - this.InternalName, + this.InternalFullName, this.ObjectType, this.DeclaredReturnType, this.Mode, @@ -219,6 +219,6 @@ protected virtual MethodGraphField CreateNewInstance(IGraphType parent) public IAppliedDirectiveCollection AppliedDirectives { get; } /// - public string InternalName { get; } + public string InternalFullName { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/TypeSystem/ObjectGraphType.cs b/src/graphql-aspnet/Schemas/TypeSystem/ObjectGraphType.cs index 2a35272b3..692323d47 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/ObjectGraphType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/ObjectGraphType.cs @@ -40,7 +40,7 @@ public ObjectGraphType( : base(name, route, directives) { this.ObjectType = Validation.ThrowIfNullOrReturn(objectType, nameof(objectType)); - this.InternalName = this.ObjectType.FriendlyName(); + this.InternalFullName = this.ObjectType.FriendlyName(); this.GraphFieldCollection.AddField(new Introspection_TypeNameMetaField(name)); } @@ -61,6 +61,6 @@ public override bool ValidateObject(object item) public Type ObjectType { get; } /// - public string InternalName { get; } + public string InternalFullName { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/TypeSystem/PropertyGraphField.cs b/src/graphql-aspnet/Schemas/TypeSystem/PropertyGraphField.cs index 803ed3a0e..71845864d 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/PropertyGraphField.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/PropertyGraphField.cs @@ -62,7 +62,7 @@ protected override MethodGraphField CreateNewInstance(IGraphType parent) this.Name, this.TypeExpression.Clone(), parent.Route.CreateChild(this.Name), - this.InternalName, + this.InternalFullName, this.ObjectType, this.DeclaredReturnType, this.Mode, diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/ScalarGraphTypeBase.cs b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/ScalarGraphTypeBase.cs index 1a1987855..ea55756b5 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/ScalarGraphTypeBase.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/ScalarGraphTypeBase.cs @@ -41,7 +41,7 @@ protected ScalarGraphTypeBase( this.Name = Validation.ThrowIfNullWhiteSpaceOrReturn(name, nameof(name)); this.Route = new SchemaItemPath(SchemaItemCollections.Scalars, this.Name); this.ObjectType = Validation.ThrowIfNullOrReturn(primaryType, nameof(primaryType)); - this.InternalName = this.ObjectType.FriendlyName(); + this.InternalFullName = this.ObjectType.FriendlyName(); this.Publish = true; this.SourceResolver = this; this.AppliedDirectives = new AppliedDirectiveCollection(this); @@ -106,7 +106,7 @@ public virtual string SerializeToQueryLanguage(object item) public virtual Type ObjectType { get; } /// - public virtual string InternalName { get; } + public virtual string InternalFullName { get; } /// public string Description { get; set; } diff --git a/src/graphql-aspnet/Schemas/TypeSystem/VirtualGraphField.cs b/src/graphql-aspnet/Schemas/TypeSystem/VirtualGraphField.cs index 6bc765673..b88233e19 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/VirtualGraphField.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/VirtualGraphField.cs @@ -66,7 +66,7 @@ public VirtualGraphField( this.TypeExpression = new GraphTypeExpression(parentTypeName); this.Arguments = new GraphFieldArgumentCollection(this); this.Resolver = new GraphControllerRouteFieldResolver(new VirtualResolvedObject(this.TypeExpression.TypeName)); - this.InternalName = $"VirtualField_{this.Name}"; + this.InternalFullName = $"VirtualField_{this.Name}"; // fields made from controller route parameters have no policies directly unto themselves // any controller class level policies are individually added to fields they declare @@ -195,6 +195,6 @@ public virtual bool CanResolveForGraphType(IGraphType graphType) public IAppliedDirectiveCollection AppliedDirectives { get; } /// - public string InternalName { get; } + public string InternalFullName { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/TypeSystem/VirtualGraphFieldArgument.cs b/src/graphql-aspnet/Schemas/TypeSystem/VirtualGraphFieldArgument.cs index 0023939ae..b8cd9db4e 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/VirtualGraphFieldArgument.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/VirtualGraphFieldArgument.cs @@ -27,33 +27,30 @@ public class VirtualGraphFieldArgument : IGraphArgument /// /// The parent graph type that owns this virutal field. /// The name of this field in the object graph. - /// The name of this field as it exists in the .NET code. + /// The fully qualified name of this field as it exists in the .NET code. /// The graph type expression representing this field. /// The route path for this argument. /// The concrete graph type in the server code that this argument is mapped to. /// if set to true indicates that this /// argument has a default value, even if its null. - /// The default value. - /// The argument modifiers. + /// The default value of this argument when not supplied, if any. public VirtualGraphFieldArgument( ISchemaItem parent, string name, - string internalName, + string internalFullName, GraphTypeExpression typeExpression, SchemaItemPath route, Type concreteType, bool hasDefaultValue, - object defaultValue = null, - GraphArgumentModifiers argModifiers = GraphArgumentModifiers.None) + object defaultValue = null) { this.Parent = Validation.ThrowIfNullOrReturn(parent, nameof(parent)); this.ObjectType = Validation.ThrowIfNullOrReturn(concreteType, nameof(concreteType)); - this.InternalName = Validation.ThrowIfNullWhiteSpaceOrReturn(internalName, nameof(internalName)); + this.InternalFullName = Validation.ThrowIfNullWhiteSpaceOrReturn(internalFullName, nameof(internalFullName)); this.Name = Validation.ThrowIfNullWhiteSpaceOrReturn(name, nameof(name)); this.Route = Validation.ThrowIfNullOrReturn(route, nameof(route)); this.ParameterName = this.Name; this.TypeExpression = Validation.ThrowIfNullOrReturn(typeExpression, nameof(typeExpression)); - this.ArgumentModifiers = argModifiers; // by definition (rule 5.4.2.1) a nullable type expression on an argument implies // an optional field. that is to say it has an implicit default value of 'null' @@ -73,7 +70,7 @@ public IGraphArgument Clone(ISchemaItem parent) public Type ObjectType { get; } /// - public string InternalName { get; } + public string InternalFullName { get; } /// public string Name { get; set; } @@ -84,9 +81,6 @@ public IGraphArgument Clone(ISchemaItem parent) /// public object DefaultValue { get; } - /// - public GraphArgumentModifiers ArgumentModifiers { get; } - /// public GraphTypeExpression TypeExpression { get; } diff --git a/src/graphql-aspnet/Schemas/TypeSystem/VirtualObjectGraphType.cs b/src/graphql-aspnet/Schemas/TypeSystem/VirtualObjectGraphType.cs index 1f9bdeca2..d6b62e62c 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/VirtualObjectGraphType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/VirtualObjectGraphType.cs @@ -65,6 +65,6 @@ public IGraphField Extend(IGraphField newField) public Type ObjectType => typeof(VirtualObjectGraphType); /// - public string InternalName => typeof(VirtualObjectGraphType).FriendlyName(); + public string InternalFullName => typeof(VirtualObjectGraphType).FriendlyName(); } } \ No newline at end of file diff --git a/src/graphql-aspnet/graphql-aspnet.csproj b/src/graphql-aspnet/graphql-aspnet.csproj index 8d890b54f..5260e555c 100644 --- a/src/graphql-aspnet/graphql-aspnet.csproj +++ b/src/graphql-aspnet/graphql-aspnet.csproj @@ -12,13 +12,4 @@ - - - - - - - - - \ No newline at end of file diff --git a/src/library-common.props b/src/library-common.props index 70e6b7b20..ebdb37434 100644 --- a/src/library-common.props +++ b/src/library-common.props @@ -1,7 +1,7 @@ - net7.0;net6.0;netstandard2.0; + net7.0;net6.0; latest $(NoWarn);1701;1702;1705;1591;NU1603;IDE0019;IDE0017;RCS1146;RCS1194; @@ -50,6 +50,8 @@ + + @@ -62,20 +64,4 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Controllers/GraphModelStateDictionaryTests.cs b/src/unit-tests/graphql-aspnet-tests/Controllers/GraphModelStateDictionaryTests.cs index 949771a14..8e3660b1c 100644 --- a/src/unit-tests/graphql-aspnet-tests/Controllers/GraphModelStateDictionaryTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Controllers/GraphModelStateDictionaryTests.cs @@ -35,7 +35,6 @@ private ExecutionArgument CreateArgument( argTemplate.Setup(x => x.Name).Returns(name); argTemplate.Setup(x => x.TypeExpression).Returns(new GraphTypeExpression(name, wrappers)); - argTemplate.Setup(x => x.ArgumentModifiers).Returns(GraphArgumentModifiers.None); argTemplate.Setup(x => x.ObjectType).Returns(concreteType); argTemplate.Setup(x => x.ParameterName).Returns(name); diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultScalarTypeProviderTestData/ScalarTestBase.cs b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultScalarTypeProviderTestData/ScalarTestBase.cs index ab0ecfe4b..38625b4f9 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultScalarTypeProviderTestData/ScalarTestBase.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultScalarTypeProviderTestData/ScalarTestBase.cs @@ -28,7 +28,7 @@ protected ScalarTestBase() this.Publish = true; this.IsVirtual = false; this.ObjectType = typeof(ScalarDataType); - this.InternalName = "myInternalName"; + this.InternalFullName = "myInternalName"; this.Route = new SchemaItemPath(AspNet.Execution.SchemaItemCollections.Types, "myScalar"); this.Name = "MyScalar"; this.Description = "my description"; @@ -52,7 +52,7 @@ protected ScalarTestBase() public Type ObjectType { get; set; } - public string InternalName { get; set; } + public string InternalFullName { get; set; } public SchemaItemPath Route { get; set; } diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/FieldMaker_InputFieldTests.cs b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/FieldMaker_InputFieldTests.cs index 086feca65..d57baf4a1 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/FieldMaker_InputFieldTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/FieldMaker_InputFieldTests.cs @@ -38,7 +38,7 @@ public void Parse_NotRequiredValueTypePropertyCheck() // non-nullable value type Assert.AreEqual("Int!", graphField.TypeExpression.ToString()); Assert.AreEqual("[type]/Input_InputTestObject/NotRequiredValueTypeField", graphField.Route.ToString()); - Assert.AreEqual("NotRequiredValueTypeField", graphField.InternalName); + Assert.AreEqual("NotRequiredValueTypeField", graphField.InternalFullName); Assert.AreEqual(typeof(int), graphField.DeclaredReturnType); Assert.AreEqual(1, graphField.AppliedDirectives.Count); @@ -63,7 +63,7 @@ public void Parse_RequiredValueTypePropertyCheck() Assert.AreEqual("Int!", graphField.TypeExpression.ToString()); Assert.AreEqual("[type]/Input_InputTestObject/RequiredValueTypeField", graphField.Route.ToString()); - Assert.AreEqual("RequiredValueTypeField", graphField.InternalName); + Assert.AreEqual("RequiredValueTypeField", graphField.InternalFullName); Assert.AreEqual(typeof(int), graphField.DeclaredReturnType); Assert.AreEqual(0, graphField.AppliedDirectives.Count); @@ -89,7 +89,7 @@ public void Parse_NotRequiredReferenceTypePropertyCheck() // meaning the type expression should also be "nullable" Assert.AreEqual("Input_TwoPropertyObject", graphField.TypeExpression.ToString()); Assert.AreEqual("[type]/Input_InputTestObject/NotRequiredReferenceTypeField", graphField.Route.ToString()); - Assert.AreEqual("NotRequiredReferenceTypeField", graphField.InternalName); + Assert.AreEqual("NotRequiredReferenceTypeField", graphField.InternalFullName); Assert.AreEqual(typeof(TwoPropertyObject), graphField.DeclaredReturnType); Assert.AreEqual(0, graphField.AppliedDirectives.Count); @@ -117,7 +117,7 @@ public void Parse_RequiredReferenceTypePropertyCheck() // the type expression is automatically hoisted to be "non-nullable" Assert.AreEqual("Input_TwoPropertyObject", graphField.TypeExpression.ToString()); Assert.AreEqual("[type]/Input_InputTestObject/RequiredReferenceTypeField", graphField.Route.ToString()); - Assert.AreEqual("RequiredReferenceTypeField", graphField.InternalName); + Assert.AreEqual("RequiredReferenceTypeField", graphField.InternalFullName); Assert.AreEqual(typeof(TwoPropertyObject), graphField.DeclaredReturnType); Assert.AreEqual(0, graphField.AppliedDirectives.Count); @@ -143,7 +143,7 @@ public void Parse_RequiredNonNullableReferenceTypePropertyCheck() // the type expression is automatically hoisted to be "non-nullable" Assert.AreEqual("Input_TwoPropertyObject!", graphField.TypeExpression.ToString()); Assert.AreEqual("[type]/Input_InputTestObject/RequiredReferenceExplicitNonNullTypeField", graphField.Route.ToString()); - Assert.AreEqual("RequiredReferenceExplicitNonNullTypeField", graphField.InternalName); + Assert.AreEqual("RequiredReferenceExplicitNonNullTypeField", graphField.InternalFullName); Assert.AreEqual(typeof(TwoPropertyObject), graphField.DeclaredReturnType); Assert.AreEqual(0, graphField.AppliedDirectives.Count); @@ -168,7 +168,7 @@ public void Parse_RequiredGraphIdPropertyCheck() // scalar is required by default Assert.AreEqual("ID!", graphField.TypeExpression.ToString()); Assert.AreEqual("[type]/Input_InputTestObject/GraphIdRequired", graphField.Route.ToString()); - Assert.AreEqual("GraphIdRequired", graphField.InternalName); + Assert.AreEqual("GraphIdRequired", graphField.InternalFullName); Assert.AreEqual(typeof(GraphId), graphField.DeclaredReturnType); Assert.AreEqual(0, graphField.AppliedDirectives.Count); @@ -192,7 +192,7 @@ public void Parse_NotRequiredGraphIdPropertyCheck() Assert.AreEqual("ID!", graphField.TypeExpression.ToString()); Assert.AreEqual("[type]/Input_InputTestObject/GraphIdNotRequired", graphField.Route.ToString()); - Assert.AreEqual("GraphIdNotRequired", graphField.InternalName); + Assert.AreEqual("GraphIdNotRequired", graphField.InternalFullName); Assert.AreEqual(typeof(GraphId), graphField.DeclaredReturnType); Assert.AreEqual(0, graphField.AppliedDirectives.Count); @@ -216,7 +216,7 @@ public void Parse_NotRequiredNullableGraphIdPropertyCheck() Assert.AreEqual("ID", graphField.TypeExpression.ToString()); Assert.AreEqual("[type]/Input_InputTestObject/GraphIdNullable", graphField.Route.ToString()); - Assert.AreEqual("GraphIdNullable", graphField.InternalName); + Assert.AreEqual("GraphIdNullable", graphField.InternalFullName); Assert.AreEqual(typeof(GraphId?), graphField.DeclaredReturnType); Assert.AreEqual(0, graphField.AppliedDirectives.Count); diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/FieldMaker_StandardFieldTests.cs b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/FieldMaker_StandardFieldTests.cs index 5e4db2787..a997abb72 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/FieldMaker_StandardFieldTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/FieldMaker_StandardFieldTests.cs @@ -113,7 +113,6 @@ public void Parse_MethodWithNullableEnum_ParsesCorrectly() var graphArg = Enumerable.FirstOrDefault(graphField.Arguments); Assert.IsNotNull(graphArg); Assert.IsEmpty(graphArg.TypeExpression.Wrappers); - Assert.AreEqual(GraphArgumentModifiers.None, graphArg.ArgumentModifiers); } [Test] diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionTests.cs index 3b5e2bef6..09625a8ca 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionTests.cs @@ -930,7 +930,7 @@ public async Task TypeExtension_OnValueType_ResolvesDataCorrectly() [Test] public async Task TypeExtension_OnGeneralObject_ResolvesDataCorrectly() { - var server = new TestServerBuilder() + var server = new TestServerBuilder(TestOptions.IncludeExceptions) .AddType() .Build(); diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/TypeSystemDirectiveTestData/ToUpperWrapperResolver.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/TypeSystemDirectiveTestData/ToUpperWrapperResolver.cs index ddaac8c46..79e32cf45 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/TypeSystemDirectiveTestData/ToUpperWrapperResolver.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/TypeSystemDirectiveTestData/ToUpperWrapperResolver.cs @@ -24,11 +24,11 @@ public ToUpperWrapperResolver(IGraphFieldResolver originalResolver) _originalResolver = originalResolver; } - public Type ObjectType { get; } - public async Task ResolveAsync(FieldResolutionContext context, CancellationToken cancelToken = default) { await _originalResolver.ResolveAsync(context, cancelToken); } + + public IGraphFieldResolverMetaData MetaData => _originalResolver.MetaData; } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ArgumentTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ArgumentTemplateTests.cs index a4d49f9c9..46d2b99d8 100644 --- a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ArgumentTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ArgumentTemplateTests.cs @@ -37,6 +37,7 @@ private AspNet.Internal.TypeTemplates.GraphArgumentTemplate ExtractParameterTemp mockMethod.Setup(x => x.InternalFullName) .Returns($"{nameof(ParameterTestClass)}.{nameof(ParameterTestClass.TestMethod)}"); mockMethod.Setup(x => x.ObjectType).Returns(typeof(ParameterTestClass)); + mockMethod.Setup(x => x.Arguments).Returns(new List()); var route = new SchemaItemPath(SchemaItemPath.Join( SchemaItemCollections.Query, diff --git a/src/unit-tests/graphql-aspnet-tests/Logging/ActionMethodModelStateValidatedLogEntryTests.cs b/src/unit-tests/graphql-aspnet-tests/Logging/ActionMethodModelStateValidatedLogEntryTests.cs index bc135115c..9b12dcf51 100644 --- a/src/unit-tests/graphql-aspnet-tests/Logging/ActionMethodModelStateValidatedLogEntryTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Logging/ActionMethodModelStateValidatedLogEntryTests.cs @@ -40,7 +40,6 @@ private ExecutionArgument CreateArgument( argTemplate.Setup(x => x.Name).Returns(name); argTemplate.Setup(x => x.TypeExpression).Returns(new GraphTypeExpression(name, wrappers)); - argTemplate.Setup(x => x.ArgumentModifiers).Returns(GraphArgumentModifiers.None); argTemplate.Setup(x => x.ObjectType).Returns(concreteType); argTemplate.Setup(x => x.ParameterName).Returns(name); diff --git a/src/unit-tests/graphql-aspnet-tests/Logging/GeneralEventLogEntryPropertyChecks.cs b/src/unit-tests/graphql-aspnet-tests/Logging/GeneralEventLogEntryPropertyChecks.cs index 7bef9f034..efe574a46 100644 --- a/src/unit-tests/graphql-aspnet-tests/Logging/GeneralEventLogEntryPropertyChecks.cs +++ b/src/unit-tests/graphql-aspnet-tests/Logging/GeneralEventLogEntryPropertyChecks.cs @@ -506,7 +506,7 @@ public void TypeSystemDirectiveAppliedLogEntry() { var directive = new Mock(); directive.Setup(x => x.Name).Returns("The Directive"); - directive.Setup(x => x.InternalName).Returns("The Directive Internal"); + directive.Setup(x => x.InternalFullName).Returns("The Directive Internal"); var item = new Mock(); item.Setup(x => x.Route).Returns(new AspNet.Schemas.Structural.SchemaItemPath(SchemaItemCollections.Types, "path1")); @@ -515,7 +515,7 @@ public void TypeSystemDirectiveAppliedLogEntry() Assert.AreEqual(LogEventIds.TypeSystemDirectiveApplied.Id, entry.EventId); Assert.AreEqual(directive.Object.Name, entry.DirectiveName); - Assert.AreEqual(directive.Object.InternalName, entry.DirectiveInternalName); + Assert.AreEqual(directive.Object.InternalFullName, entry.DirectiveInternalName); Assert.AreEqual(item.Object.Route.Path, entry.SchemaItemPath); Assert.AreEqual(typeof(GraphSchema).FriendlyName(true), entry.SchemaTypeName); } @@ -525,7 +525,7 @@ public void ExecutionDirectiveAppliedLogEntry() { var directive = new Mock(); directive.Setup(x => x.Name).Returns("The Directive"); - directive.Setup(x => x.InternalName).Returns("The Directive Internal"); + directive.Setup(x => x.InternalFullName).Returns("The Directive Internal"); var docPart = new DocumentOperation( new Mock().Object, @@ -539,7 +539,7 @@ public void ExecutionDirectiveAppliedLogEntry() Assert.AreEqual(LogEventIds.ExecutionDirectiveApplied.Id, entry.EventId); Assert.AreEqual(directive.Object.Name, entry.DirectiveName); - Assert.AreEqual(directive.Object.InternalName, entry.DirectiveInternalName); + Assert.AreEqual(directive.Object.InternalFullName, entry.DirectiveInternalName); Assert.AreEqual(DirectiveLocation.QUERY.ToString(), entry.DirectiveLocation); Assert.AreEqual(typeof(GraphSchema).FriendlyName(true), entry.SchemaTypeName); Assert.AreEqual(33, entry.SourceLine); diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GraphFieldArgumentCloningTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GraphFieldArgumentCloningTests.cs index 696775bf1..7d050f1c7 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/GraphFieldArgumentCloningTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GraphFieldArgumentCloningTests.cs @@ -34,7 +34,6 @@ public void ClonedArgument_PropertyCheck() "argName", GraphTypeExpression.FromDeclaration("String"), new SchemaItemPath("[type]/GraphType1/Field1/Arg1"), - GraphArgumentModifiers.ParentFieldResult, "paramName", "internalName", typeof(string), @@ -53,8 +52,7 @@ public void ClonedArgument_PropertyCheck() Assert.AreEqual(arg.Description, clonedArg.Description); Assert.AreEqual(arg.DefaultValue, clonedArg.DefaultValue); Assert.AreEqual(arg.ObjectType, clonedArg.ObjectType); - Assert.AreEqual(arg.InternalName, clonedArg.InternalName); - Assert.AreEqual(arg.ArgumentModifiers, clonedArg.ArgumentModifiers); + Assert.AreEqual(arg.InternalFullName, clonedArg.InternalFullName); Assert.AreEqual(arg.TypeExpression, clonedArg.TypeExpression); Assert.AreEqual(arg.ParameterName, clonedArg.ParameterName); Assert.AreEqual(arg.AppliedDirectives.Count, arg.AppliedDirectives.Count); diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GraphFieldCloningTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GraphFieldCloningTests.cs index 73e3a3bc9..480b14460 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/GraphFieldCloningTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GraphFieldCloningTests.cs @@ -61,7 +61,6 @@ public void MethodField_PropertyCheck() "arg1", GraphTypeExpression.FromDeclaration("String"), field.Route.CreateChild("arg1"), - GraphArgumentModifiers.None, "arg1", "arg1", typeof(string), @@ -91,7 +90,7 @@ public void MethodField_PropertyCheck() Assert.AreEqual(field.DeprecationReason, clonedField.DeprecationReason); Assert.AreEqual(field.Complexity, clonedField.Complexity); Assert.AreEqual(field.FieldSource, clonedField.FieldSource); - Assert.AreEqual(field.InternalName, clonedField.InternalName); + Assert.AreEqual(field.InternalFullName, clonedField.InternalFullName); Assert.IsFalse(object.ReferenceEquals(field.TypeExpression, clonedField.TypeExpression)); Assert.IsTrue(object.ReferenceEquals(field.Resolver, clonedField.Resolver)); @@ -143,7 +142,6 @@ public void PropertyField_PropertyCheck() "arg1", GraphTypeExpression.FromDeclaration("String"), field.Route.CreateChild("arg1"), - GraphArgumentModifiers.None, "arg1", "arg1", typeof(string), @@ -161,7 +159,7 @@ public void PropertyField_PropertyCheck() var clonedField = field.Clone(clonedParent.Object) as PropertyGraphField; Assert.IsNotNull(clonedField); - Assert.AreEqual(field.InternalName, clonedField.InternalName); + Assert.AreEqual(field.InternalFullName, clonedField.InternalFullName); Assert.AreEqual(field.Name, clonedField.Name); Assert.AreEqual(field.ObjectType, clonedField.ObjectType); Assert.AreEqual(field.DeclaredReturnType, clonedField.DeclaredReturnType); From 22dbae62a835a9e80ea664179a3d8c80d62bd18e Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Tue, 4 Jul 2023 06:36:27 -0700 Subject: [PATCH 24/63] WIP, union list bug --- .../Execution/ExecutionArgumentCollection.cs | 30 ++--- src/graphql-aspnet/GraphQLServerSettings.cs | 1 - .../IGraphFieldResolverParameterMetaData.cs | 6 + .../Resolvers/FieldResolverMetaData.cs | 2 + .../FieldResolverParameterMetaData.cs | 11 +- ...ieldResolverParameterMetaDataCollection.cs | 2 + .../TypeTemplates/GraphArgumentTemplate.cs | 9 ++ .../UnionTypeExecutionTestData/Home.cs | 22 ++++ .../UnionTypeExecutionTestData/IBuilding.cs | 20 ++++ .../UnionTypeExecutionTestData/Television.cs | 16 +++ .../UnrelatedItemsController.cs | 71 ++++++++++++ .../Execution/UnionTypeExecutionTests.cs | 108 ++++++++++++++++++ 12 files changed, 282 insertions(+), 16 deletions(-) create mode 100644 src/unit-tests/graphql-aspnet-tests/Execution/TestData/UnionTypeExecutionTestData/Home.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Execution/TestData/UnionTypeExecutionTestData/IBuilding.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Execution/TestData/UnionTypeExecutionTestData/Television.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Execution/TestData/UnionTypeExecutionTestData/UnrelatedItemsController.cs diff --git a/src/graphql-aspnet/Execution/ExecutionArgumentCollection.cs b/src/graphql-aspnet/Execution/ExecutionArgumentCollection.cs index 9e7052998..f3cedc96d 100644 --- a/src/graphql-aspnet/Execution/ExecutionArgumentCollection.cs +++ b/src/graphql-aspnet/Execution/ExecutionArgumentCollection.cs @@ -76,7 +76,7 @@ public void Add(ExecutionArgument argument) /// public IExecutionArgumentCollection ForContext(GraphFieldExecutionContext fieldContext) { - return new ExecutionArgumentCollection(_arguments, fieldContext); + return new ExecutionArgumentCollection(_arguments, fieldContext); } /// @@ -108,7 +108,7 @@ public object[] PrepareArguments(IGraphFieldResolverMetaData resolverMetadata) { Validation.ThrowIfNull(resolverMetadata, nameof(resolverMetadata)); - var preparedParams = new List(); + var preparedParams = new object[resolverMetadata.Parameters.Count]; for (var i = 0; i < resolverMetadata.Parameters.Count; i++) { @@ -116,6 +116,7 @@ public object[] PrepareArguments(IGraphFieldResolverMetaData resolverMetadata) object passedValue = this.ResolveParameterFromMetadata(parameter); + var schemaListItem = false; if (parameter.ArgumentModifiers.IsPartOfTheSchema()) { // additional checks and coersion if this the value is @@ -136,31 +137,32 @@ public object[] PrepareArguments(IGraphFieldResolverMetaData resolverMetadata) if (graphArgument == null) throw new GraphExecutionException($"Argument '{parameter.InternalName}' was not found on its expected parent."); + schemaListItem = graphArgument.TypeExpression.IsListOfItems; if (passedValue == null && !graphArgument.TypeExpression.IsNullable) { - // technically shouldn't be throwable given the validation routines + // technically shouldn't be possible given the validation routines // but captured here as a saftey net for users // doing custom extensions or implementations throw new GraphExecutionException( $"The parameter '{parameter.InternalName}' for field '{_fieldContext?.Request?.Field?.Route.Path}' could not be resolved from the query document " + "or variable collection and no default value was found."); } + } - // ensure compatible list types between the internally - // tracked data and the target type of the method being invoked - // e.g. convert List => T[] when needed - if (graphArgument.TypeExpression.IsListOfItems) - { - var listMangler = new ListMangler(parameter.ExpectedType); - var result = listMangler.Convert(passedValue); - passedValue = result.Data; - } + // ensure compatible list types between the internally + // tracked data and the target type of the method being invoked + // e.g. convert List => T[] when needed + if (parameter.IsList) + { + var listMangler = new ListMangler(parameter.ExpectedType); + var result = listMangler.Convert(passedValue); + passedValue = result.Data; } - preparedParams.Add(passedValue); + preparedParams[i] = passedValue; } - return preparedParams.ToArray(); + return preparedParams; } private object ResolveParameterFromMetadata(IGraphFieldResolverParameterMetaData argDefinition) diff --git a/src/graphql-aspnet/GraphQLServerSettings.cs b/src/graphql-aspnet/GraphQLServerSettings.cs index daa1cf59e..21483aa84 100644 --- a/src/graphql-aspnet/GraphQLServerSettings.cs +++ b/src/graphql-aspnet/GraphQLServerSettings.cs @@ -11,7 +11,6 @@ namespace GraphQL.AspNet { using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Directives; - using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; /// diff --git a/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverParameterMetaData.cs b/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverParameterMetaData.cs index 1ad385ae9..e2d5318ff 100644 --- a/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverParameterMetaData.cs +++ b/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverParameterMetaData.cs @@ -63,5 +63,11 @@ public interface IGraphFieldResolverParameterMetaData /// /// The default value. object DefaultValue { get; } + + /// + /// Gets a value indicating whether this parameter is expecting a list or collection of items. + /// + /// true if this instance is a list or collection; otherwise, false. + bool IsList { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Internal/Resolvers/FieldResolverMetaData.cs b/src/graphql-aspnet/Internal/Resolvers/FieldResolverMetaData.cs index e250d1144..564a6969a 100644 --- a/src/graphql-aspnet/Internal/Resolvers/FieldResolverMetaData.cs +++ b/src/graphql-aspnet/Internal/Resolvers/FieldResolverMetaData.cs @@ -10,6 +10,7 @@ namespace GraphQL.AspNet.Internal.Resolvers { using System; + using System.Diagnostics; using System.Reflection; using GraphQL.AspNet.Common; using GraphQL.AspNet.Interfaces.Execution; @@ -18,6 +19,7 @@ namespace GraphQL.AspNet.Internal.Resolvers /// A metadata object containing parsed and computed values related to /// C# method that is used a a resolver to a graph field. /// + [DebuggerDisplay("Method: {InternalName}")] internal class FieldResolverMetaData : IGraphFieldResolverMetaData { /// diff --git a/src/graphql-aspnet/Internal/Resolvers/FieldResolverParameterMetaData.cs b/src/graphql-aspnet/Internal/Resolvers/FieldResolverParameterMetaData.cs index 31ab7fc37..086bbb422 100644 --- a/src/graphql-aspnet/Internal/Resolvers/FieldResolverParameterMetaData.cs +++ b/src/graphql-aspnet/Internal/Resolvers/FieldResolverParameterMetaData.cs @@ -10,6 +10,7 @@ namespace GraphQL.AspNet.Internal.Resolvers { using System; + using System.Diagnostics; using System.Reflection; using GraphQL.AspNet.Common; using GraphQL.AspNet.Interfaces.Execution; @@ -19,16 +20,19 @@ namespace GraphQL.AspNet.Internal.Resolvers /// A metadata object containing parsed and computed values related to a single parameter /// on a C# method that is used a a resolver to a graph field. /// + [DebuggerDisplay("Parameter: {InternalName}")] internal class FieldResolverParameterMetaData : IGraphFieldResolverParameterMetaData { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The parameter info for a single parameter within a resolver method. /// The name of the parameter as its declared in source code. /// The full name of the parameter, including namespace, owning object and declared method, as it exists in source code. /// Any modifier attributes for this parameter discovered via templating or set /// at runtime by the target schema. + /// if set to true this parameter is expecting a list + /// of items to be passed to it at runtime. /// The default value assigned to this parameter in source code when the parameter /// was declared. public FieldResolverParameterMetaData( @@ -36,6 +40,7 @@ public FieldResolverParameterMetaData( string internalName, string internalFullName, GraphArgumentModifiers modifiers, + bool isListBasedParameter, object defaultValue = null) { this.ParameterInfo = Validation.ThrowIfNullOrReturn(paramInfo, nameof(paramInfo)); @@ -44,6 +49,7 @@ public FieldResolverParameterMetaData( this.InternalFullName = Validation.ThrowIfNullWhiteSpaceOrReturn(internalFullName, nameof(internalFullName)); this.DefaultValue = defaultValue; this.ArgumentModifiers = modifiers; + this.IsList = isListBasedParameter; } /// @@ -63,5 +69,8 @@ public FieldResolverParameterMetaData( /// public Type ExpectedType { get; } + + /// + public bool IsList { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Internal/Resolvers/FieldResolverParameterMetaDataCollection.cs b/src/graphql-aspnet/Internal/Resolvers/FieldResolverParameterMetaDataCollection.cs index 4a67017c8..e3ba5509f 100644 --- a/src/graphql-aspnet/Internal/Resolvers/FieldResolverParameterMetaDataCollection.cs +++ b/src/graphql-aspnet/Internal/Resolvers/FieldResolverParameterMetaDataCollection.cs @@ -11,6 +11,7 @@ namespace GraphQL.AspNet.Internal.Resolvers { using System.Collections; using System.Collections.Generic; + using System.Diagnostics; using System.Linq; using GraphQL.AspNet.Interfaces.Execution; using GraphQL.AspNet.Schemas.TypeSystem; @@ -18,6 +19,7 @@ namespace GraphQL.AspNet.Internal.Resolvers /// /// A collection of parameter metadata that can be accessed by index in its parent method or by name. /// + [DebuggerDisplay("Count = {Count}")] internal class FieldResolverParameterMetaDataCollection : IGraphFieldResolverParameterMetaDataCollection { private List _parameters; diff --git a/src/graphql-aspnet/Internal/TypeTemplates/GraphArgumentTemplate.cs b/src/graphql-aspnet/Internal/TypeTemplates/GraphArgumentTemplate.cs index c24c9501f..7de158531 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/GraphArgumentTemplate.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/GraphArgumentTemplate.cs @@ -19,6 +19,7 @@ namespace GraphQL.AspNet.Internal.TypeTemplates using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Common; using GraphQL.AspNet.Common.Extensions; + using GraphQL.AspNet.Execution; using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Interfaces.Execution; using GraphQL.AspNet.Interfaces.Internal; @@ -240,11 +241,19 @@ public void ValidateOrThrow() /// public IGraphFieldResolverParameterMetaData CreateResolverMetaData() { + var isValidList = this.TypeExpression.IsListOfItems; + if (!isValidList && this.ArgumentModifiers.IsSourceParameter()) + { + if (this.Parent is IGraphFieldTemplate gft) + isValidList = gft.Mode == FieldResolutionMode.Batch; + } + return new FieldResolverParameterMetaData( this.Parameter, this.InternalName, this.InternalFullName, this.ArgumentModifiers, + isValidList, this.DefaultValue); } diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/UnionTypeExecutionTestData/Home.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/UnionTypeExecutionTestData/Home.cs new file mode 100644 index 000000000..da06094a1 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/UnionTypeExecutionTestData/Home.cs @@ -0,0 +1,22 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Execution.TestData.UnionTypeExecutionTestData +{ + public class Home : IBuilding + { + public string Name { get; set; } + + public int Width { get; set; } + + public int Height { get; set; } + + public int Id { get; set; } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/UnionTypeExecutionTestData/IBuilding.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/UnionTypeExecutionTestData/IBuilding.cs new file mode 100644 index 000000000..753cb6171 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/UnionTypeExecutionTestData/IBuilding.cs @@ -0,0 +1,20 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Execution.TestData.UnionTypeExecutionTestData +{ + public interface IBuilding + { + int Id { get; } + + int Width { get; set; } + + int Height { get; set; } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/UnionTypeExecutionTestData/Television.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/UnionTypeExecutionTestData/Television.cs new file mode 100644 index 000000000..73aa0d457 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/UnionTypeExecutionTestData/Television.cs @@ -0,0 +1,16 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Execution.TestData.UnionTypeExecutionTestData +{ + public class Television + { + public string Name { get; set; } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/UnionTypeExecutionTestData/UnrelatedItemsController.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/UnionTypeExecutionTestData/UnrelatedItemsController.cs new file mode 100644 index 000000000..83a658037 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/UnionTypeExecutionTestData/UnrelatedItemsController.cs @@ -0,0 +1,71 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Execution.TestData.UnionTypeExecutionTestData +{ + using System.Collections.Generic; + using GraphQL.AspNet.Attributes; + using GraphQL.AspNet.Controllers; + using GraphQL.AspNet.Interfaces.Controllers; + + public class UnrelatedItemsController : GraphController + { + + [QueryRoot("retrieveItems", "TheThingsUnion", typeof(Television), typeof(Person), typeof(Home), TypeExpression = "[Type]")] + public IGraphActionResult RetrieveItems() + { + var list = new List(); + list.Add(new Person() + { + Id = 1, + Name = "Bob Smith", + }); + + list.Add(new Television() + { + Name = "Tv 1", + }); + + list.Add(new Home() + { + Id = 1, + Name = "Home 1", + Width = 200, + Height = 300, + }); + + list.Add(new Home() + { + Id = 2, + Name = "Home 2", + Width = 300, + Height = 400, + }); + + return this.Ok(list); + } + + [TypeExtension(typeof(IBuilding), "squareFeet", typeof(int))] + public int BuildingSquareFeet(IBuilding building) + { + return building.Width * building.Height; + } + + [BatchTypeExtension(typeof(IBuilding), "perimeter", typeof(int))] + public IGraphActionResult BuildingPerimeter(IEnumerable buildings) + { + var dic = new Dictionary(); + + foreach (var building in buildings) + dic.Add(building, (building.Width * 2) + (building.Height * 2)); + + return this.Ok(dic); + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/UnionTypeExecutionTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/UnionTypeExecutionTests.cs index ec3b590ca..4a16706df 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/UnionTypeExecutionTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/UnionTypeExecutionTests.cs @@ -282,5 +282,113 @@ ... on Person { Assert.Fail("Expected a specific unhandled exception from the failed union, got none"); } + + [Test] + public async Task WhenMultipleUnrelatedTypesAreReturnedGenerally_AndOneExecutesABatchExtensionForAnImplementedInterface_QueryExecutesCorrectly() + { + var server = new TestServerBuilder(TestOptions.IncludeExceptions) + .AddType() + .AddType() + .AddType() + .AddType() + .AddGraphController() + .Build(); + + // The Items on retrieveItems are not related (Person, Home, TV) + // The method returns the unioned items as a List to the runtime + // + // IBuilding, which home implements, has `.perimeter` built as a batch extension + // and needs to take inthe IEnumerable + // + // The runtime must properlty detect and cast the right items of List + // to a single IEnumerable to correctly invoke the batch extension + var builder = server.CreateQueryContextBuilder() + .AddQueryText( + @"query { + retrieveItems { + ... on Home { + id + name + + #this is a batch extension + perimeter + } + } + }"); + + var expectedOutput = + @"{ + ""data"": { + ""retrieveItems"" : [{ + ""id"" : 1, + ""name"": ""Home 1"", + ""perimeter"": 1000 + }, + { + ""id"" : 2, + ""name"": ""Home 2"", + ""perimeter"": 1400 + }] + } + }"; + + var result = await server.RenderResult(builder); + CommonAssertions.AreEqualJsonStrings(expectedOutput, result); + } + + [Test] + public async Task WhenMultipleUnrelatedTypesAreReturnedGenerally_AndOneExecutesATypeExtensionForAnImplementedInterface_QueryExecutesCorrectly() + { + + var server = new TestServerBuilder() + .AddType() + .AddType() + .AddType() + .AddType() + .AddGraphController() + .Build(); + + // The items on retrieveItems are not related (Person, Home, TV) + // The method returns the unioned items as a List to the runtime + // + // IBuilding, which home implements, has `.squareFeet` built as a type extension + // and needs to take in an IBuilding + // + // The runtime must detect and properly cast the right objects in the unioned list + // to IBuilding to correctly invoke the type extension + var builder = server.CreateQueryContextBuilder() + .AddQueryText( + @"query { + retrieveItems { + ... on Home { + id + name + + #this is a single item type extension + squareFeet + } + } + }"); + + var expectedOutput = + @"{ + ""data"": { + ""retrieveItems"" : [{ + ""id"" : 1, + ""name"": ""Home 1"", + ""squareFeet"": 60000 + }, + { + ""id"" : 2, + ""name"": ""Home 2"", + ""squareFeet"": 120000 + }] + } + }"; + + var result = await server.RenderResult(builder); + CommonAssertions.AreEqualJsonStrings(expectedOutput, result); + } + } } \ No newline at end of file From 2946a8905245e1b140d70d64303a02faec9ae162 Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Tue, 4 Jul 2023 07:28:01 -0700 Subject: [PATCH 25/63] WIP, fixed batch type extension of interface regression --- .../Contexts/SortedFieldExecutionContextList.cs | 6 ++++++ .../Execution/IGraphFieldResolverParameterMetaData.cs | 11 +++++++++++ .../Resolvers/FieldResolverParameterMetaData.cs | 9 +++++++++ .../Components/ProcessChildFieldsMiddleware.cs | 9 ++++++--- .../UnrelatedItemsController.cs | 1 - .../Execution/UnionTypeExecutionTests.cs | 2 -- 6 files changed, 32 insertions(+), 6 deletions(-) diff --git a/src/graphql-aspnet/Execution/Contexts/SortedFieldExecutionContextList.cs b/src/graphql-aspnet/Execution/Contexts/SortedFieldExecutionContextList.cs index 6d3a8471d..21fd51737 100644 --- a/src/graphql-aspnet/Execution/Contexts/SortedFieldExecutionContextList.cs +++ b/src/graphql-aspnet/Execution/Contexts/SortedFieldExecutionContextList.cs @@ -58,5 +58,11 @@ public void Add(GraphFieldExecutionContext context, bool executeInIsolation) /// /// The paralell contexts. public IEnumerable ParalellContexts => _paralellList; + + /// + /// Gets the total number of contexts to be executed. + /// + /// The total number of contexts in this instance. + public int Count => _paralellList.Count + _syncList.Count; } } \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverParameterMetaData.cs b/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverParameterMetaData.cs index e2d5318ff..366f24f21 100644 --- a/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverParameterMetaData.cs +++ b/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverParameterMetaData.cs @@ -37,6 +37,17 @@ public interface IGraphFieldResolverParameterMetaData /// The expected type of data this parameter can accept. Type ExpectedType { get; } + /// + /// Gets the core type represented by + /// + /// + /// If this parameter is not a + /// list this property will be the same as . When this parameter is a list + /// this property will represent the T in List<T> + /// + /// The type of the unwrapped expected parameter. + Type UnwrappedExpectedParameterType { get; } + /// /// Gets the fully qualified name, including namespace, of this item as it exists in the /// .NET code (e.g. Namespace.ObjectType.MethodName). diff --git a/src/graphql-aspnet/Internal/Resolvers/FieldResolverParameterMetaData.cs b/src/graphql-aspnet/Internal/Resolvers/FieldResolverParameterMetaData.cs index 086bbb422..1fa1bf745 100644 --- a/src/graphql-aspnet/Internal/Resolvers/FieldResolverParameterMetaData.cs +++ b/src/graphql-aspnet/Internal/Resolvers/FieldResolverParameterMetaData.cs @@ -45,6 +45,12 @@ public FieldResolverParameterMetaData( { this.ParameterInfo = Validation.ThrowIfNullOrReturn(paramInfo, nameof(paramInfo)); this.ExpectedType = this.ParameterInfo.ParameterType; + this.UnwrappedExpectedParameterType = GraphValidation.EliminateWrappersFromCoreType( + this.ExpectedType, + eliminateEnumerables: true, + eliminateTask: true, + eliminateNullableT: false); + this.InternalName = Validation.ThrowIfNullWhiteSpaceOrReturn(internalName, nameof(internalName)); this.InternalFullName = Validation.ThrowIfNullWhiteSpaceOrReturn(internalFullName, nameof(internalFullName)); this.DefaultValue = defaultValue; @@ -70,6 +76,9 @@ public FieldResolverParameterMetaData( /// public Type ExpectedType { get; } + /// + public Type UnwrappedExpectedParameterType { get; } + /// public bool IsList { get; } } diff --git a/src/graphql-aspnet/Middleware/FieldExecution/Components/ProcessChildFieldsMiddleware.cs b/src/graphql-aspnet/Middleware/FieldExecution/Components/ProcessChildFieldsMiddleware.cs index f82688dff..bf18ecd5f 100644 --- a/src/graphql-aspnet/Middleware/FieldExecution/Components/ProcessChildFieldsMiddleware.cs +++ b/src/graphql-aspnet/Middleware/FieldExecution/Components/ProcessChildFieldsMiddleware.cs @@ -28,6 +28,7 @@ namespace GraphQL.AspNet.Middleware.FieldExecution.Components using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Internal; /// /// A middleware component that, when a result exists on the context, invokes the next set @@ -109,8 +110,6 @@ private async Task ProcessDownStreamFieldContextsAsync(GraphFieldExecutionContex return; } - var allChildPipelines = new List(); - // Step 0 // ----------------------------------------------------------------------- // create a lookup of source items by concrete type known to the schema, for easy seperation to the individual @@ -178,6 +177,8 @@ private async Task ProcessDownStreamFieldContextsAsync(GraphFieldExecutionContex } } + var allChildPipelines = new List(executableChildContexts.Count); + // Step 4 // --------------------------------- // Execute all the child contexts. Isolating those that need to be @@ -365,7 +366,9 @@ private IEnumerable CreateChildExecutionContexts( // create a list to house the raw source data being passed for the batch // this is the IEnumerable required as an input to any batch resolver - var sourceArgumentType = parentContext.Field.ObjectType ?? typeof(object); + var coreSourceParamType = childInvocationContext.Field.Resolver.MetaData.Parameters.SourceParameter?.UnwrappedExpectedParameterType; + + var sourceArgumentType = coreSourceParamType ?? typeof(object); var sourceListType = typeof(List<>).MakeGenericType(sourceArgumentType); var sourceDataList = InstanceFactory.CreateInstance(sourceListType, sourceItemsToInclude.Count) as IList; diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/UnionTypeExecutionTestData/UnrelatedItemsController.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/UnionTypeExecutionTestData/UnrelatedItemsController.cs index 83a658037..33e0462be 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/UnionTypeExecutionTestData/UnrelatedItemsController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/UnionTypeExecutionTestData/UnrelatedItemsController.cs @@ -16,7 +16,6 @@ namespace GraphQL.AspNet.Tests.Execution.TestData.UnionTypeExecutionTestData public class UnrelatedItemsController : GraphController { - [QueryRoot("retrieveItems", "TheThingsUnion", typeof(Television), typeof(Person), typeof(Home), TypeExpression = "[Type]")] public IGraphActionResult RetrieveItems() { diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/UnionTypeExecutionTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/UnionTypeExecutionTests.cs index 4a16706df..f4a4fd4fe 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/UnionTypeExecutionTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/UnionTypeExecutionTests.cs @@ -339,7 +339,6 @@ ... on Home { [Test] public async Task WhenMultipleUnrelatedTypesAreReturnedGenerally_AndOneExecutesATypeExtensionForAnImplementedInterface_QueryExecutesCorrectly() { - var server = new TestServerBuilder() .AddType() .AddType() @@ -389,6 +388,5 @@ ... on Home { var result = await server.RenderResult(builder); CommonAssertions.AreEqualJsonStrings(expectedOutput, result); } - } } \ No newline at end of file From 409307221f7277914ff3b90502201d3993c47317 Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Tue, 4 Jul 2023 14:38:24 -0700 Subject: [PATCH 26/63] WIP, ready to remove global providers --- .../GraphControllers/SearchController.cs | 5 +- .../SchemaArgumentBindingRules.cs | 41 ++++++ .../SchemaDeclarationConfiguration.cs | 14 ++ .../Engine/TypeMakers/GraphArgumentMaker.cs | 4 +- .../Execution/ExecutionArgumentCollection.cs | 26 ++-- .../ISchemaDeclarationConfiguration.cs | 9 +- .../Internal/IGraphArgumentTemplate.cs | 2 +- .../Schema/IGraphArgumentCollection.cs | 8 +- .../FieldResolverParameterMetaData.cs | 2 +- .../TypeTemplates/GraphArgumentTemplate.cs | 16 ++- .../Schemas/GraphSchemaManager.cs | 3 + .../GraphArgumentValidator.cs | 4 +- .../GraphFieldArgumentCollection.cs | 20 ++- .../TypeSystem/GraphArgumentModifiers.cs | 11 +- .../GraphArgumentModifiersExtensions.cs | 16 ++- .../GeneralQueryExecutionRuntimeFieldTests.cs | 131 ++++++++++++++++++ .../RuntimeFieldTestData/IInjectedService.cs | 16 +++ .../RuntimeFieldTestData/InjectedService.cs | 19 +++ .../Schemas/IExternalArgumentChecker.cs | 12 ++ 19 files changed, 324 insertions(+), 35 deletions(-) create mode 100644 src/graphql-aspnet/Configuration/SchemaArgumentBindingRules.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Execution/TestData/RuntimeFieldTestData/IInjectedService.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Execution/TestData/RuntimeFieldTestData/InjectedService.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/IExternalArgumentChecker.cs diff --git a/src/ancillary-projects/starwars/starwars-common/GraphControllers/SearchController.cs b/src/ancillary-projects/starwars/starwars-common/GraphControllers/SearchController.cs index 6d5ad6cbe..149e82b63 100644 --- a/src/ancillary-projects/starwars/starwars-common/GraphControllers/SearchController.cs +++ b/src/ancillary-projects/starwars/starwars-common/GraphControllers/SearchController.cs @@ -11,15 +11,12 @@ namespace GraphQL.AspNet.StarwarsAPI.Common.GraphControllers { using System.Collections.Generic; using System.ComponentModel; - using System.Linq; using System.Threading.Tasks; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Interfaces.Controllers; - using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.StarwarsAPI.Common.Model; using GraphQL.AspNet.StarwarsAPI.Common.Services; - using Microsoft.AspNetCore.Authorization; /// /// A controller to handle search queries across the spectrum of the star wars universe. @@ -42,7 +39,7 @@ public SearchController(IStarWarsDataService starWarsData) /// /// The text to search for. /// Task<IGraphActionResult>. - [QueryRoot("search","SearchResults", typeof(Droid), typeof(Human), typeof(Starship), TypeExpression = "[Type]")] + [QueryRoot("search", "SearchResults", typeof(Droid), typeof(Human), typeof(Starship), TypeExpression = "[Type]")] [Description("Searches for the specified text as the name of a starship or character (not case sensitive).")] public async Task GlobalSearch(string searchText = "*") { diff --git a/src/graphql-aspnet/Configuration/SchemaArgumentBindingRules.cs b/src/graphql-aspnet/Configuration/SchemaArgumentBindingRules.cs new file mode 100644 index 000000000..71d39dc5c --- /dev/null +++ b/src/graphql-aspnet/Configuration/SchemaArgumentBindingRules.cs @@ -0,0 +1,41 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Configuration +{ + /// + /// A declaration of the possible rules used by a schema to determine which + /// arguments should be injected by a DI container and which should be part of the + /// a query. + /// + public enum SchemaArgumentBindingRules + { + /// + /// Undecorated arguments will be treated as being part of the schema if the declared .NET type of the + /// argument is part of the schema. If the argument type is not part of the schema, + /// the runtime will attempt to be resolved from the DI container when a query executes. + /// + ArgumentsPreferQueryResolution = 0, + + /// + /// All arguments intended to be part of the schema must be explicitly decorated using + /// [FromGraphQL]. Undecorated arguments will be treated as needing to be resolved + /// from a DI container when a query execute. Undecorated arguments WILL NOT be included as part of the schema. + /// + ArgumentsRequireGraphQlDeclaration = 1, + + /// + /// All arguments intended to be resolved from the DI container during query execution must be explicitly + /// declared using [FromServices]. + /// Undecorated arguments will be treated as being resolved from a query and WILL be included + /// as part of the schema. + /// + ArgumentsRequireDiDeclaration = 2, + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/SchemaDeclarationConfiguration.cs b/src/graphql-aspnet/Configuration/SchemaDeclarationConfiguration.cs index fd0d5da52..2ef2a8225 100644 --- a/src/graphql-aspnet/Configuration/SchemaDeclarationConfiguration.cs +++ b/src/graphql-aspnet/Configuration/SchemaDeclarationConfiguration.cs @@ -29,8 +29,13 @@ public class SchemaDeclarationConfiguration : ISchemaDeclarationConfiguration public SchemaDeclarationConfiguration() { this.AllowedOperations = new HashSet(); + this.ArgumentBindingRules = new HashSet(); + this.AllowedOperations.Add(GraphOperationType.Query); this.AllowedOperations.Add(GraphOperationType.Mutation); + + this.ArgumentBindingRules + .Add(Configuration.SchemaArgumentBindingRules.ArgumentsPreferQueryResolution); } /// @@ -51,11 +56,20 @@ public void Merge(ISchemaDeclarationConfiguration config) foreach (var op in config.AllowedOperations) this.AllowedOperations.Add(op); } + + if (config.ArgumentBindingRules != null) + { + foreach (var rule in config.ArgumentBindingRules) + this.ArgumentBindingRules.Add(rule); + } } /// public bool DisableIntrospection { get; set; } + /// + public HashSet ArgumentBindingRules { get; } + /// public TemplateDeclarationRequirements FieldDeclarationRequirements { get; set; } = TemplateDeclarationRequirements.Default; diff --git a/src/graphql-aspnet/Engine/TypeMakers/GraphArgumentMaker.cs b/src/graphql-aspnet/Engine/TypeMakers/GraphArgumentMaker.cs index 042932eee..564ba372d 100644 --- a/src/graphql-aspnet/Engine/TypeMakers/GraphArgumentMaker.cs +++ b/src/graphql-aspnet/Engine/TypeMakers/GraphArgumentMaker.cs @@ -44,8 +44,8 @@ public GraphArgumentCreationResult CreateArgument(ISchemaItem owner, IGraphArgum formatter.FormatFieldName(template.Name), template.TypeExpression.CloneTo(formatter.FormatGraphTypeName(template.TypeExpression.TypeName)), template.Route, - template.DeclaredArgumentName, - template.InternalName, + template.ParameterName, + template.InternalFullName, template.ObjectType, template.HasDefaultValue, template.DefaultValue, diff --git a/src/graphql-aspnet/Execution/ExecutionArgumentCollection.cs b/src/graphql-aspnet/Execution/ExecutionArgumentCollection.cs index f3cedc96d..90974ebe8 100644 --- a/src/graphql-aspnet/Execution/ExecutionArgumentCollection.cs +++ b/src/graphql-aspnet/Execution/ExecutionArgumentCollection.cs @@ -114,7 +114,7 @@ public object[] PrepareArguments(IGraphFieldResolverMetaData resolverMetadata) { var parameter = resolverMetadata.Parameters[i]; - object passedValue = this.ResolveParameterFromMetadata(parameter); + object passedValue = this.ResolveParameterValue(parameter); var schemaListItem = false; if (parameter.ArgumentModifiers.IsPartOfTheSchema()) @@ -125,14 +125,14 @@ public object[] PrepareArguments(IGraphFieldResolverMetaData resolverMetadata) .Request .Field .Arguments - .FindArgumentByInternalName(parameter.InternalName); + .FindArgumentByParameterName(parameter.InternalName); graphArgument = graphArgument ?? _directiveContext? .Request .Directive .Arguments - .FindArgumentByInternalName(parameter.InternalName); + .FindArgumentByParameterName(parameter.InternalName); if (graphArgument == null) throw new GraphExecutionException($"Argument '{parameter.InternalName}' was not found on its expected parent."); @@ -165,32 +165,32 @@ public object[] PrepareArguments(IGraphFieldResolverMetaData resolverMetadata) return preparedParams; } - private object ResolveParameterFromMetadata(IGraphFieldResolverParameterMetaData argDefinition) + private object ResolveParameterValue(IGraphFieldResolverParameterMetaData parameterDefinition) { - if (argDefinition == null) + if (parameterDefinition == null) return null; - if (argDefinition.ArgumentModifiers.IsSourceParameter()) + if (parameterDefinition.ArgumentModifiers.IsSourceParameter()) return this.SourceData; - if (argDefinition.ArgumentModifiers.IsCancellationToken()) + if (parameterDefinition.ArgumentModifiers.IsCancellationToken()) return _fieldContext?.CancellationToken ?? default; - if (argDefinition.ArgumentModifiers.IsInjected()) + if (parameterDefinition.ArgumentModifiers.IsInjected()) { if (_fieldContext != null) - return _fieldContext.ServiceProvider.GetService(argDefinition.ExpectedType); + return _fieldContext.ServiceProvider.GetService(parameterDefinition.ExpectedType); if (_directiveContext != null) - return _directiveContext.ServiceProvider.GetService(argDefinition.ExpectedType); + return _directiveContext.ServiceProvider.GetService(parameterDefinition.ExpectedType); return null; } - if (this.ContainsKey(argDefinition.InternalName)) - return this[argDefinition.InternalName].Value; + if (this.ContainsKey(parameterDefinition.InternalName)) + return this[parameterDefinition.InternalName].Value; - return argDefinition.DefaultValue; + return parameterDefinition.DefaultValue; } /// diff --git a/src/graphql-aspnet/Interfaces/Configuration/ISchemaDeclarationConfiguration.cs b/src/graphql-aspnet/Interfaces/Configuration/ISchemaDeclarationConfiguration.cs index c34218189..f3db6a802 100644 --- a/src/graphql-aspnet/Interfaces/Configuration/ISchemaDeclarationConfiguration.cs +++ b/src/graphql-aspnet/Interfaces/Configuration/ISchemaDeclarationConfiguration.cs @@ -13,7 +13,6 @@ namespace GraphQL.AspNet.Interfaces.Configuration using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Configuration.Formatting; - using GraphQL.AspNet.Execution; using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Schemas.TypeSystem; @@ -42,6 +41,14 @@ public interface ISchemaDeclarationConfiguration /// The declaration requirements for this schema. TemplateDeclarationRequirements FieldDeclarationRequirements { get; } + /// + /// Gets the defined rules this schema should use when inspecting implicit or late bound + /// field arguments before the schema is placed online. These rules do not effect explicitly + /// declared arguments that use [FromGraphQL] or [FromServices]. + /// + /// The schema item binding rules to obey. + HashSet ArgumentBindingRules { get; } + /// /// Gets an object used to format the declared names in your C# code as various items in the type system /// for this . diff --git a/src/graphql-aspnet/Interfaces/Internal/IGraphArgumentTemplate.cs b/src/graphql-aspnet/Interfaces/Internal/IGraphArgumentTemplate.cs index 424aa6ef9..661b87197 100644 --- a/src/graphql-aspnet/Interfaces/Internal/IGraphArgumentTemplate.cs +++ b/src/graphql-aspnet/Interfaces/Internal/IGraphArgumentTemplate.cs @@ -55,7 +55,7 @@ public interface IGraphArgumentTemplate : ISchemaItemTemplate /// Gets the name of the argument as its declared in the server side code. /// /// The name of the declared argument. - string DeclaredArgumentName { get; } + string ParameterName { get; } /// /// Gets the input type of this argument as its declared in the C# code base with no modifications or diff --git a/src/graphql-aspnet/Interfaces/Schema/IGraphArgumentCollection.cs b/src/graphql-aspnet/Interfaces/Schema/IGraphArgumentCollection.cs index bb03714d6..05c90057a 100644 --- a/src/graphql-aspnet/Interfaces/Schema/IGraphArgumentCollection.cs +++ b/src/graphql-aspnet/Interfaces/Schema/IGraphArgumentCollection.cs @@ -56,6 +56,12 @@ IGraphArgument AddArgument( Type concreteType, object defaultValue); + /// + /// Removes the specified argument instance from this collection. + /// + /// The argument to remove. + void Remove(IGraphArgument arg); + /// /// Determines whether this collection contains a . Argument /// names are case sensitive and should match the public name as its defined on the target schema @@ -79,7 +85,7 @@ IGraphArgument AddArgument( /// /// The internal name of the argument. /// IGraphArgument. - IGraphArgument FindArgumentByInternalName(string internalName); + IGraphArgument FindArgumentByParameterName(string internalName); /// /// Gets the with the specified name. Argument diff --git a/src/graphql-aspnet/Internal/Resolvers/FieldResolverParameterMetaData.cs b/src/graphql-aspnet/Internal/Resolvers/FieldResolverParameterMetaData.cs index 1fa1bf745..fe01700f8 100644 --- a/src/graphql-aspnet/Internal/Resolvers/FieldResolverParameterMetaData.cs +++ b/src/graphql-aspnet/Internal/Resolvers/FieldResolverParameterMetaData.cs @@ -68,7 +68,7 @@ public FieldResolverParameterMetaData( public string InternalName { get; } /// - public GraphArgumentModifiers ArgumentModifiers { get; } + public GraphArgumentModifiers ArgumentModifiers { get; private set; } /// public object DefaultValue { get; } diff --git a/src/graphql-aspnet/Internal/TypeTemplates/GraphArgumentTemplate.cs b/src/graphql-aspnet/Internal/TypeTemplates/GraphArgumentTemplate.cs index 7de158531..fcb446f4c 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/GraphArgumentTemplate.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/GraphArgumentTemplate.cs @@ -64,7 +64,10 @@ public virtual void Parse() _argDeclaration = this.Parameter.SingleAttributeOrDefault(); string name = null; if (_argDeclaration != null) + { name = _argDeclaration?.ArgumentName?.Trim(); + this.ArgumentModifiers = this.ArgumentModifiers | GraphArgumentModifiers.ExplicitSchemaItem; + } if (string.IsNullOrWhiteSpace(name)) name = Constants.Routing.PARAMETER_META_NAME; @@ -73,7 +76,7 @@ public virtual void Parse() // to be consumed from a DI container var fromServicesAttrib = this.Parameter.SingleAttributeOfTypeOrDefault(); if (fromServicesAttrib != null) - this.ArgumentModifiers = this.ArgumentModifiers | GraphArgumentModifiers.Injected; + this.ArgumentModifiers = this.ArgumentModifiers | GraphArgumentModifiers.ExplicitInjected; name = name.Replace(Constants.Routing.PARAMETER_META_NAME, this.Parameter.Name); this.Route = new GraphArgumentFieldPath(this.Parent.Route, name); @@ -234,6 +237,15 @@ public void ValidateOrThrow() $".NET parameter. (Declared '{this.TypeExpression}' is incompatiable with '{actualTypeExpression}') "); } + if (this.ArgumentModifiers.IsPartOfTheSchema() && this.ArgumentModifiers.IsInjected()) + { + throw new GraphTypeDeclarationException( + $"The item '{this.Parent.InternalFullName}' declares an argument '{this.Name}' that " + + $"is defined to be supplied from a graphql query AND from a DI services container. " + + $"An argument can not be supplied from a graphql query and from a DI container. If declaring argument attributes, supply " + + $"{nameof(FromGraphQLAttribute)} or {nameof(FromServicesAttribute)}, but not both."); + } + foreach (var directive in this.AppliedDirectives) directive.ValidateOrThrow(); } @@ -300,7 +312,7 @@ public IGraphFieldResolverParameterMetaData CreateResolverMetaData() public GraphArgumentModifiers ArgumentModifiers { get; protected set; } /// - public string DeclaredArgumentName => this.Parameter.Name; + public string ParameterName => this.Parameter.Name; /// public MetaGraphTypes[] DeclaredTypeWrappers { get; private set; } diff --git a/src/graphql-aspnet/Schemas/GraphSchemaManager.cs b/src/graphql-aspnet/Schemas/GraphSchemaManager.cs index fecfd4b54..052ded9fb 100644 --- a/src/graphql-aspnet/Schemas/GraphSchemaManager.cs +++ b/src/graphql-aspnet/Schemas/GraphSchemaManager.cs @@ -29,6 +29,7 @@ namespace GraphQL.AspNet.Schemas using GraphQL.AspNet.Schemas.TypeSystem.Introspection; using GraphQL.AspNet.Schemas.TypeSystem.Introspection.Fields; using GraphQL.AspNet.Schemas.TypeSystem.Introspection.Model; + using Microsoft.AspNetCore.Mvc; /// /// Assists with the creation of data @@ -38,6 +39,7 @@ namespace GraphQL.AspNet.Schemas internal sealed class GraphSchemaManager { private readonly GraphNameFormatter _formatter; + private readonly Func _externalTypeChecker; /// /// Initializes a new instance of the class. @@ -47,6 +49,7 @@ public GraphSchemaManager(ISchema schema) { this.Schema = Validation.ThrowIfNullOrReturn(schema, nameof(schema)); _formatter = this.Schema.Configuration.DeclarationOptions.GraphNamingFormatter; + this.EnsureSchemaDependencies(); this.EnsureGraphOperationType(GraphOperationType.Query); } diff --git a/src/graphql-aspnet/Schemas/SchemaItemValidators/GraphArgumentValidator.cs b/src/graphql-aspnet/Schemas/SchemaItemValidators/GraphArgumentValidator.cs index 045968d80..d6e80c563 100644 --- a/src/graphql-aspnet/Schemas/SchemaItemValidators/GraphArgumentValidator.cs +++ b/src/graphql-aspnet/Schemas/SchemaItemValidators/GraphArgumentValidator.cs @@ -48,8 +48,8 @@ public override void ValidateOrThrow(ISchemaItem schemaItem, ISchema schema) if (argument.ObjectType.IsInterface) { throw new GraphTypeDeclarationException( - $"The item '{argument.InternalFullName}' declares an argument '{argument.Name}' of type '{argument.ObjectType.FriendlyName()}' " + - $"which is an interface. Interfaces cannot be used as input arguments to any type."); + $"The argument '{argument.Name}' on '{argument.Parent.Route.Path}' is of type '{argument.ObjectType.FriendlyName()}', " + + $"which is an interface. Interfaces cannot be used as input arguments to any graph type."); } } } diff --git a/src/graphql-aspnet/Schemas/Structural/GraphFieldArgumentCollection.cs b/src/graphql-aspnet/Schemas/Structural/GraphFieldArgumentCollection.cs index a63c6388b..097d44ce3 100644 --- a/src/graphql-aspnet/Schemas/Structural/GraphFieldArgumentCollection.cs +++ b/src/graphql-aspnet/Schemas/Structural/GraphFieldArgumentCollection.cs @@ -46,7 +46,7 @@ public IGraphArgument AddArgument(IGraphArgument argument) Validation.ThrowIfNull(argument, nameof(argument)); _arguments.Add(argument.Name, argument); - _argumentByInternalName.Add(argument.InternalFullName, argument); + _argumentByInternalName.Add(argument.ParameterName, argument); return argument; } @@ -106,6 +106,18 @@ public IGraphArgument AddArgument( return this.AddArgument(argument); } + /// + public void Remove(IGraphArgument arg) + { + if (arg == null) + return; + + if (_argumentByInternalName.ContainsKey(arg.ParameterName)) + _argumentByInternalName.Remove(arg.ParameterName); + if (_arguments.ContainsKey(arg.Name)) + _arguments.Remove(arg.Name); + } + /// public bool ContainsKey(string argumentName) { @@ -125,10 +137,10 @@ public IGraphArgument FindArgument(string argumentName) } /// - public IGraphArgument FindArgumentByInternalName(string internalName) + public IGraphArgument FindArgumentByParameterName(string parameterName) { - if (_argumentByInternalName.ContainsKey(internalName)) - return _argumentByInternalName[internalName]; + if (_argumentByInternalName.ContainsKey(parameterName)) + return _argumentByInternalName[parameterName]; return null; } diff --git a/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiers.cs b/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiers.cs index 1d387226e..6f0fe49ea 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiers.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiers.cs @@ -38,9 +38,16 @@ public enum GraphArgumentModifiers CancellationToken = 4, /// - /// This parameter is supplied to a field via a DI Container injection. It will not be exposed + /// This parameter is declared to be resolved via a DI Container injection. It WILL NEVER be exposed /// on the object graph. /// - Injected = 8, + ExplicitInjected = 8, + + /// + /// This parameter is declared to be resolved as an argument to a graph field. It WILL ALWAYS be + /// exposed on the object graph. If the argument cannot be exposed because of a rule violation the + /// schema will fail to build. + /// + ExplicitSchemaItem = 16, } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiersExtensions.cs b/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiersExtensions.cs index e1a498a04..f9b58d485 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiersExtensions.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiersExtensions.cs @@ -56,7 +56,19 @@ public static bool IsNotPartOfTheSchema(this GraphArgumentModifiers modifiers) /// true if the modifiers indicate the argument is part of the schema; otherwise, false. public static bool IsPartOfTheSchema(this GraphArgumentModifiers modifiers) { - return modifiers == GraphArgumentModifiers.None; + return modifiers == GraphArgumentModifiers.None + || modifiers.IsExplicitlyPartOfTheSchema(); + } + + /// + /// Determines whether the modifiers indicate that the argument is explicitly declared that it MUST be included in a + /// an externally exposed schema. + /// + /// The modifiers to check. + /// true if the modifiers indicate the argument is explicitly declared to be a part of the schema; otherwise, false. + public static bool IsExplicitlyPartOfTheSchema(this GraphArgumentModifiers modifiers) + { + return modifiers.HasFlag(GraphArgumentModifiers.ExplicitSchemaItem); } /// @@ -67,7 +79,7 @@ public static bool IsPartOfTheSchema(this GraphArgumentModifiers modifiers) /// true if the modifiers indicate the argument is to be resolved from a DI continer; otherwise, false. public static bool IsInjected(this GraphArgumentModifiers modifiers) { - return modifiers.HasFlag(GraphArgumentModifiers.Injected); + return modifiers.HasFlag(GraphArgumentModifiers.ExplicitInjected); } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionRuntimeFieldTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionRuntimeFieldTests.cs index 643f94aa2..b8d8f08ad 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionRuntimeFieldTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionRuntimeFieldTests.cs @@ -14,8 +14,11 @@ namespace GraphQL.AspNet.Tests.Execution using GraphQL.AspNet.Controllers.ActionResults; using GraphQL.AspNet.Interfaces.Controllers; using GraphQL.AspNet.Tests.Execution.TestData.RuntimeFieldTest; + using GraphQL.AspNet.Tests.Execution.TestData.RuntimeFieldTestData; using GraphQL.AspNet.Tests.Framework; using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using Microsoft.AspNetCore.Mvc; + using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; [TestFixture] @@ -245,5 +248,133 @@ public async Task BasicMappedQuery_ReturningActionResult_ResolvesCorrectly() }", result); } + + [Test] + public async Task BasicMappedQuery_WithExplicitlyDeclaredInjectedService_ReturningValueResult_ResolvesCorrectly() + { + var serverBuilder = new TestServerBuilder(); + serverBuilder.AddTransient(); + + serverBuilder.AddGraphQL(o => + { + o.MapQuery("/field1/field2") + .AddResolver((int a, int b, [FromServices] IInjectedService injectedService) => + { + // injected srvice returns 23 + return a + b + injectedService.FetchValue(); + }); + }); + + var server = serverBuilder.Build(); + var builder = server.CreateQueryContextBuilder(); + builder.AddQueryText(@"query { field1 { field2(a: 6, b: 10 } } }"); + + var result = await server.RenderResult(builder); + CommonAssertions.AreEqualJsonStrings( + @"{ + ""data"": { + ""field1"": { + ""field2"" : 39 + } + } + }", + result); + } + + [Test] + public async Task BasicMappedQuery_WithExplicitlyDeclaredInjectedService_ReturningActionResult_ResolvesCorrectly() + { + var serverBuilder = new TestServerBuilder(); + serverBuilder.AddTransient(); + + serverBuilder.AddGraphQL(o => + { + o.MapQuery("/field1/field2") + .AddResolver((int a, int b, [FromServices] IInjectedService injectedService) => + { + // injected srvice returns 23 + return GraphActionResult.Ok(a + b + injectedService.FetchValue()); + }); + }); + + var server = serverBuilder.Build(); + var builder = server.CreateQueryContextBuilder(); + builder.AddQueryText(@"query { field1 { field2(a: 5, b: 33 } } }"); + + var result = await server.RenderResult(builder); + CommonAssertions.AreEqualJsonStrings( + @"{ + ""data"": { + ""field1"": { + ""field2"" : 61 + } + } + }", + result); + } + + [Test] + public async Task BasicMappedQuery_WithImplicitlyDeclaredInjectedService_ReturningValueResult_ResolvesCorrectly() + { + var serverBuilder = new TestServerBuilder(); + serverBuilder.AddTransient(); + + serverBuilder.AddGraphQL(o => + { + o.MapQuery("/field1/field2") + .AddResolver((int a, int b, IInjectedService injectedService) => + { + // injected srvice returns 23 + return a + b + injectedService.FetchValue(); + }); + }); + + var server = serverBuilder.Build(); + var builder = server.CreateQueryContextBuilder(); + builder.AddQueryText(@"query { field1 { field2(a: 6, b: 10 } } }"); + + var result = await server.RenderResult(builder); + CommonAssertions.AreEqualJsonStrings( + @"{ + ""data"": { + ""field1"": { + ""field2"" : 39 + } + } + }", + result); + } + + [Test] + public async Task BasicMappedQuery_WithImplicitlyDeclaredInjectedService_ReturningActionResult_ResolvesCorrectly() + { + var serverBuilder = new TestServerBuilder(); + serverBuilder.AddTransient(); + + serverBuilder.AddGraphQL(o => + { + o.MapQuery("/field1/field2") + .AddResolver((int a, int b, IInjectedService injectedService) => + { + // injected srvice returns 23 + return GraphActionResult.Ok(a + b + injectedService.FetchValue()); + }); + }); + + var server = serverBuilder.Build(); + var builder = server.CreateQueryContextBuilder(); + builder.AddQueryText(@"query { field1 { field2(a: 5, b: 33 } } }"); + + var result = await server.RenderResult(builder); + CommonAssertions.AreEqualJsonStrings( + @"{ + ""data"": { + ""field1"": { + ""field2"" : 61 + } + } + }", + result); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/RuntimeFieldTestData/IInjectedService.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/RuntimeFieldTestData/IInjectedService.cs new file mode 100644 index 000000000..5918b3882 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/RuntimeFieldTestData/IInjectedService.cs @@ -0,0 +1,16 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Execution.TestData.RuntimeFieldTestData +{ + public interface IInjectedService + { + int FetchValue(); + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/RuntimeFieldTestData/InjectedService.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/RuntimeFieldTestData/InjectedService.cs new file mode 100644 index 000000000..e346b010a --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/RuntimeFieldTestData/InjectedService.cs @@ -0,0 +1,19 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Execution.TestData.RuntimeFieldTestData +{ + public class InjectedService : IInjectedService + { + public int FetchValue() + { + return 23; + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/IExternalArgumentChecker.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/IExternalArgumentChecker.cs new file mode 100644 index 000000000..ba2ca2c77 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/IExternalArgumentChecker.cs @@ -0,0 +1,12 @@ +namespace GraphQL.AspNet.Tests.Schemas +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using System.Threading.Tasks; + + internal interface IExternalArgumentChecker + { + } +} From 0bf3a18fe9034114ca3e9cc9d40eedb53ed7a9fc Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Mon, 10 Jul 2023 17:31:21 -0700 Subject: [PATCH 27/63] WIP, primary library switched off of global type providers --- ...ubscriptionEnabledGraphTypeMakerFactory.cs | 62 ++ ...bscriptionEnabledGraphTypeMakerProvider.cs | 28 - ...SubscriptionEnabledTypeTemplateProvider.cs | 39 - .../SubscriptionEnabledGraphFieldMaker.cs | 6 +- ...ptionControllerActionGraphFieldTemplate.cs | 4 +- .../SubscriptionPublisherSchemaExtension.cs | 6 +- .../SubscriptionReceiverSchemaExtension.cs | 7 +- ....cs => DirectiveBindingSchemaExtension.cs} | 26 +- .../Formatting/GraphNameFormatter.cs | 5 +- .../Configuration/SchemaOptions.cs | 22 +- .../Configuration/SchemaTypeToRegister.cs | 4 +- .../Startup/GraphQLSchemaInjector{TSchema}.cs | 21 +- .../Configuration/Startup/SchemaPreCacher.cs | 76 -- .../Engine/DefaultGraphQLSchemaFactory.cs | 223 +++++ ...DefaultGraphQLSchemaFactory_Controllers.cs | 239 +++++ .../DefaultGraphQLSchemaFactory_Directives.cs | 37 + .../DefaultGraphQLSchemaFactory_GraphTypes.cs | 123 +++ ...faultGraphQLSchemaFactory_Introspection.cs | 78 ++ ...GraphQLSchemaFactory_RuntimeDefinitions.cs | 47 + .../DefaultGraphQLSchemaFactory_Validation.cs | 40 + .../Engine/DefaultGraphQLTypeMakerFactory.cs | 147 +++ .../Engine/DefaultGraphTypeMakerProvider.cs | 95 -- .../Engine/DefaultScalarGraphTypeProvider.cs | 286 ------ .../Engine/DefaultTypeTemplateProvider.cs | 134 --- .../Engine/TypeMakers/ObjectGraphTypeMaker.cs | 122 --- .../Engine/TypeMakers/ScalarGraphTypeMaker.cs | 47 - .../Execution/DirectiveProcessorTypeSystem.cs | 4 + .../FieldResolution/FieldDataItem.cs | 5 +- .../Execution/GraphSchemaInitializer.cs | 115 --- .../Resolvers/EnumInputValueResolver.cs | 0 .../Resolvers/EnumLeafValueResolver.cs | 0 .../Resolvers/ExtendedGraphFieldResolver.cs | 0 .../Resolvers/FieldResolverMetaData.cs | 0 .../FieldResolverParameterMetaData.cs | 0 ...ieldResolverParameterMetaDataCollection.cs | 0 ...tionGraphFieldResolver{TSource,TReturn}.cs | 0 .../GraphControllerActionResolver.cs | 0 .../GraphControllerActionResolverBase.cs | 0 .../GraphControllerRouteFieldResolver.cs | 0 .../Resolvers/GraphDirectiveActionResolver.cs | 0 .../Resolvers/InputObjectValueResolver.cs | 0 .../Resolvers/InputValueResolverBase.cs | 0 .../InputValueResolverMethodGenerator.cs | 0 .../InternalFieldResolverMetaData.cs | 0 .../Schema_TypeGraphFieldResolver.cs | 0 .../Type_EnumValuesGraphFieldResolver.cs | 0 .../Type_TypeGraphFieldResolver.cs | 0 .../Resolvers/ListInputValueResolver.cs | 0 .../ObjectMethodGraphFieldResolver.cs | 0 .../ObjectPropertyGraphFieldResolver.cs | 0 .../Resolvers/ScalarInputValueResolver.cs | 0 .../GraphDataItem_ResolveFieldStatus.cs | 13 +- src/graphql-aspnet/GraphQLProviders.cs | 46 +- ...rationExtension.cs => ISchemaExtension.cs} | 9 +- .../Engine/IGraphQLSchemaFactory{TSchema}.cs | 46 + .../Engine/IGraphQLTypeMakerFactory.cs | 73 ++ .../IGraphQLTypeMakerFactory{TSchema}.cs | 23 + .../Interfaces/Engine/IGraphTypeMaker.cs | 8 +- .../Engine/IGraphTypeMakerProvider.cs | 51 -- .../Engine/IGraphTypeTemplateProvider.cs | 59 -- .../Engine/IScalarGraphTypeProvider.cs | 113 --- .../Internal/IScalarGraphTypeTemplate.cs | 26 + .../Internal/IUnionGraphTypeTemplate.cs | 26 + .../Interfaces/Schema/IGraphField.cs | 7 - .../Interfaces/Schema/IScalarGraphType.cs | 11 + .../Schema/ISchemaTypeCollection.cs | 3 +- .../TypeTemplates/GraphArgumentTemplate.cs | 4 +- .../TypeTemplates/GraphFieldTemplateBase.cs | 34 +- .../GraphTypeExtensionFieldTemplate.cs | 6 +- .../InputObjectGraphTypeTemplate.cs | 4 +- .../MethodGraphFieldTemplateBase.cs | 4 +- .../NonLeafGraphTypeTemplateBase.cs | 4 +- .../RuntimeGraphControllerTemplate.cs | 2 +- .../TypeTemplates/ScalarGraphTypeTemplate.cs | 77 ++ .../TypeTemplates/UnionGraphTypeTemplate.cs | 98 ++ .../TypeMakers/DependentTypeCollection.cs | 0 .../Generation}/TypeMakers/DirectiveMaker.cs | 39 +- .../TypeMakers/EnumGraphTypeMaker.cs | 31 +- .../FieldContainerGraphTypeMakerBase.cs | 65 ++ .../TypeMakers/GraphArgumentCreationResult.cs | 0 .../TypeMakers/GraphArgumentMaker.cs | 41 +- .../TypeMakers/GraphFieldCreationResult.cs | 0 .../Generation}/TypeMakers/GraphFieldMaker.cs | 110 ++- .../TypeMakers/GraphMakerExtensions.cs | 0 .../TypeMakers/GraphTypeCreationResult.cs | 0 .../TypeMakers/InputObjectGraphTypeMaker.cs | 36 +- .../TypeMakers/InterfaceGraphTypeMaker.cs | 41 +- .../TypeMakers/ObjectGraphTypeMaker.cs | 93 ++ .../TypeMakers/ScalarGraphTypeMaker.cs | 66 ++ .../TypeMakers/UnionGraphTypeMaker.cs | 35 +- .../Schemas/GraphSchemaManager.cs | 499 ---------- .../Schemas/GraphTypeExpression_Statics.cs | 21 +- .../{Internal => Schemas}/GraphTypeNames.cs | 5 +- .../{Internal => Schemas}/GraphValidation.cs | 30 +- .../GraphFieldValidator.cs | 22 + .../Schemas/TypeSystem/GraphFieldArgument.cs | 2 +- .../Model/IntrospectedDirective.cs | 4 + .../Introspection/Model/IntrospectedField.cs | 5 + .../Introspection/Model/IntrospectedType.cs | 9 + .../Introspection/Model/Introspection.cs | 5 + .../Schemas/TypeSystem/MethodGraphField.cs | 4 - .../Schemas/TypeSystem/PropertyGraphField.cs | 4 +- .../TypeSystem/Scalars/GlobalScalars.cs | 313 +++++++ .../TypeSystem/Scalars/ScalarGraphTypeBase.cs | 16 +- .../Schemas/TypeSystem/SchemaExtensions.cs | 3 + .../TypeCollections/ConcreteTypeCollection.cs | 59 +- .../TypeCollections/SchemaTypeCollection.cs | 11 +- .../MultipartRequestServerExtension.cs | 6 +- .../Schema/FileUploadScalarGraphType.cs | 2 + src/graphql-aspnet/graphql-aspnet.csproj | 4 + .../Configuration/ConfigurationSetupTests.cs | 22 - ...SubscriptionEnabledFieldFieldMakerTests.cs | 4 +- .../GraphQLGlobalSubscriptionRestorePoint.cs | 15 +- .../GraphControllerTemplateTests.cs | 6 +- .../Schemas/GraphSchemaManagerTests.cs | 81 -- .../SubscriptionPublisherExtensionTests.cs | 2 - .../SubscriptionReceiverExtensionTests.cs | 4 - .../GraphQLGlobalRestorePoint.cs | 81 -- .../GraphQLTemplateHelper.cs | 57 +- .../TestServer.cs | 20 +- .../Configuration/ConfigurationSetupTests.cs | 47 - .../Configuration/DirectiveApplicatorTests.cs | 12 +- ...aOptionsCustomLifetimeRegistrationTests.cs | 4 - .../ActionResults/ActionResultTests.cs | 3 + .../ScalarTestBase.cs | 8 + .../Engine/DefaultScalarTypeProviderTests.cs | 176 ---- .../CustomController.cs | 23 + .../CustomDirective.cs | 25 + .../CustomEnum.cs | 17 + .../CustomObjectWithCustomScalarArgument.cs | 23 + .../CustomObjectWithCustomScalarField.cs | 23 + .../CustomObjectWithFieldWithArg.cs | 22 + .../TwoPropertyObjectAsScalar.cs | 34 + .../Engine/DefaultSchemaFactoryTests.cs | 454 ++++++++++ .../TypeMakers/DirectiveTypeMakerTests.cs | 23 +- .../TypeMakers/EnumGraphTypeMakerTests.cs | 44 +- .../TypeMakers/FieldMaker_InputFieldTests.cs | 43 +- .../FieldMaker_StandardFieldTests.cs | 18 +- .../TypeMakers/GraphTypeMakerFactoryTests.cs | 37 - .../TypeMakers/GraphTypeMakerTestBase.cs | 20 +- .../InputObjectGraphTypeMakerTests.cs | 4 +- .../TypeMakers/InterfaceTypeMakerTests.cs | 12 +- .../TypeMakers/ObjectGraphTypeMakerTests.cs | 12 +- .../TypeMakers/ScalarGraphTypeMakerTests.cs | 58 +- .../Engine/TypeMakers/UnionTypeMakerTests.cs | 9 +- .../DirectiveProcessorTypeSystemTests.cs | 22 +- .../GeneralQueryExecutionRuntimeFieldTests.cs | 6 + .../Execution/IntrospectionTests.cs | 5 +- .../TypeSystemDirectiveDiscoveryTests.cs | 5 +- .../Internal/InputResolverGeneratorTests.cs | 5 +- .../Internal/ObjectMethodResolverTests.cs | 25 +- .../Internal/ObjectPropertyResolverTests.cs | 22 +- .../Templating/ArgumentTemplateTests.cs | 14 +- .../Templating/ControllerTemplateTests.cs | 6 +- .../DefaultUnionTemplateProviderTests.cs | 69 -- .../Templating/GraphTypeNamesTests.cs | 19 +- .../MethodGraphFieldTemplateTests.cs | 2 +- .../ObjectGraphTypeTemplateTests.cs | 32 +- .../PropertyGraphFieldTemplateTests.cs | 4 +- .../Schemas/DefaultTypeTests.cs | 7 +- .../Schemas/GraphFieldCloningTests.cs | 2 - .../Schemas/GraphSchemaManagerTests.cs | 849 ------------------ .../Schemas/SchemaLanguageGeneratorTests.cs | 4 +- ...CollectionInterefaceImplementationTests.cs | 22 +- .../Schemas/SchemaTypeCollectionTests.cs | 36 +- .../MultiPartRequestServerExtensionTests.cs | 30 +- .../MultipartRequestExtensionMethodsTests.cs | 12 - ...ltipartRequestGraphQLHttpProcessorTests.cs | 16 +- 168 files changed, 3434 insertions(+), 3599 deletions(-) create mode 100644 src/graphql-aspnet-subscriptions/Engine/SubscriptionEnabledGraphTypeMakerFactory.cs delete mode 100644 src/graphql-aspnet-subscriptions/Engine/SubscriptionEnabledGraphTypeMakerProvider.cs delete mode 100644 src/graphql-aspnet-subscriptions/Engine/SubscriptionEnabledTypeTemplateProvider.cs rename src/graphql-aspnet/Configuration/{DirectiveBindingConfiguration.cs => DirectiveBindingSchemaExtension.cs} (88%) delete mode 100644 src/graphql-aspnet/Configuration/Startup/SchemaPreCacher.cs create mode 100644 src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory.cs create mode 100644 src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Controllers.cs create mode 100644 src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Directives.cs create mode 100644 src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_GraphTypes.cs create mode 100644 src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Introspection.cs create mode 100644 src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_RuntimeDefinitions.cs create mode 100644 src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Validation.cs create mode 100644 src/graphql-aspnet/Engine/DefaultGraphQLTypeMakerFactory.cs delete mode 100644 src/graphql-aspnet/Engine/DefaultGraphTypeMakerProvider.cs delete mode 100644 src/graphql-aspnet/Engine/DefaultScalarGraphTypeProvider.cs delete mode 100644 src/graphql-aspnet/Engine/DefaultTypeTemplateProvider.cs delete mode 100644 src/graphql-aspnet/Engine/TypeMakers/ObjectGraphTypeMaker.cs delete mode 100644 src/graphql-aspnet/Engine/TypeMakers/ScalarGraphTypeMaker.cs delete mode 100644 src/graphql-aspnet/Execution/GraphSchemaInitializer.cs rename src/graphql-aspnet/{Internal => Execution}/Resolvers/EnumInputValueResolver.cs (100%) rename src/graphql-aspnet/{Internal => Execution}/Resolvers/EnumLeafValueResolver.cs (100%) rename src/graphql-aspnet/{Internal => Execution}/Resolvers/ExtendedGraphFieldResolver.cs (100%) rename src/graphql-aspnet/{Internal => Execution}/Resolvers/FieldResolverMetaData.cs (100%) rename src/graphql-aspnet/{Internal => Execution}/Resolvers/FieldResolverParameterMetaData.cs (100%) rename src/graphql-aspnet/{Internal => Execution}/Resolvers/FieldResolverParameterMetaDataCollection.cs (100%) rename src/graphql-aspnet/{Internal => Execution}/Resolvers/FunctionGraphFieldResolver{TSource,TReturn}.cs (100%) rename src/graphql-aspnet/{Internal => Execution}/Resolvers/GraphControllerActionResolver.cs (100%) rename src/graphql-aspnet/{Internal => Execution}/Resolvers/GraphControllerActionResolverBase.cs (100%) rename src/graphql-aspnet/{Internal => Execution}/Resolvers/GraphControllerRouteFieldResolver.cs (100%) rename src/graphql-aspnet/{Internal => Execution}/Resolvers/GraphDirectiveActionResolver.cs (100%) rename src/graphql-aspnet/{Internal => Execution}/Resolvers/InputObjectValueResolver.cs (100%) rename src/graphql-aspnet/{Internal => Execution}/Resolvers/InputValueResolverBase.cs (100%) rename src/graphql-aspnet/{Internal => Execution}/Resolvers/InputValueResolverMethodGenerator.cs (100%) rename src/graphql-aspnet/{Internal => Execution}/Resolvers/InternalFieldResolverMetaData.cs (100%) rename src/graphql-aspnet/{Internal => Execution}/Resolvers/Introspeection/Schema_TypeGraphFieldResolver.cs (100%) rename src/graphql-aspnet/{Internal => Execution}/Resolvers/Introspeection/Type_EnumValuesGraphFieldResolver.cs (100%) rename src/graphql-aspnet/{Internal => Execution}/Resolvers/Introspeection/Type_TypeGraphFieldResolver.cs (100%) rename src/graphql-aspnet/{Internal => Execution}/Resolvers/ListInputValueResolver.cs (100%) rename src/graphql-aspnet/{Internal => Execution}/Resolvers/ObjectMethodGraphFieldResolver.cs (100%) rename src/graphql-aspnet/{Internal => Execution}/Resolvers/ObjectPropertyGraphFieldResolver.cs (100%) rename src/graphql-aspnet/{Internal => Execution}/Resolvers/ScalarInputValueResolver.cs (100%) rename src/graphql-aspnet/Interfaces/Configuration/{ISchemaConfigurationExtension.cs => ISchemaExtension.cs} (72%) create mode 100644 src/graphql-aspnet/Interfaces/Engine/IGraphQLSchemaFactory{TSchema}.cs create mode 100644 src/graphql-aspnet/Interfaces/Engine/IGraphQLTypeMakerFactory.cs create mode 100644 src/graphql-aspnet/Interfaces/Engine/IGraphQLTypeMakerFactory{TSchema}.cs delete mode 100644 src/graphql-aspnet/Interfaces/Engine/IGraphTypeMakerProvider.cs delete mode 100644 src/graphql-aspnet/Interfaces/Engine/IGraphTypeTemplateProvider.cs delete mode 100644 src/graphql-aspnet/Interfaces/Engine/IScalarGraphTypeProvider.cs create mode 100644 src/graphql-aspnet/Interfaces/Internal/IScalarGraphTypeTemplate.cs create mode 100644 src/graphql-aspnet/Interfaces/Internal/IUnionGraphTypeTemplate.cs create mode 100644 src/graphql-aspnet/Internal/TypeTemplates/ScalarGraphTypeTemplate.cs create mode 100644 src/graphql-aspnet/Internal/TypeTemplates/UnionGraphTypeTemplate.cs rename src/graphql-aspnet/{Engine => Schemas/Generation}/TypeMakers/DependentTypeCollection.cs (100%) rename src/graphql-aspnet/{Engine => Schemas/Generation}/TypeMakers/DirectiveMaker.cs (64%) rename src/graphql-aspnet/{Engine => Schemas/Generation}/TypeMakers/EnumGraphTypeMaker.cs (69%) create mode 100644 src/graphql-aspnet/Schemas/Generation/TypeMakers/FieldContainerGraphTypeMakerBase.cs rename src/graphql-aspnet/{Engine => Schemas/Generation}/TypeMakers/GraphArgumentCreationResult.cs (100%) rename src/graphql-aspnet/{Engine => Schemas/Generation}/TypeMakers/GraphArgumentMaker.cs (52%) rename src/graphql-aspnet/{Engine => Schemas/Generation}/TypeMakers/GraphFieldCreationResult.cs (100%) rename src/graphql-aspnet/{Engine => Schemas/Generation}/TypeMakers/GraphFieldMaker.cs (65%) rename src/graphql-aspnet/{Engine => Schemas/Generation}/TypeMakers/GraphMakerExtensions.cs (100%) rename src/graphql-aspnet/{Engine => Schemas/Generation}/TypeMakers/GraphTypeCreationResult.cs (100%) rename src/graphql-aspnet/{Engine => Schemas/Generation}/TypeMakers/InputObjectGraphTypeMaker.cs (62%) rename src/graphql-aspnet/{Engine => Schemas/Generation}/TypeMakers/InterfaceGraphTypeMaker.cs (58%) create mode 100644 src/graphql-aspnet/Schemas/Generation/TypeMakers/ObjectGraphTypeMaker.cs create mode 100644 src/graphql-aspnet/Schemas/Generation/TypeMakers/ScalarGraphTypeMaker.cs rename src/graphql-aspnet/{Engine => Schemas/Generation}/TypeMakers/UnionGraphTypeMaker.cs (65%) delete mode 100644 src/graphql-aspnet/Schemas/GraphSchemaManager.cs rename src/graphql-aspnet/{Internal => Schemas}/GraphTypeNames.cs (97%) rename src/graphql-aspnet/{Internal => Schemas}/GraphValidation.cs (95%) create mode 100644 src/graphql-aspnet/Schemas/SchemaItemValidators/GraphFieldValidator.cs create mode 100644 src/graphql-aspnet/Schemas/TypeSystem/Scalars/GlobalScalars.cs delete mode 100644 src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/GraphSchemaManagerTests.cs delete mode 100644 src/unit-tests/graphql-aspnet-testframework/GraphQLGlobalRestorePoint.cs delete mode 100644 src/unit-tests/graphql-aspnet-tests/Engine/DefaultScalarTypeProviderTests.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/CustomController.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/CustomDirective.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/CustomEnum.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/CustomObjectWithCustomScalarArgument.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/CustomObjectWithCustomScalarField.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/CustomObjectWithFieldWithArg.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/TwoPropertyObjectAsScalar.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTests.cs delete mode 100644 src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/GraphTypeMakerFactoryTests.cs delete mode 100644 src/unit-tests/graphql-aspnet-tests/Internal/Templating/DefaultUnionTemplateProviderTests.cs delete mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/GraphSchemaManagerTests.cs diff --git a/src/graphql-aspnet-subscriptions/Engine/SubscriptionEnabledGraphTypeMakerFactory.cs b/src/graphql-aspnet-subscriptions/Engine/SubscriptionEnabledGraphTypeMakerFactory.cs new file mode 100644 index 000000000..e2a151308 --- /dev/null +++ b/src/graphql-aspnet-subscriptions/Engine/SubscriptionEnabledGraphTypeMakerFactory.cs @@ -0,0 +1,62 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Engine +{ + using System; + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Controllers; + using GraphQL.AspNet.Engine.TypeMakers; + using GraphQL.AspNet.Interfaces.Engine; + using GraphQL.AspNet.Interfaces.Internal; + using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Schemas.Generation; + using GraphQL.AspNet.Schemas.TypeSystem; + + /// + /// An upgraded "type maker" factory that adds low level subscription field support + /// to the type system. + /// + /// The type of the schema this maker factory is registered to handle. + public class SubscriptionEnabledGraphQLTypeMakerFactory : DefaultGraphQLTypeMakerFactory + where TSchema : class, ISchema + { + /// + /// Initializes a new instance of the class. + /// + public SubscriptionEnabledGraphQLTypeMakerFactory() + { + } + + /// + public override IGraphTypeTemplate MakeTemplate(Type objectType, TypeKind? kind = null) + { + if (Validation.IsCastable(objectType)) + return new SubscriptionGraphControllerTemplate(objectType); + + return base.MakeTemplate(objectType, kind); + } + + /// + public override IGraphFieldMaker CreateFieldMaker() + { + return new SubscriptionEnabledGraphFieldMaker(this.Schema, this); + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet-subscriptions/Engine/SubscriptionEnabledGraphTypeMakerProvider.cs b/src/graphql-aspnet-subscriptions/Engine/SubscriptionEnabledGraphTypeMakerProvider.cs deleted file mode 100644 index 5dfb03d58..000000000 --- a/src/graphql-aspnet-subscriptions/Engine/SubscriptionEnabledGraphTypeMakerProvider.cs +++ /dev/null @@ -1,28 +0,0 @@ -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - -namespace GraphQL.AspNet.Engine -{ - using GraphQL.AspNet.Engine.TypeMakers; - using GraphQL.AspNet.Interfaces.Engine; - using GraphQL.AspNet.Interfaces.Schema; - - /// - /// An upgraded "type maker" factory that adds low level subscription field support - /// to the type system. - /// - public class SubscriptionEnabledGraphTypeMakerProvider : DefaultGraphTypeMakerProvider - { - /// - public override IGraphFieldMaker CreateFieldMaker(ISchema schema) - { - return new SubscriptionEnabledGraphFieldMaker(schema); - } - } -} \ No newline at end of file diff --git a/src/graphql-aspnet-subscriptions/Engine/SubscriptionEnabledTypeTemplateProvider.cs b/src/graphql-aspnet-subscriptions/Engine/SubscriptionEnabledTypeTemplateProvider.cs deleted file mode 100644 index 9e9214e43..000000000 --- a/src/graphql-aspnet-subscriptions/Engine/SubscriptionEnabledTypeTemplateProvider.cs +++ /dev/null @@ -1,39 +0,0 @@ -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - -namespace GraphQL.AspNet.Engine -{ - using System; - using GraphQL.AspNet.Common; - using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Interfaces.Internal; - using GraphQL.AspNet.Internal.TypeTemplates; - using GraphQL.AspNet.Schemas.TypeSystem; - - /// - /// A template provider that adds the ability to parse subscription marked fields on graph controllers - /// in order to add them to the schema. - /// - public class SubscriptionEnabledTypeTemplateProvider : DefaultTypeTemplateProvider - { - /// - /// Makes a graph template from the given type. - /// - /// Type of the object. - /// The kind of graph type to parse for. - /// IGraphItemTemplate. - protected override IGraphTypeTemplate MakeTemplate(Type objectType, TypeKind kind) - { - if (Validation.IsCastable(objectType)) - return new SubscriptionGraphControllerTemplate(objectType); - - return base.MakeTemplate(objectType, kind); - } - } -} \ No newline at end of file diff --git a/src/graphql-aspnet-subscriptions/Engine/TypeMakers/SubscriptionEnabledGraphFieldMaker.cs b/src/graphql-aspnet-subscriptions/Engine/TypeMakers/SubscriptionEnabledGraphFieldMaker.cs index a38e52e62..6c385af9f 100644 --- a/src/graphql-aspnet-subscriptions/Engine/TypeMakers/SubscriptionEnabledGraphFieldMaker.cs +++ b/src/graphql-aspnet-subscriptions/Engine/TypeMakers/SubscriptionEnabledGraphFieldMaker.cs @@ -20,9 +20,11 @@ namespace GraphQL.AspNet.Engine.TypeMakers using System.Collections.Generic; using GraphQL.AspNet.Configuration.Formatting; using GraphQL.AspNet.Execution; + using GraphQL.AspNet.Interfaces.Engine; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Schemas.Generation.TypeMakers; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Security; @@ -36,8 +38,8 @@ public class SubscriptionEnabledGraphFieldMaker : GraphFieldMaker /// Initializes a new instance of the class. /// /// The schema. - public SubscriptionEnabledGraphFieldMaker(ISchema schema) - : base(schema) + public SubscriptionEnabledGraphFieldMaker(ISchema schema, IGraphQLTypeMakerFactory factory) + : base(schema, factory) { } diff --git a/src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionControllerActionGraphFieldTemplate.cs b/src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionControllerActionGraphFieldTemplate.cs index 02fa75842..0a339d107 100644 --- a/src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionControllerActionGraphFieldTemplate.cs +++ b/src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionControllerActionGraphFieldTemplate.cs @@ -134,7 +134,7 @@ public override void ValidateOrThrow() } /// - protected override GraphArgumentTemplate CreateInputArgument(ParameterInfo paramInfo) + protected override GraphArgumentTemplate CreateArgument(ParameterInfo paramInfo) { if (this.Route.RootCollection == Execution.SchemaItemCollections.Subscription) { @@ -144,7 +144,7 @@ protected override GraphArgumentTemplate CreateInputArgument(ParameterInfo param _explicitlyDeclaredAsSubscriptionSourceType != null); } - return base.CreateInputArgument(paramInfo); + return base.CreateArgument(paramInfo); } /// diff --git a/src/graphql-aspnet-subscriptions/SubscriptionServer/SubscriptionPublisherSchemaExtension.cs b/src/graphql-aspnet-subscriptions/SubscriptionServer/SubscriptionPublisherSchemaExtension.cs index 8133410cf..ebc73ae37 100644 --- a/src/graphql-aspnet-subscriptions/SubscriptionServer/SubscriptionPublisherSchemaExtension.cs +++ b/src/graphql-aspnet-subscriptions/SubscriptionServer/SubscriptionPublisherSchemaExtension.cs @@ -48,11 +48,9 @@ public void Configure(SchemaOptions options) // swap out the master providers for the ones that includes // support for the subscription action type - if (!(GraphQLProviders.TemplateProvider is SubscriptionEnabledTypeTemplateProvider)) - GraphQLProviders.TemplateProvider = new SubscriptionEnabledTypeTemplateProvider(); - if (!(GraphQLProviders.GraphTypeMakerProvider is SubscriptionEnabledGraphTypeMakerProvider)) - GraphQLProviders.GraphTypeMakerProvider = new SubscriptionEnabledGraphTypeMakerProvider(); + // need to register the schema enabled type maker factory + throw new NotImplementedException(); } /// diff --git a/src/graphql-aspnet-subscriptions/SubscriptionServer/SubscriptionReceiverSchemaExtension.cs b/src/graphql-aspnet-subscriptions/SubscriptionServer/SubscriptionReceiverSchemaExtension.cs index facb10443..a680e8355 100644 --- a/src/graphql-aspnet-subscriptions/SubscriptionServer/SubscriptionReceiverSchemaExtension.cs +++ b/src/graphql-aspnet-subscriptions/SubscriptionServer/SubscriptionReceiverSchemaExtension.cs @@ -92,13 +92,8 @@ public void Configure(SchemaOptions options) // swap out the master templating provider for the one that includes // support for the subscription action type if and only if the developer has not // already registered their own custom one - if (GraphQLProviders.TemplateProvider == null || GraphQLProviders.TemplateProvider.GetType() == typeof(DefaultTypeTemplateProvider)) - GraphQLProviders.TemplateProvider = new SubscriptionEnabledTypeTemplateProvider(); - // swap out the master graph type maker to its "subscription enabled" version - // if and only if the developer has not already registered their own custom instance - if (GraphQLProviders.GraphTypeMakerProvider == null || GraphQLProviders.GraphTypeMakerProvider.GetType() == typeof(DefaultGraphTypeMakerProvider)) - GraphQLProviders.GraphTypeMakerProvider = new SubscriptionEnabledGraphTypeMakerProvider(); + // need to register the subscription enable graph type maker factory // Update the query execution pipeline // ------------------------------------------ diff --git a/src/graphql-aspnet/Configuration/DirectiveBindingConfiguration.cs b/src/graphql-aspnet/Configuration/DirectiveBindingSchemaExtension.cs similarity index 88% rename from src/graphql-aspnet/Configuration/DirectiveBindingConfiguration.cs rename to src/graphql-aspnet/Configuration/DirectiveBindingSchemaExtension.cs index a52d1724b..62c9bab21 100644 --- a/src/graphql-aspnet/Configuration/DirectiveBindingConfiguration.cs +++ b/src/graphql-aspnet/Configuration/DirectiveBindingSchemaExtension.cs @@ -21,7 +21,7 @@ namespace GraphQL.AspNet.Configuration /// A configuration class used to apply a late-bound directive to a set of schema items /// matching a filter. /// - public sealed class DirectiveBindingConfiguration : ISchemaConfigurationExtension + public sealed class DirectiveBindingSchemaExtension : ISchemaExtension { // a set of default filters applied to any directive applicator unless explicitly removed // by the developer. Used to auto filter items down to those reasonably assumed @@ -30,9 +30,9 @@ public sealed class DirectiveBindingConfiguration : ISchemaConfigurationExtensio private static IReadOnlyList> _defaultFilters; /// - /// Initializes static members of the class. + /// Initializes static members of the class. /// - static DirectiveBindingConfiguration() + static DirectiveBindingSchemaExtension() { var list = new List>(4); @@ -53,10 +53,10 @@ static DirectiveBindingConfiguration() private List> _customFilters; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// Type of the directive being applied in this instnace. - public DirectiveBindingConfiguration(Type directiveType) + public DirectiveBindingSchemaExtension(Type directiveType) : this() { _directiveType = Validation.ThrowIfNullOrReturn(directiveType, nameof(directiveType)); @@ -64,24 +64,24 @@ public DirectiveBindingConfiguration(Type directiveType) } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// Name of the directive as it is declared in the schema /// where it is being applied. - public DirectiveBindingConfiguration(string directiveName) + public DirectiveBindingSchemaExtension(string directiveName) : this() { _directiveName = Validation.ThrowIfNullWhiteSpaceOrReturn(directiveName, nameof(directiveName)); } - private DirectiveBindingConfiguration() + private DirectiveBindingSchemaExtension() { _customFilters = new List>(); this.WithArguments(); } /// - void ISchemaConfigurationExtension.Configure(ISchema schema) + void ISchemaExtension.Extend(ISchema schema) { var allFilters = _defaultFilters.Concat(_customFilters).ToList(); foreach (var schemaItem in schema.AllSchemaItems(includeDirectives: false)) @@ -125,7 +125,7 @@ void ISchemaConfigurationExtension.Configure(ISchema schema) /// The arguments to supply to the directive when its /// executed. /// IDirectiveInjector. - public DirectiveBindingConfiguration WithArguments(params object[] arguments) + public DirectiveBindingSchemaExtension WithArguments(params object[] arguments) { arguments = arguments ?? new object[0]; _argumentFunction = x => arguments; @@ -141,7 +141,7 @@ public DirectiveBindingConfiguration WithArguments(params object[] arguments) /// A function that will be used to /// create a new unique set of arguments per schema item the directive is applied to. /// IDirectiveInjector. - public DirectiveBindingConfiguration WithArguments(Func argsCreator) + public DirectiveBindingSchemaExtension WithArguments(Func argsCreator) { Validation.ThrowIfNull(argsCreator, nameof(argsCreator)); _argumentFunction = argsCreator; @@ -158,7 +158,7 @@ public DirectiveBindingConfiguration WithArguments(Func a /// /// The item filter. /// DirectiveApplicator. - public DirectiveBindingConfiguration ToItems(Func itemFilter) + public DirectiveBindingSchemaExtension ToItems(Func itemFilter) { Validation.ThrowIfNull(itemFilter, nameof(itemFilter)); _customFilters.Add(itemFilter); @@ -169,7 +169,7 @@ public DirectiveBindingConfiguration ToItems(Func itemFilter) /// Clears this instance of any directive arguments and filter criteria. /// /// DirectiveApplicator. - public DirectiveBindingConfiguration Clear() + public DirectiveBindingSchemaExtension Clear() { _customFilters.Clear(); this.WithArguments(); diff --git a/src/graphql-aspnet/Configuration/Formatting/GraphNameFormatter.cs b/src/graphql-aspnet/Configuration/Formatting/GraphNameFormatter.cs index 6311ea0b9..50eb9537c 100644 --- a/src/graphql-aspnet/Configuration/Formatting/GraphNameFormatter.cs +++ b/src/graphql-aspnet/Configuration/Formatting/GraphNameFormatter.cs @@ -11,6 +11,7 @@ namespace GraphQL.AspNet.Configuration.Formatting { using System.Diagnostics; using GraphQL.AspNet.Common.Extensions; + using GraphQL.AspNet.Schemas.TypeSystem.Scalars; /// /// A formatter class capable of altering a graph item name before its added to a schema. @@ -87,10 +88,6 @@ public virtual string FormatEnumValueName(string name) /// System.String. public virtual string FormatGraphTypeName(string name) { - // scalar names are considered fixed constants and can't be changed - if (name == null || GraphQLProviders.ScalarProvider.IsScalar(name)) - return name; - return this.FormatName(name, _typeNameStrategy); } diff --git a/src/graphql-aspnet/Configuration/SchemaOptions.cs b/src/graphql-aspnet/Configuration/SchemaOptions.cs index 9118e9b10..51dcb8722 100644 --- a/src/graphql-aspnet/Configuration/SchemaOptions.cs +++ b/src/graphql-aspnet/Configuration/SchemaOptions.cs @@ -36,7 +36,7 @@ public abstract class SchemaOptions private readonly List _registeredServices; private readonly List _runtimeTemplates; - private List _configExtensions; + private List _configExtensions; /// /// Initializes a new instance of the class. @@ -55,7 +55,7 @@ public SchemaOptions(Type schemaType, IServiceCollection serviceCollection) _runtimeTemplates = new List(); _serverExtensions = new Dictionary(); _registeredServices = new List(); - _configExtensions = new List(); + _configExtensions = new List(); this.DeclarationOptions = new SchemaDeclarationConfiguration(); this.CacheOptions = new SchemaQueryExecutionPlanCacheConfiguration(); @@ -282,7 +282,7 @@ public void RegisterExtension(TExtensionType extension) /// further processing after the extension executes. /// /// The extension to apply. - public void AddConfigurationExtension(ISchemaConfigurationExtension extension) + public void AddSchemaExtension(ISchemaExtension extension) { Validation.ThrowIfNull(extension, nameof(extension)); _configExtensions.Add(extension); @@ -294,7 +294,7 @@ public void AddConfigurationExtension(ISchemaConfigurationExtension extension) /// /// The type of the directive to apply. /// IDirectiveInjector. - public DirectiveBindingConfiguration ApplyDirective() + public DirectiveBindingSchemaExtension ApplyDirective() where TDirectiveType : GraphDirective { return this.ApplyDirective(typeof(TDirectiveType)); @@ -306,14 +306,14 @@ public DirectiveBindingConfiguration ApplyDirective() /// /// The type of the directive to apply to schema items. /// IDirectiveInjector. - public DirectiveBindingConfiguration ApplyDirective(Type directiveType) + public DirectiveBindingSchemaExtension ApplyDirective(Type directiveType) { Validation.ThrowIfNull(directiveType, nameof(directiveType)); Validation.ThrowIfNotCastable(directiveType, nameof(directiveType)); this.AddType(directiveType, null, null); - var applicator = new DirectiveBindingConfiguration(directiveType); - this.AddConfigurationExtension(applicator); + var applicator = new DirectiveBindingSchemaExtension(directiveType); + this.AddSchemaExtension(applicator); return applicator; } @@ -325,11 +325,11 @@ public DirectiveBindingConfiguration ApplyDirective(Type directiveType) /// /// Name of the directive. /// IDirectiveInjector. - public DirectiveBindingConfiguration ApplyDirective(string directiveName) + public DirectiveBindingSchemaExtension ApplyDirective(string directiveName) { directiveName = Validation.ThrowIfNullWhiteSpaceOrReturn(directiveName, nameof(directiveName)); - var applicator = new DirectiveBindingConfiguration(directiveName); - this.AddConfigurationExtension(applicator); + var applicator = new DirectiveBindingSchemaExtension(directiveName); + this.AddSchemaExtension(applicator); return applicator; } @@ -386,7 +386,7 @@ internal void AddRuntimeSchemaItem(IGraphQLRuntimeSchemaItemDefinition template) /// created. /// /// The configuration extensions. - public IEnumerable ConfigurationExtensions => _configExtensions; + public IEnumerable SchemaExtensions => _configExtensions; /// /// Gets or sets a value indicating whether any , or diff --git a/src/graphql-aspnet/Configuration/SchemaTypeToRegister.cs b/src/graphql-aspnet/Configuration/SchemaTypeToRegister.cs index 1f2e7cc01..69c0f8789 100644 --- a/src/graphql-aspnet/Configuration/SchemaTypeToRegister.cs +++ b/src/graphql-aspnet/Configuration/SchemaTypeToRegister.cs @@ -32,7 +32,9 @@ public class SchemaTypeToRegister /// Initializes a new instance of the class. /// /// The type to be registered to the schema. - /// The graph type kind to register the type as. + /// (optional) A specific graph type kind to force the type to be + /// coerced into. + [DebuggerStepperBoundary] public SchemaTypeToRegister(Type type, TypeKind? typeKind = null) { this.Type = Validation.ThrowIfNullOrReturn(type, nameof(type)); diff --git a/src/graphql-aspnet/Configuration/Startup/GraphQLSchemaInjector{TSchema}.cs b/src/graphql-aspnet/Configuration/Startup/GraphQLSchemaInjector{TSchema}.cs index beb1f2c56..3a970d820 100644 --- a/src/graphql-aspnet/Configuration/Startup/GraphQLSchemaInjector{TSchema}.cs +++ b/src/graphql-aspnet/Configuration/Startup/GraphQLSchemaInjector{TSchema}.cs @@ -29,6 +29,7 @@ namespace GraphQL.AspNet.Configuration.Startup using GraphQL.AspNet.Middleware.FieldExecution; using GraphQL.AspNet.Middleware.QueryExecution; using GraphQL.AspNet.Middleware.SchemaItemSecurity; + using GraphQL.AspNet.Schemas.Generation; using GraphQL.AspNet.Web; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; @@ -160,6 +161,8 @@ private void RegisterEngineComponents() // "per request per schema" components _options.ServiceCollection.TryAddTransient(typeof(IGraphQLHttpProcessor), _options.QueryHandler.HttpProcessorType); + _options.ServiceCollection.TryAddTransient, DefaultGraphQLSchemaFactory>(); + _options.ServiceCollection.TryAddTransient, DefaultGraphQLTypeMakerFactory>(); // "per application server" instance _options.ServiceCollection.TryAddScoped(sp => sp?.GetService()); @@ -180,9 +183,17 @@ private void RegisterEngineComponents() /// TSchema. private TSchema BuildNewSchemaInstance(IServiceProvider serviceProvider) { - var schemaInstance = GraphSchemaBuilder.BuildSchema(serviceProvider); - var initializer = new GraphSchemaInitializer(_options, serviceProvider); - initializer.Initialize(schemaInstance); + var scope = serviceProvider.CreateScope(); + + var schemaConfig = _options.CreateConfiguration(); + + var factory = scope.ServiceProvider.GetRequiredService>(); + var schemaInstance = factory.CreateInstance( + scope, + schemaConfig, + _options.SchemaTypesToRegister, + _options.RuntimeTemplates, + _options.SchemaExtensions); serviceProvider.WriteLogEntry( (l) => l.SchemaInstanceCreated(schemaInstance)); @@ -239,10 +250,6 @@ public void UseSchema(IServiceProvider serviceProvider) /// server options on this instance are invoked with just the service provider. private void UseSchema(IServiceProvider serviceProvider, bool invokeServerExtensions) { - // pre-parse any types known to this schema - var preCacher = new SchemaPreCacher(); - preCacher.PreCacheTemplates(_options.SchemaTypesToRegister.Select(x => x.Type)); - // only when the service provider is used for final configuration do we // invoke extensions with just the service provider // (mostly just for test harnessing, but may be used by developers as well) diff --git a/src/graphql-aspnet/Configuration/Startup/SchemaPreCacher.cs b/src/graphql-aspnet/Configuration/Startup/SchemaPreCacher.cs deleted file mode 100644 index e95e2d962..000000000 --- a/src/graphql-aspnet/Configuration/Startup/SchemaPreCacher.cs +++ /dev/null @@ -1,76 +0,0 @@ -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - -namespace GraphQL.AspNet.Configuration.Startup -{ - using System; - using System.Collections.Generic; - using System.Linq; - using GraphQL.AspNet; - using GraphQL.AspNet.Common; - using GraphQL.AspNet.Interfaces.Internal; - using GraphQL.AspNet.Internal; - - /// - /// Preloads data related to a schema into memory. - /// - internal class SchemaPreCacher - { - private readonly HashSet _parsedTypes; - - /// - /// Initializes a new instance of the class. - /// - public SchemaPreCacher() - { - _parsedTypes = new HashSet(); - } - - /// - /// Iterates over the schema types and ensures the are pre-loaded into the global template cache. - /// - /// The schema types. - public void PreCacheTemplates(IEnumerable schemaTypes) - { - if (schemaTypes == null) - return; - - foreach (var type in schemaTypes) - { - this.PreParseTypeAndChildren(type); - } - } - - private void PreParseTypeAndChildren(Type type) - { - if (_parsedTypes.Contains(type)) - return; - - _parsedTypes.Add(type); - - // can't preparse scalars (no parsing nessceary) - if (GraphQLProviders.ScalarProvider.IsScalar(type)) - return; - - // can't preparse union proxies (they aren't parsable graph types) - if (!GraphValidation.IsParseableType(type)) - return; - - var template = GraphQLProviders.TemplateProvider.ParseType(type); - - if (template is IGraphTypeFieldTemplateContainer fieldContainer) - { - foreach (var dependent in fieldContainer.FieldTemplates.Values.SelectMany(x => x.RetrieveRequiredTypes())) - { - this.PreParseTypeAndChildren(dependent.Type); - } - } - } - } -} \ No newline at end of file diff --git a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory.cs b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory.cs new file mode 100644 index 000000000..9d265708c --- /dev/null +++ b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory.cs @@ -0,0 +1,223 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Engine +{ + using System; + using System.Collections.Generic; + using System.Linq; + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Configuration.Startup; + using GraphQL.AspNet.Interfaces.Configuration; + using GraphQL.AspNet.Interfaces.Configuration.Templates; + using GraphQL.AspNet.Interfaces.Engine; + using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Schemas.Generation; + using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Schemas.TypeSystem.Scalars; + using Microsoft.Extensions.DependencyInjection; + + /// + /// The default schema factory, capable of creating singleton instances of + /// schemas, fully populated and ready to serve requests. + /// + /// The type of the schema being built. + public partial class DefaultGraphQLSchemaFactory : IGraphQLSchemaFactory + where TSchema : class, ISchema + { + /// + /// Initializes a new instance of the class. + /// + public DefaultGraphQLSchemaFactory() + : this(true, true, null) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// if set to true the specification defined + /// directives (e.g. @skip, @include etc.) will be automatically added to any + /// created schema instance. + /// if set to true any discovered + /// type system directives will be applied to their target schema items. + /// A type factory instance to use. When null, one will attempt to be created + /// from the schema's service scope. + public DefaultGraphQLSchemaFactory( + bool includeBuiltInDirectives = true, + bool processTypeSystemDirectives = true, + IGraphQLTypeMakerFactory factory = null) + { + this.IncludeBuiltInDirectives = includeBuiltInDirectives; + this.ProcessTypeSystemDirectives = processTypeSystemDirectives; + this.MakerFactory = factory; + } + + /// + public virtual TSchema CreateInstance( + IServiceScope serviceScope, + ISchemaConfiguration configuration, + IEnumerable typesToRegister = null, + IEnumerable runtimeItemDefinitions = null, + IEnumerable schemaExtensions = null) + { + Validation.ThrowIfNull(serviceScope, nameof(serviceScope)); + Validation.ThrowIfNull(configuration, nameof(configuration)); + + this.ServiceProvider = serviceScope.ServiceProvider; + + runtimeItemDefinitions = runtimeItemDefinitions ?? Enumerable.Empty(); + typesToRegister = typesToRegister ?? Enumerable.Empty(); + schemaExtensions = schemaExtensions ?? Enumerable.Empty(); + + this.Schema = GraphSchemaBuilder.BuildSchema(this.ServiceProvider); + + if (this.Schema.IsInitialized) + return this.Schema; + + this.Schema.Configuration.Merge(configuration); + if (this.MakerFactory == null) + this.MakerFactory = this.ServiceProvider.GetRequiredService>(); + + this.MakerFactory.Initialize(this.Schema); + + // Step 1: Ensure all the bare bones requirements are set + // -------------------------------------- + this.EnsureBaseLineDependencies(); + + // Step 2a: Figure out which types are scalars and register them first + // -------------------------------------- + // This speeds up the generation process since they don't have to be found + // and validated when trying to import objects or interfaces. + var scalarsToRegister = new List(); + var nonScalarsToRegister = new List(); + foreach (var regType in typesToRegister) + { + if (Validation.IsCastable(GlobalScalars.FindBuiltInScalarType(regType.Type) ?? regType.Type)) + scalarsToRegister.Add(regType); + else + nonScalarsToRegister.Add(regType); + } + + // Step 2b: Register all explicitly declared scalars first + // -------------------------------------- + foreach (var type in scalarsToRegister) + this.EnsureGraphType(type.Type); + + // Step 2c: Register other graph types + // -------------------------------------- + foreach (var type in nonScalarsToRegister) + this.EnsureGraphType(type.Type, type.TypeKind); + + // Step 3: Register any runtime defined items (e.g. minimal api registrations) + // -------------------------------------- + foreach (var itemDef in runtimeItemDefinitions) + this.AddRuntimeSchemaItemDefinition(itemDef); + + // Step 4: execute any assigned schema extensions + // -------------------------------------- + // this includes any late bound directives added to the type system via .ApplyDirective() + foreach (var extension in schemaExtensions) + extension.Extend(this.Schema); + + // Step 5: apply all queued type system directives to the now filled schema + // -------------------------------------- + if (this.ProcessTypeSystemDirectives) + this.ApplyTypeSystemDirectives(); + + // Step 6: Run final validations to ensure the schema is internally consistant + // -------------------------------------- + this.ValidateSchemaIntegrity(); + + // Step 7: Rebuild introspection data to match the now completed schema instance + // -------------------------------------- + if (!this.Schema.Configuration.DeclarationOptions.DisableIntrospection) + this.RebuildIntrospectionData(); + + this.Schema.IsInitialized = true; + return this.Schema; + } + + /// + /// Ensures the target schema has all the "specification required" pieces and dependencies + /// accounted for. + /// + protected virtual void EnsureBaseLineDependencies() + { + // all schemas depend on String because of the __typename field + this.EnsureGraphType(typeof(string)); + + // ensure top level schema directives are accounted for + foreach (var directive in this.Schema.GetType().ExtractAppliedDirectives()) + { + this.Schema.AppliedDirectives.Add(directive); + } + + foreach (var appliedDirective in this.Schema.AppliedDirectives.Where(x => x.DirectiveType != null)) + { + this.EnsureGraphType( + appliedDirective.DirectiveType, + TypeKind.DIRECTIVE); + } + + // ensure all globally required directives are added + if (this.IncludeBuiltInDirectives) + { + foreach (var type in Constants.GlobalDirectives) + this.EnsureGraphType(type); + } + + // all schemas must support query + this.EnsureGraphOperationType(GraphOperationType.Query); + } + + /// + /// Gets the service provider that will be used to create service instances + /// needed to generate the schema + /// + /// The service provider. + protected virtual IServiceProvider ServiceProvider { get; private set; } + + /// + /// Gets the configuration settings that will be used to generate + /// the schema. + /// + /// The schema configuration instance. + protected virtual ISchemaConfiguration Configuration => this.Schema.Configuration; + + /// + /// Gets the schema instance being built by this factory instance. + /// + /// The schema. + protected virtual TSchema Schema { get; private set; } + + /// + /// Gets or sets a factory instnace that can serve up instances of various + /// makers to generate graph types for the building . + /// + /// The maker factory to use in this instance. + protected virtual IGraphQLTypeMakerFactory MakerFactory { get; set; } + + /// + /// Gets a value indicating whether the specification-defined, built-in directives (e.g. skip, include etc.) + /// are automatically added to the schema that is generated. + /// + /// true if [include built in directives]; otherwise, false. + protected virtual bool IncludeBuiltInDirectives { get; } + + /// + /// Gets a value indicating whether any assigned type system directives will be processed when a schema instance + /// is built. + /// + /// true if type system directives should be processed for any schema items; otherwise, false. + protected virtual bool ProcessTypeSystemDirectives { get; } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Controllers.cs b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Controllers.cs new file mode 100644 index 000000000..d9fd8e7a4 --- /dev/null +++ b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Controllers.cs @@ -0,0 +1,239 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Engine +{ + using System; + using System.Collections.Generic; + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Execution; + using GraphQL.AspNet.Execution.Exceptions; + using GraphQL.AspNet.Interfaces.Internal; + using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Schemas.Structural; + using GraphQL.AspNet.Schemas.TypeSystem; + + /// + /// The default schema factory, capable of creating singleton instances of + /// schemas, fully populated and ready to serve requests. + /// + public partial class DefaultGraphQLSchemaFactory + { + /// + /// Incorpates the templated controller into the schema. + /// + /// The template of the controller to add. + protected virtual void AddController(IGraphControllerTemplate template) + { + Validation.ThrowIfNull(template, nameof(template)); + + foreach (var action in template.Actions) + this.AddAction(action); + + foreach (var extension in template.Extensions) + this.AddTypeExtension(extension); + } + + /// + /// Adds the type extension to the schema for the configured concrete type. If the type + /// is not registered to the schema the field extension is queued for when it is added (if ever). + /// + /// The extension to add. + protected virtual void AddTypeExtension(IGraphFieldTemplate extension) + { + var fieldMaker = this.MakerFactory.CreateFieldMaker(); + var fieldResult = fieldMaker.CreateField(extension); + + if (fieldResult != null) + { + this.Schema.KnownTypes.EnsureGraphFieldExtension(extension.SourceObjectType, fieldResult.Field); + this.EnsureDependents(fieldResult); + } + } + + /// + /// Adds the to the schema. Any required parent fields + /// will be automatically created if necessary to ensure proper nesting. + /// + /// The action to add to the schema. + protected virtual void AddAction(IGraphFieldTemplate action) + { + if (this.Schema.Configuration.DeclarationOptions.AllowedOperations.Contains(action.Route.RootCollection.ToGraphOperationType())) + { + var operation = action.Route.RootCollection.ToGraphOperationType(); + this.EnsureGraphOperationType(operation); + var parentField = this.AddOrRetrieveControllerRoutePath(action); + this.AddActionAsField(parentField, action); + } + else + { + throw new ArgumentOutOfRangeException( + nameof(action), + $"The '{action.InternalFullName}' action's operation root ({action.Route.RootCollection}) is not " + + $"allowed by the target schema (Name: {this.Schema.Name})."); + } + } + + /// + /// Inspects the root and ensures that any intermediate, virtual fields + /// are accounted for and returns a reference to the immediate parent this action should be added to. + /// + /// The action. + /// IGraphField. + protected virtual IObjectGraphType AddOrRetrieveControllerRoutePath(IGraphFieldTemplate action) + { + var pathSegments = action.Route.GenerateParentPathSegments(); + + // loop through all parent path parts of this action + // creating virtual fields as necessary or using existing ones and adding on to them + IObjectGraphType parentType = this.Schema.Operations[action.Route.RootCollection.ToGraphOperationType()]; + + for (var i = 0; i < pathSegments.Count; i++) + { + var segment = pathSegments[i]; + var formattedName = this.Schema.Configuration.DeclarationOptions.GraphNamingFormatter.FormatFieldName(segment.Name); + if (parentType.Fields.ContainsKey(formattedName)) + { + var field = parentType[formattedName]; + var foundType = Schema.KnownTypes.FindGraphType(field.TypeExpression.TypeName); + + var ogt = foundType as IObjectGraphType; + if (ogt != null) + { + if (ogt.IsVirtual) + { + parentType = ogt; + continue; + } + + throw new GraphTypeDeclarationException( + $"The action '{action.Route}' attempted to nest itself under the {foundType.Kind} graph type '{foundType.Name}', which is returned by " + + $"the route '{field.Route}'. Actions can only be added to virtual graph types created by their parent controller."); + } + + if (foundType != null) + { + throw new GraphTypeDeclarationException( + $"The action '{action.Route.Path}' attempted to nest itself under the graph type '{foundType.Name}'. {foundType.Kind} graph types cannot " + + "accept fields."); + } + else + { + throw new GraphTypeDeclarationException( + $"The action '{action.Route.Path}' attempted to nest itself under the field '{field.Route}' but no graph type was found " + + "that matches its type."); + } + } + + parentType = this.CreateVirtualFieldOnParent( + parentType, + formattedName, + segment, + i == 0 ? action.Parent : null); + } + + return parentType; + } + + /// + /// Performs an out-of-band append of a new graph field to a parent. Accounts for type updates in this schema ONLY. + /// + /// the parent type to add the new field to. + /// Name of the field. + /// The path segment to represent the new field. + /// The definition item from which graph attributes should be used, if any. Attributes will be set to an empty string if not supplied. + /// The type associated with the field added to the parent type. + protected virtual IObjectGraphType CreateVirtualFieldOnParent( + IObjectGraphType parentType, + string fieldName, + SchemaItemPath path, + ISchemaItemTemplate definition = null) + { + var childField = new VirtualGraphField( + parentType, + fieldName, + path, + this.MakeSafeTypeNameFromRoutePath(path)) + { + IsDepreciated = false, + DepreciationReason = string.Empty, + Description = definition?.Description ?? string.Empty, + }; + + parentType.Extend(childField); + this.Schema.KnownTypes.EnsureGraphType(childField.AssociatedGraphType); + this.EnsureDependents(childField); + + return childField.AssociatedGraphType; + } + + /// + /// Makes the unique route being used for this virtual field type safe, removing special control characters + /// but retaining its uniqueness. + /// + /// The path. + /// System.String. + protected virtual string MakeSafeTypeNameFromRoutePath(SchemaItemPath path) + { + var segments = new List(); + foreach (var pathSegmentName in path) + { + switch (pathSegmentName) + { + case Constants.Routing.QUERY_ROOT: + segments.Add(Constants.ReservedNames.QUERY_TYPE_NAME); + break; + + case Constants.Routing.MUTATION_ROOT: + segments.Add(Constants.ReservedNames.MUTATION_TYPE_NAME); + break; + + case Constants.Routing.SUBSCRIPTION_ROOT: + segments.Add(Constants.ReservedNames.SUBSCRIPTION_TYPE_NAME); + break; + + default: + segments.Add(this.Schema.Configuration.DeclarationOptions.GraphNamingFormatter.FormatGraphTypeName(pathSegmentName)); + break; + } + } + + segments.Reverse(); + return string.Join("_", segments); + } + + /// + /// Iterates the given and adds + /// all found types to the type system for this . Generates + /// a field reference on the provided parent with a resolver pointing to the provided graph action. + /// + /// The parent which will own the generated action field. + /// The action. + protected virtual void AddActionAsField(IObjectGraphType parentType, IGraphFieldTemplate action) + { + // apend the action as a field on the parent + var maker = this.MakerFactory.CreateFieldMaker(); + var fieldResult = maker.CreateField(action); + + if (fieldResult != null) + { + if (parentType.Fields.ContainsKey(fieldResult.Field.Name)) + { + throw new GraphTypeDeclarationException( + $"The '{parentType.Kind}' graph type '{parentType.Name}' already contains a field named '{fieldResult.Field.Name}'. " + + $"The action method '{action.InternalFullName}' cannot be added to the graph type with the same name."); + } + + parentType.Extend(fieldResult.Field); + this.EnsureDependents(fieldResult); + } + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Directives.cs b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Directives.cs new file mode 100644 index 000000000..e04192fee --- /dev/null +++ b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Directives.cs @@ -0,0 +1,37 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Engine +{ + using System.Linq; + using GraphQL.AspNet.Execution; + using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Schemas.TypeSystem; + + /// + /// The default schema factory, capable of creating singleton instances of + /// schemas, fully populated and ready to serve requests. + /// + public partial class DefaultGraphQLSchemaFactory + { + /// + /// Inspects all graph types, fields, arguments and directives for any pending + /// type system directives. When found, applies each directive as approprate to the + /// target schema item. + /// + protected virtual void ApplyTypeSystemDirectives() + { + var processor = new DirectiveProcessorTypeSystem( + this.ServiceProvider, + new QuerySession()); + + processor.ApplyDirectives(this.Schema); + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_GraphTypes.cs b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_GraphTypes.cs new file mode 100644 index 000000000..560dcd9c9 --- /dev/null +++ b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_GraphTypes.cs @@ -0,0 +1,123 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Engine +{ + using System; + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Controllers; + using GraphQL.AspNet.Engine.TypeMakers; + using GraphQL.AspNet.Interfaces.Engine; + using GraphQL.AspNet.Interfaces.Internal; + using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Internal; + using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Schemas.TypeSystem.Scalars; + using GraphQL.AspNet.ServerExtensions.MultipartRequests.Model; + + /// + /// The default schema factory, capable of creating singleton instances of + /// schemas, fully populated and ready to serve requests. + /// + public partial class DefaultGraphQLSchemaFactory + { + /// + /// Ensures that the root operation type (query, mutation etc.) exists on this schema and the associated virtual + /// type representing it also exists in the schema's type collection. + /// + /// Type of the operation. + protected virtual void EnsureGraphOperationType(GraphOperationType operationType) + { + if (operationType == GraphOperationType.Unknown) + { + throw new ArgumentOutOfRangeException($"The operation type '{operationType}' is " + + $"not supported by graphql."); + } + + if (!this.Schema.Operations.ContainsKey(operationType)) + { + var operation = new GraphOperation(operationType); + this.Schema.KnownTypes.EnsureGraphType(operation); + this.Schema.Operations.Add(operation.OperationType, operation); + } + } + + /// + /// An idempodent method that will parse and add the given type into the schema + /// in a manner appropriate to its definition and expected type kind. + /// + /// The type to ensure exists in the graph. + /// The type kind to add the provided + /// as. If the provided type can only be matched to one type kind (such as enums), this + /// value is ignored. + /// + /// + /// + /// is required to differentiate OBJECT from INPUT_OBJECT registrations + /// for explicit type inclusions. + /// + protected virtual void EnsureGraphType(Type type, TypeKind? typeKind = null) + { + Validation.ThrowIfNull(type, nameof(type)); + + type = GraphValidation.EliminateWrappersFromCoreType(type); + + // if the type is already registered, early exit no point in running it through again + var existingGraphType = this.Schema.KnownTypes.FindGraphType(type); + if (existingGraphType != null) + { + if (existingGraphType.Kind == TypeKind.SCALAR) + return; + + if (this.Schema.KnownTypes.Contains(type, typeKind)) + return; + } + + var template = this.MakerFactory.MakeTemplate(type, typeKind); + if (template is IGraphControllerTemplate controllerTemplate) + { + this.AddController(controllerTemplate); + return; + } + + GraphTypeCreationResult makerResult = null; + var maker = this.MakerFactory.CreateTypeMaker(type, typeKind); + if (maker != null) + { + // if a maker can be assigned for this graph type + // create the graph type directly + makerResult = maker.CreateGraphType(template); + } + + if (makerResult != null) + { + this.Schema.KnownTypes.EnsureGraphType(makerResult.GraphType, makerResult.ConcreteType); + this.EnsureDependents(makerResult); + } + } + + /// + /// Ensures the dependents in the provided collection are part of the target . + /// + /// The dependency set to inspect. + protected virtual void EnsureDependents(IGraphItemDependencies dependencySet) + { + foreach (var abstractType in dependencySet.AbstractGraphTypes) + { + this.Schema.KnownTypes.EnsureGraphType(abstractType); + } + + foreach (var dependent in dependencySet.DependentTypes) + { + this.EnsureGraphType(dependent.Type, dependent.ExpectedKind); + } + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Introspection.cs b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Introspection.cs new file mode 100644 index 000000000..1742fd1a7 --- /dev/null +++ b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Introspection.cs @@ -0,0 +1,78 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Engine +{ + using System; + using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Schemas.TypeSystem.Introspection; + using GraphQL.AspNet.Schemas.TypeSystem.Introspection.Fields; + using GraphQL.AspNet.Schemas.TypeSystem.Introspection.Model; + + /// + /// The default schema factory, capable of creating singleton instances of + /// schemas, fully populated and ready to serve requests. + /// + public partial class DefaultGraphQLSchemaFactory + { + + /// + /// Clears, builds and caches the introspection metadata used to describe this schema. If introspection + /// fields have not been added to the schema this method does nothing. No changes to the schema + /// items themselves happens during this method call. + /// + protected virtual void RebuildIntrospectionData() + { + if (this.Schema.Configuration.DeclarationOptions.DisableIntrospection) + return; + + this.EnsureGraphOperationType(GraphOperationType.Query); + this.AddIntrospectionFields(); + + var queryType = this.Schema.Operations[GraphOperationType.Query]; + if (!queryType.Fields.ContainsKey(Constants.ReservedNames.SCHEMA_FIELD)) + return; + + var field = queryType.Fields[Constants.ReservedNames.SCHEMA_FIELD] as Introspection_SchemaField; + field.IntrospectedSchema.Rebuild(); + } + + /// + /// Adds the internal introspection fields to the query operation type if and only if the contained schema allows + /// it through its internal configuration. This method is idempotent. + /// + protected virtual void AddIntrospectionFields() + { + this.EnsureGraphOperationType(GraphOperationType.Query); + var queryField = this.Schema.Operations[GraphOperationType.Query]; + + // Note: introspection fields are defined by the graphql spec, no custom name or item formatting is allowed + // for Type and field name formatting. + // spec: https://graphql.github.io/graphql-spec/October2021/#sec-Schema-Introspection + if (!queryField.Fields.ContainsKey(Constants.ReservedNames.SCHEMA_FIELD)) + { + var introspectedSchema = new IntrospectedSchema(this.Schema); + queryField.Extend(new Introspection_SchemaField(introspectedSchema)); + queryField.Extend(new Introspection_TypeGraphField(introspectedSchema)); + + this.EnsureGraphType(typeof(string)); + this.EnsureGraphType(typeof(bool)); + this.Schema.KnownTypes.EnsureGraphType(new Introspection_DirectiveLocationType(), typeof(DirectiveLocation)); + this.Schema.KnownTypes.EnsureGraphType(new Introspection_DirectiveType(), typeof(IntrospectedDirective)); + this.Schema.KnownTypes.EnsureGraphType(new Introspection_EnumValueType(), typeof(IntrospectedEnumValue)); + this.Schema.KnownTypes.EnsureGraphType(new Introspection_FieldType(), typeof(IntrospectedField)); + this.Schema.KnownTypes.EnsureGraphType(new Introspection_InputValueType(), typeof(IntrospectedInputValueType)); + this.Schema.KnownTypes.EnsureGraphType(new Introspection_SchemaType(), typeof(IntrospectedSchema)); + this.Schema.KnownTypes.EnsureGraphType(new Introspection_TypeKindType(), typeof(TypeKind)); + this.Schema.KnownTypes.EnsureGraphType(new Introspection_TypeType(), typeof(IntrospectedType)); + } + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_RuntimeDefinitions.cs b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_RuntimeDefinitions.cs new file mode 100644 index 000000000..2043ff81b --- /dev/null +++ b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_RuntimeDefinitions.cs @@ -0,0 +1,47 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Engine +{ + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Interfaces.Configuration.Templates; + using GraphQL.AspNet.Internal.TypeTemplates; + + /// + /// The default schema factory, capable of creating singleton instances of + /// schemas, fully populated and ready to serve requests. + /// + public partial class DefaultGraphQLSchemaFactory + { + /// + /// Adds a runtime declared field (with its assigned resolver) as a field in the schema. + /// + /// The runtime defined item to add to the schema. + protected virtual void AddRuntimeSchemaItemDefinition(IGraphQLRuntimeSchemaItemDefinition itemDefinition) + { + if (itemDefinition is IGraphQLRuntimeResolvedFieldDefinition fieldDef) + this.AddRuntimeFieldDefinition(fieldDef); + } + + /// + /// Adds the runtime defined field into the schema. + /// + /// The field definition to add. + protected virtual void AddRuntimeFieldDefinition(IGraphQLRuntimeResolvedFieldDefinition fieldDefinition) + { + Validation.ThrowIfNull(fieldDefinition, nameof(fieldDefinition)); + var template = new RuntimeGraphControllerTemplate(fieldDefinition); + + template.Parse(); + template.ValidateOrThrow(); + + this.AddController(template); + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Validation.cs b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Validation.cs new file mode 100644 index 000000000..c8a2def45 --- /dev/null +++ b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Validation.cs @@ -0,0 +1,40 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Engine +{ + using System; + using System.Collections.Generic; + using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Interfaces.Configuration.Templates; + using GraphQL.AspNet.Schemas.SchemaItemValidators; + using GraphQL.AspNet.Schemas.TypeSystem; + + /// + /// The default schema factory, capable of creating singleton instances of + /// schemas, fully populated and ready to serve requests. + /// + public partial class DefaultGraphQLSchemaFactory + { + /// + /// Validates each registered type, field, argument and directive to ensure that its + /// internally consistance with itself and that the schema is in a usable state. + /// + protected virtual void ValidateSchemaIntegrity() + { + var allItems = this.Schema.AllSchemaItems(includeDirectives: true); + + foreach (var item in allItems) + { + var validator = SchemaItemValidationFactory.CreateValidator(item); + validator.ValidateOrThrow(item, this.Schema); + } + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Engine/DefaultGraphQLTypeMakerFactory.cs b/src/graphql-aspnet/Engine/DefaultGraphQLTypeMakerFactory.cs new file mode 100644 index 000000000..b27ec7a23 --- /dev/null +++ b/src/graphql-aspnet/Engine/DefaultGraphQLTypeMakerFactory.cs @@ -0,0 +1,147 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Schemas.Generation +{ + using System; + using System.Data; + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Controllers; + using GraphQL.AspNet.Directives; + using GraphQL.AspNet.Interfaces.Engine; + using GraphQL.AspNet.Interfaces.Internal; + using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Schemas.Generation.TypeMakers; + using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Schemas.TypeSystem.Scalars; + + /// + /// An object used during schema generation to organize and expose the various + /// template objects to the schema. + /// + /// The type of the schema this maker factory is registered to handle. + public class DefaultGraphQLTypeMakerFactory : IGraphQLTypeMakerFactory + where TSchema : class, ISchema + { + /// + /// Initializes a new instance of the class. + /// + public DefaultGraphQLTypeMakerFactory() + { + } + + /// + public virtual IGraphTypeTemplate MakeTemplate(Type objectType, TypeKind? kind = null) + { + if (objectType == null) + return null; + + // attempt to turn "int" into "IntScalarType" when necessary + objectType = GlobalScalars.FindBuiltInScalarType(objectType) ?? objectType; + + IGraphTypeTemplate template; + if (Validation.IsCastable(objectType)) + template = new ScalarGraphTypeTemplate(objectType); + else if (Validation.IsCastable(objectType)) + template = new UnionGraphTypeTemplate(objectType); + else if (objectType.IsEnum) + template = new EnumGraphTypeTemplate(objectType); + else if (objectType.IsInterface) + template = new InterfaceGraphTypeTemplate(objectType); + else if (Validation.IsCastable(objectType)) + template = new GraphDirectiveTemplate(objectType); + else if (Validation.IsCastable(objectType)) + template = new GraphControllerTemplate(objectType); + else if (kind.HasValue && kind.Value == TypeKind.INPUT_OBJECT) + template = new InputObjectGraphTypeTemplate(objectType); + else + template = new ObjectGraphTypeTemplate(objectType); + + template.Parse(); + template.ValidateOrThrow(); + + return template; + } + + /// + public virtual IGraphTypeMaker CreateTypeMaker(Type objectType, TypeKind? kind = null) + { + if (objectType == null) + return null; + + objectType = GlobalScalars.FindBuiltInScalarType(objectType) ?? objectType; + + if (Validation.IsCastable(objectType)) + return new ScalarGraphTypeMaker(this.Schema.Configuration); + + if (objectType.IsEnum) + return new EnumGraphTypeMaker(this.Schema.Configuration); + + if (objectType.IsInterface) + return new InterfaceGraphTypeMaker(this.Schema.Configuration, this.CreateFieldMaker()); + + if (Validation.IsCastable(objectType)) + return new DirectiveMaker(this.Schema.Configuration, this.CreateArgumentMaker()); + + if (Validation.IsCastable(objectType)) + return null; + + if (Validation.IsCastable(objectType)) + return new UnionGraphTypeMaker(this.Schema.Configuration); + + if (kind.HasValue && kind.Value == TypeKind.INPUT_OBJECT) + { + return new InputObjectGraphTypeMaker( + this.Schema.Configuration, + this.CreateFieldMaker()); + } + + // when all else fails just use an object maker + return new ObjectGraphTypeMaker( + this.Schema.Configuration, + this.CreateFieldMaker()); + } + + /// + public virtual IGraphFieldMaker CreateFieldMaker() + { + return new GraphFieldMaker(this.Schema, this); + } + + /// + public virtual IGraphArgumentMaker CreateArgumentMaker() + { + return new GraphArgumentMaker(this.Schema); + } + + /// + public virtual IUnionGraphTypeMaker CreateUnionMaker() + { + return new UnionGraphTypeMaker(this.Schema.Configuration); + } + + /// + public void Initialize(ISchema schemaInstance) + { + Validation.ThrowIfNull(schemaInstance, nameof(schemaInstance)); + + if (this.Schema != null) + throw new InvalidOperationException("This instance has already been initialized with a schema"); + + this.Schema = schemaInstance; + } + + /// + /// Gets the schema this factory works against. + /// + /// The schema. + public ISchema Schema { get; private set; } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Engine/DefaultGraphTypeMakerProvider.cs b/src/graphql-aspnet/Engine/DefaultGraphTypeMakerProvider.cs deleted file mode 100644 index bdded513c..000000000 --- a/src/graphql-aspnet/Engine/DefaultGraphTypeMakerProvider.cs +++ /dev/null @@ -1,95 +0,0 @@ -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - -namespace GraphQL.AspNet.Engine -{ - using System; - using System.Reflection; - using GraphQL.AspNet.Common; - using GraphQL.AspNet.Common.Extensions; - using GraphQL.AspNet.Common.Generics; - using GraphQL.AspNet.Engine.TypeMakers; - using GraphQL.AspNet.Execution.Exceptions; - using GraphQL.AspNet.Interfaces.Engine; - using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Schemas.TypeSystem; - - /// - /// An abstract factory for creating type makers using all the default type makers types. - /// - public class DefaultGraphTypeMakerProvider : IGraphTypeMakerProvider - { - /// - public virtual IGraphFieldMaker CreateFieldMaker(ISchema schema) - { - return new GraphFieldMaker(schema); - } - - /// - public virtual IGraphTypeMaker CreateTypeMaker(ISchema schema, TypeKind kind) - { - if (schema == null) - return null; - - switch (kind) - { - case TypeKind.DIRECTIVE: - return new DirectiveMaker(schema); - - case TypeKind.SCALAR: - return new ScalarGraphTypeMaker(); - - case TypeKind.OBJECT: - return new ObjectGraphTypeMaker(schema); - - case TypeKind.INTERFACE: - return new InterfaceGraphTypeMaker(schema); - - case TypeKind.ENUM: - return new EnumGraphTypeMaker(schema); - - case TypeKind.INPUT_OBJECT: - return new InputObjectGraphTypeMaker(schema); - - // note: unions cannot currently be made via the type maker stack - } - - return null; - } - - /// - public IUnionGraphTypeMaker CreateUnionMaker(ISchema schema) - { - return new UnionGraphTypeMaker(schema); - } - - /// - public IGraphUnionProxy CreateUnionProxyFromType(Type proxyType) - { - if (proxyType == null) - return null; - - IGraphUnionProxy proxy = null; - if (Validation.IsCastable(proxyType)) - { - var paramlessConstructor = proxyType.GetConstructor(BindingFlags.Instance | BindingFlags.Public, null, Type.EmptyTypes, null); - if (paramlessConstructor == null) - { - throw new GraphTypeDeclarationException( - $"The union proxy type '{proxyType.FriendlyName()}' could not be instantiated. " + - "All union proxy types must declare a parameterless constructor."); - } - - proxy = InstanceFactory.CreateInstance(proxyType) as IGraphUnionProxy; - } - - return proxy; - } - } -} \ No newline at end of file diff --git a/src/graphql-aspnet/Engine/DefaultScalarGraphTypeProvider.cs b/src/graphql-aspnet/Engine/DefaultScalarGraphTypeProvider.cs deleted file mode 100644 index a9c2b3154..000000000 --- a/src/graphql-aspnet/Engine/DefaultScalarGraphTypeProvider.cs +++ /dev/null @@ -1,286 +0,0 @@ -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - -namespace GraphQL.AspNet.Engine -{ - using System; - using System.Collections.Generic; - using System.Linq; - using GraphQL.AspNet.Common; - using GraphQL.AspNet.Common.Extensions; - using GraphQL.AspNet.Common.Generics; - using GraphQL.AspNet.Execution.Exceptions; - using GraphQL.AspNet.Interfaces.Engine; - using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal; - using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Schemas.TypeSystem.Scalars; - - /// - /// A built-in, default collection of instances of objects; - /// the most fundamental unit of graphql. - /// - public class DefaultScalarGraphTypeProvider : IScalarGraphTypeProvider - { - private readonly List _scalarReferences; - private readonly IDictionary _scalarsByConcreteType; - private readonly IDictionary _scalarsByName; - - /// - /// Initializes a new instance of the class. - /// - public DefaultScalarGraphTypeProvider() - { - _scalarReferences = new List(); - _scalarsByConcreteType = new Dictionary(); - _scalarsByName = new Dictionary(); - - this.RegisterScalar(typeof(IntScalarType)); - this.RegisterScalar(typeof(LongScalarType)); - this.RegisterScalar(typeof(UIntScalarType)); - this.RegisterScalar(typeof(ULongScalarType)); - this.RegisterScalar(typeof(FloatScalarType)); - this.RegisterScalar(typeof(DoubleScalarType)); - this.RegisterScalar(typeof(DecimalScalarType)); - this.RegisterScalar(typeof(BooleanScalarType)); - this.RegisterScalar(typeof(StringScalarType)); - this.RegisterScalar(typeof(DateTimeScalarType)); - this.RegisterScalar(typeof(DateTimeOffsetScalarType)); - this.RegisterScalar(typeof(ByteScalarType)); - this.RegisterScalar(typeof(SByteScalarType)); - this.RegisterScalar(typeof(GuidScalarType)); - this.RegisterScalar(typeof(UriScalarType)); - this.RegisterScalar(typeof(GraphIdScalarType)); - this.RegisterScalar(typeof(ShortScalarType)); - this.RegisterScalar(typeof(UShortScalarType)); - -#if NET6_0_OR_GREATER - this.RegisterScalar(typeof(DateOnlyScalarType)); - this.RegisterScalar(typeof(TimeOnlyScalarType)); -#endif - } - - /// - public virtual bool IsLeaf(Type type) - { - if (type == null) - return false; - - if (type.IsEnum) - return true; - - return _scalarsByConcreteType.ContainsKey(type); - } - - /// - public virtual Type EnsureBuiltInTypeReference(Type type) - { - if (this.IsScalar(type)) - { - return _scalarsByConcreteType[type].PrimaryType; - } - - return type; - } - - /// - public virtual bool IsScalar(Type concreteType) - { - return concreteType != null && _scalarsByConcreteType.ContainsKey(concreteType); - } - - /// - public virtual bool IsScalar(string scalarName) - { - return scalarName != null && _scalarsByName.ContainsKey(scalarName); - } - - /// - public virtual Type RetrieveConcreteType(string scalarName) - { - if (this.IsScalar(scalarName)) - return _scalarsByName[scalarName].PrimaryType; - return null; - } - - /// - public virtual string RetrieveScalarName(Type concreteType) - { - if (this.IsScalar(concreteType)) - return _scalarsByConcreteType[concreteType].Name; - - return null; - } - - /// - public virtual IScalarGraphType CreateScalar(string scalarName) - { - if (this.IsScalar(scalarName)) - return this.CreateScalarFromInstanceType(_scalarsByName[scalarName].InstanceType); - - return null; - } - - /// - public virtual IScalarGraphType CreateScalar(Type concreteType) - { - if (this.IsScalar(concreteType)) - { - var primaryInstanceType = this.EnsureBuiltInTypeReference(concreteType); - return this.CreateScalarFromInstanceType(_scalarsByConcreteType[primaryInstanceType].InstanceType); - } - - return null; - } - - /// - /// Creates a new instance of the scalar from its formal type declaration. - /// - /// Type of the scalar. - /// IScalarGraphType. - protected virtual IScalarGraphType CreateScalarFromInstanceType(Type scalarType) - { - return InstanceFactory.CreateInstance(scalarType) as IScalarGraphType; - } - - private ScalarReference FindReferenceByImplementationType(Type type) - { - var primaryType = this.EnsureBuiltInTypeReference(type); - if (this.IsScalar(primaryType)) - return _scalarsByConcreteType[primaryType]; - - return null; - } - - /// - public virtual void RegisterCustomScalar(Type scalarType) - { - this.RegisterScalar(scalarType); - } - - /// - /// Internal logic that must be excuted to register a scalar, regardless of what - /// any subclass may do. - /// - /// Type of the scalar. - private void RegisterScalar(Type scalarType) - { - Validation.ThrowIfNull(scalarType, nameof(scalarType)); - - if (!Validation.IsCastable(scalarType)) - { - throw new GraphTypeDeclarationException( - $"The scalar must implement the interface '{typeof(IScalarGraphType).FriendlyName()}'."); - } - - var paramlessConstructor = scalarType.GetConstructor(new Type[0]); - if (paramlessConstructor == null) - { - throw new GraphTypeDeclarationException( - "The scalar must declare a public, parameterless constructor."); - } - - var graphType = InstanceFactory.CreateInstance(scalarType) as IScalarGraphType; - if (string.IsNullOrWhiteSpace(graphType.Name)) - { - throw new GraphTypeDeclarationException( - "The scalar must supply a name that is not null or whitespace."); - } - - if (!GraphValidation.IsValidGraphName(graphType.Name)) - { - throw new GraphTypeDeclarationException( - $"The scalar must supply a name that that conforms to the standard rules for GraphQL. (Regex: {Constants.RegExPatterns.NameRegex})"); - } - - if (graphType.Kind != TypeKind.SCALAR) - { - throw new GraphTypeDeclarationException( - $"The scalar's type kind must be set to '{nameof(TypeKind.SCALAR)}'."); - } - - if (graphType.ObjectType == null) - { - throw new GraphTypeDeclarationException( - $"The scalar must supply a value for '{nameof(graphType.ObjectType)}', is cannot be null."); - } - - if (graphType.SourceResolver == null) - { - throw new GraphTypeDeclarationException( - $"The scalar must supply a value for '{nameof(graphType.SourceResolver)}' that can convert data from a " + - $"query into the primary object type of '{graphType.ObjectType.FriendlyName()}'."); - } - - if (graphType.ValueType == ScalarValueType.Unknown) - { - throw new GraphTypeDeclarationException( - $"The scalar must supply a value for '{nameof(graphType.ValueType)}'. This lets the validation engine " + - "know what data types submitted on a user query could be parsed into a value for this scale."); - } - - if (graphType.OtherKnownTypes == null) - { - throw new GraphTypeDeclarationException( - $"Custom scalars must supply a value for '{nameof(graphType.OtherKnownTypes)}', it cannot be null. " + - $"Use '{nameof(TypeCollection)}.{nameof(TypeCollection.Empty)}' if there are no other known types."); - } - - if (graphType.AppliedDirectives == null || graphType.AppliedDirectives.Parent != graphType) - { - throw new GraphTypeDeclarationException( - $"Custom scalars must supply a value for '{nameof(graphType.AppliedDirectives)}', it cannot be null. " + - $"The '{nameof(IAppliedDirectiveCollection.Parent)}' property of the directive collection must also be set to the scalar itself."); - } - - var isAScalarAlready = this.IsScalar(graphType.Name); - if (isAScalarAlready) - { - throw new GraphTypeDeclarationException( - $"A scalar named '{graphType.Name}' already exists in this graphql instance."); - } - - var reference = this.FindReferenceByImplementationType(graphType.ObjectType); - if (reference != null) - { - throw new GraphTypeDeclarationException( - $"The scalar's primary object type of '{graphType.ObjectType.FriendlyName()}' is " + - $"already reserved by the scalar '{reference.Name}'. Scalar object types must be unique."); - } - - foreach (var type in graphType.OtherKnownTypes) - { - var otherReference = this.FindReferenceByImplementationType(type); - if (otherReference != null) - { - throw new GraphTypeDeclarationException( - $"The scalar's other known type of '{type.FriendlyName()}' is " + - $"already reserved by the scalar '{otherReference.Name}'. Scalar object types must be unique."); - } - } - - var newReference = ScalarReference.Create(graphType, scalarType); - _scalarsByConcreteType.Add(newReference.PrimaryType, newReference); - foreach (var otherRef in newReference.OtherKnownTypes) - _scalarsByConcreteType.Add(otherRef, newReference); - - _scalarsByName.Add(newReference.Name, newReference); - _scalarReferences.Add(newReference); - } - - /// - /// Gets an enumeration of the known concrete type classes related to the scalars known to this provider. - /// - /// The concrete types. - public IEnumerable ConcreteTypes => _scalarsByConcreteType.Keys; - - /// - public IEnumerable ScalarInstanceTypes => _scalarReferences.Select(x => x.InstanceType); - } -} \ No newline at end of file diff --git a/src/graphql-aspnet/Engine/DefaultTypeTemplateProvider.cs b/src/graphql-aspnet/Engine/DefaultTypeTemplateProvider.cs deleted file mode 100644 index ecbc87f24..000000000 --- a/src/graphql-aspnet/Engine/DefaultTypeTemplateProvider.cs +++ /dev/null @@ -1,134 +0,0 @@ -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - -namespace GraphQL.AspNet.Engine -{ - using System; - using System.Collections.Concurrent; - using GraphQL.AspNet.Common; - using GraphQL.AspNet.Common.Extensions; - using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Directives; - using GraphQL.AspNet.Execution.Exceptions; - using GraphQL.AspNet.Interfaces.Engine; - using GraphQL.AspNet.Interfaces.Internal; - using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal; - using GraphQL.AspNet.Internal.TypeTemplates; - using GraphQL.AspNet.Schemas.TypeSystem; - - /// - /// A singular collection of all the graph type templates currently in the loaded app domain. Templates are - /// schema agnostic and expected to be reused across multiple schema instances. - /// - public class DefaultTypeTemplateProvider : IGraphTypeTemplateProvider - { - // maintain a collection of any already parsed - // templates to speed up any dynamic construction operations that may occur at run time. - private readonly ConcurrentDictionary, IGraphTypeTemplate> _knownObjects; - - /// - /// Initializes a new instance of the class. - /// - public DefaultTypeTemplateProvider() - { - _knownObjects = new ConcurrentDictionary, IGraphTypeTemplate>(); - this.CacheTemplates = true; - } - - /// - public ISchemaItemTemplate ParseType(TypeKind? kind = null) - { - return this.ParseType(typeof(TObjectType), kind); - } - - /// - public IGraphTypeTemplate ParseType(Type objectType, TypeKind? kind = null) - { - Validation.ThrowIfNull(objectType, nameof(objectType)); - - var typeKind = GraphValidation.ResolveTypeKind(objectType, kind); - var typeKey = Tuple.Create(typeKind, objectType); - - if (_knownObjects.TryGetValue(typeKey, out var template) && this.CacheTemplates) - return template; - - if (GraphQLProviders.ScalarProvider.IsScalar(objectType)) - { - throw new GraphTypeDeclarationException( - $"The type '{objectType.FriendlyName()}' is a known scalar type. Scalars must be explicitly defined and cannot be templated.", - objectType); - } - - if (Validation.IsCastable(objectType)) - { - throw new GraphTypeDeclarationException( - $"The union proxy '{objectType.FriendlyName()}' cannot be directly parsed as a graph type. Double check " + - "your field attribute declarations.", - objectType); - } - - GraphValidation.IsValidGraphType(objectType, true); - - template = this.MakeTemplate(objectType, typeKind); - template.Parse(); - template.ValidateOrThrow(); - - if (this.CacheTemplates) - _knownObjects.TryAdd(typeKey, template); - - return template; - } - - /// - public void Clear() - { - _knownObjects.Clear(); - } - - /// - /// Makes a graph template from the given type. - /// - /// Type of the object. - /// The kind of graph type to parse for. - /// IGraphItemTemplate. - protected virtual IGraphTypeTemplate MakeTemplate(Type objectType, TypeKind kind) - { - return MakeTemplateInternal(objectType, kind); - } - - /// - /// Internal overload of the default factory method for creating template objects. Used in various aspects of testing. - /// - /// Type of the object. - /// The kind. - /// IGraphTypeTemplate. - internal static IGraphTypeTemplate MakeTemplateInternal(Type objectType, TypeKind kind) - { - if (objectType.IsInterface) - return new InterfaceGraphTypeTemplate(objectType); - if (objectType.IsEnum) - return new EnumGraphTypeTemplate(objectType); - if (Validation.IsCastable(objectType)) - return new GraphControllerTemplate(objectType); - if (Validation.IsCastable(objectType)) - return new GraphDirectiveTemplate(objectType); - if (kind == TypeKind.INPUT_OBJECT) - return new InputObjectGraphTypeTemplate(objectType); - - return new ObjectGraphTypeTemplate(objectType); - } - - /// - public int Count => _knownObjects.Count; - - /// - public bool CacheTemplates { get; set; } - } -} \ No newline at end of file diff --git a/src/graphql-aspnet/Engine/TypeMakers/ObjectGraphTypeMaker.cs b/src/graphql-aspnet/Engine/TypeMakers/ObjectGraphTypeMaker.cs deleted file mode 100644 index 580cb4c18..000000000 --- a/src/graphql-aspnet/Engine/TypeMakers/ObjectGraphTypeMaker.cs +++ /dev/null @@ -1,122 +0,0 @@ -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - -namespace GraphQL.AspNet.Engine.TypeMakers -{ - using System; - using System.Collections.Generic; - using System.Linq; - using GraphQL.AspNet.Common; - using GraphQL.AspNet.Configuration; - using GraphQL.AspNet.Interfaces.Engine; - using GraphQL.AspNet.Interfaces.Internal; - using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal; - using GraphQL.AspNet.Internal.TypeTemplates; - using GraphQL.AspNet.Schemas.TypeSystem; - - /// - /// A "maker" capable of producing a qualified from its related template. - /// - public class ObjectGraphTypeMaker : IGraphTypeMaker - { - private readonly ISchema _schema; - - /// - /// Initializes a new instance of the class. - /// - /// The schema defining the graph type creation rules this generator should follow. - public ObjectGraphTypeMaker(ISchema schema) - { - _schema = Validation.ThrowIfNullOrReturn(schema, nameof(schema)); - } - - /// - /// Inspects the given type and, in accordance with the rules of this maker, will - /// generate a complete set of necessary graph types required to support it. - /// - /// The concrete type to incorporate into the schema. - /// GraphTypeCreationResult. - public virtual GraphTypeCreationResult CreateGraphType(Type concreteType) - { - if (concreteType == null) - return null; - - var template = GraphQLProviders.TemplateProvider.ParseType(concreteType, TypeKind.OBJECT) as IObjectGraphTypeTemplate; - if (template == null) - return null; - - var result = new GraphTypeCreationResult(); - - var formatter = _schema.Configuration.DeclarationOptions.GraphNamingFormatter; - var directives = template.CreateAppliedDirectives(); - - var objectType = new ObjectGraphType( - formatter.FormatGraphTypeName(template.Name), - concreteType, - template.Route, - directives) - { - Description = template.Description, - Publish = template.Publish, - }; - - result.GraphType = objectType; - result.ConcreteType = concreteType; - - // account for any potential type system directives - result.AddDependentRange(template.RetrieveRequiredTypes()); - - var fieldMaker = GraphQLProviders.GraphTypeMakerProvider.CreateFieldMaker(_schema); - foreach (var fieldTemplate in ObjectGraphTypeMaker.GatherFieldTemplates(template, _schema)) - { - var fieldResult = fieldMaker.CreateField(fieldTemplate); - objectType.Extend(fieldResult.Field); - result.MergeDependents(fieldResult); - } - - // add in declared interfaces by name - foreach (var iface in template.DeclaredInterfaces) - { - objectType.InterfaceNames.Add(formatter.FormatGraphTypeName(GraphTypeNames.ParseName(iface, TypeKind.INTERFACE))); - } - - return result; - } - - /// - /// Creates the collection of graph fields that belong to the template. - /// - /// The template to generate fields for. - /// The schema. - /// IEnumerable<IGraphField>. - internal static IEnumerable GatherFieldTemplates(IGraphTypeFieldTemplateContainer template, ISchema schema) - { - // gather the fields to include in the graph type - var requiredDeclarations = template.DeclarationRequirements ?? schema.Configuration.DeclarationOptions.FieldDeclarationRequirements; - - return template.FieldTemplates.Values.Where(x => - { - if (x.IsExplicitDeclaration) - return true; - - switch (x.FieldSource) - { - case GraphFieldSource.Method: - return requiredDeclarations.AllowImplicitMethods(); - - case GraphFieldSource.Property: - return requiredDeclarations.AllowImplicitProperties(); - } - - return false; - }); - } - } -} \ No newline at end of file diff --git a/src/graphql-aspnet/Engine/TypeMakers/ScalarGraphTypeMaker.cs b/src/graphql-aspnet/Engine/TypeMakers/ScalarGraphTypeMaker.cs deleted file mode 100644 index 5f666739f..000000000 --- a/src/graphql-aspnet/Engine/TypeMakers/ScalarGraphTypeMaker.cs +++ /dev/null @@ -1,47 +0,0 @@ -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - -namespace GraphQL.AspNet.Engine.TypeMakers -{ - using System; - using GraphQL.AspNet.Interfaces.Engine; - using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Schemas.TypeSystem; - - /// - /// A "maker" capable of producing a qualified from its related template. - /// - public class ScalarGraphTypeMaker : IGraphTypeMaker - { - /// - public GraphTypeCreationResult CreateGraphType(Type concreteType) - { - var scalarType = GraphQLProviders.ScalarProvider.CreateScalar(concreteType); - if (scalarType != null) - { - var result = new GraphTypeCreationResult() - { - GraphType = scalarType, - ConcreteType = concreteType, - }; - - // add any known diretives as dependents - foreach (var directiveToApply in scalarType.AppliedDirectives) - { - if (directiveToApply.DirectiveType != null) - result.AddDependent(directiveToApply.DirectiveType, TypeKind.DIRECTIVE); - } - - return result; - } - - return null; - } - } -} \ No newline at end of file diff --git a/src/graphql-aspnet/Execution/DirectiveProcessorTypeSystem.cs b/src/graphql-aspnet/Execution/DirectiveProcessorTypeSystem.cs index 349c7b488..e6248e054 100644 --- a/src/graphql-aspnet/Execution/DirectiveProcessorTypeSystem.cs +++ b/src/graphql-aspnet/Execution/DirectiveProcessorTypeSystem.cs @@ -61,10 +61,14 @@ public DirectiveProcessorTypeSystem(IServiceProvider serviceProvider, IQuerySess /// The schema to apply directives too. public void ApplyDirectives(TSchema schema) { + Validation.ThrowIfNull(schema, nameof(schema)); + // all schema items var anyDirectivesApplied = false; foreach (var item in schema.AllSchemaItems()) + { anyDirectivesApplied = this.ApplyDirectivesToItem(schema, item) || anyDirectivesApplied; + } } /// diff --git a/src/graphql-aspnet/Execution/FieldResolution/FieldDataItem.cs b/src/graphql-aspnet/Execution/FieldResolution/FieldDataItem.cs index bfe6f39ed..38e07f5bb 100644 --- a/src/graphql-aspnet/Execution/FieldResolution/FieldDataItem.cs +++ b/src/graphql-aspnet/Execution/FieldResolution/FieldDataItem.cs @@ -369,8 +369,9 @@ public bool GenerateResult(out IQueryResponseItem result) if (!this.Status.IncludeInOutput()) return false; - // leafs have nothing underneath them, the resolved data IS the item value. - if (this.FieldContext.Field.IsLeaf) + // leafs have nothing underneath them, the resolved data IS the item value. + var graphType = this.Schema.KnownTypes.FindGraphType(this.FieldContext.Field.TypeExpression.TypeName); + if (graphType.Kind.IsLeafKind()) { // List and List are leafs since there is no further // resolution to the data but its still must be projected diff --git a/src/graphql-aspnet/Execution/GraphSchemaInitializer.cs b/src/graphql-aspnet/Execution/GraphSchemaInitializer.cs deleted file mode 100644 index dbc7bda74..000000000 --- a/src/graphql-aspnet/Execution/GraphSchemaInitializer.cs +++ /dev/null @@ -1,115 +0,0 @@ -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - -namespace GraphQL.AspNet.Execution -{ - using System; - using System.Linq; - using GraphQL.AspNet.Attributes; - using GraphQL.AspNet.Common; - using GraphQL.AspNet.Common.Extensions; - using GraphQL.AspNet.Configuration; - using GraphQL.AspNet.Interfaces.Configuration.Templates; - using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Schemas; - - /// - /// Perform a set of standardized steps to setup and configure any graph schema according to the rules - /// for document operation execution used by the various schema pipelines. - /// - /// The type of the schema that the initializer - /// can work with. - internal sealed class GraphSchemaInitializer - where TSchema : class, ISchema - { - private readonly SchemaOptions _options; - private readonly IServiceProvider _serviceProvider; - - /// - /// Initializes a new instance of the class. - /// - /// The options. - /// The service provider from which to draw componentry for - /// initailization. - public GraphSchemaInitializer(SchemaOptions options, IServiceProvider serviceProvider) - { - _options = Validation.ThrowIfNullOrReturn(options, nameof(options)); - _serviceProvider = Validation.ThrowIfNullOrReturn(serviceProvider, nameof(serviceProvider)); - } - - /// - /// Initializes the schema: - /// * Add any controllers to the schema instance that were configured during startup. - /// * Add all methods, virtual graph types, return types parameters and property configurations. - /// * Add any additional types added at startup. - /// * Register introspection meta-fields. - /// - /// The schema to initialize. - public void Initialize(TSchema schema) - { - Validation.ThrowIfNull(schema, nameof(schema)); - if (schema.IsInitialized) - return; - - lock (schema) - { - if (schema.IsInitialized) - return; - - schema.Configuration.Merge(_options.CreateConfiguration()); - - var manager = new GraphSchemaManager(schema); - manager.AddBuiltInDirectives(); - - // Step 1: Register any configured types to this instance - // -------------------------------------- - foreach (var registration in _options.SchemaTypesToRegister) - { - var typeDeclaration = registration.Type.SingleAttributeOrDefault(); - if (typeDeclaration != null && typeDeclaration.PreventAutoInclusion) - continue; - - manager.EnsureGraphType(registration.Type, registration.TypeKind); - } - - // Step 2: Register any runtime configured fields and directives (minimal api) - // -------------------------------------- - var runtimeFields = _options.RuntimeTemplates - .Where(x => x is IGraphQLRuntimeResolvedFieldDefinition) - .Cast(); - - foreach (var field in runtimeFields) - manager.AddRuntimeFieldDeclaration(field); - - // Step 3: execute any assigned schema configuration extensions - // -------------------------------------- - // this includes any late bound directives added to the type system via .ApplyDirective() - foreach (var extension in _options.ConfigurationExtensions) - extension.Configure(schema); - - // Step 4: apply all queued type system directives - // -------------------------------------- - var processor = new DirectiveProcessorTypeSystem( - _serviceProvider, - new QuerySession()); - processor.ApplyDirectives(schema); - - // Step 5: Run final validations to ensure the schema is internally consistant - // -------------------------------------- - manager.ValidateSchemaIntegrity(); - - // Step 6: Rebuild introspection data to match the now completed schema instance - // -------------------------------------- - manager.RebuildIntrospectionData(); - - schema.IsInitialized = true; - } - } - } -} \ No newline at end of file diff --git a/src/graphql-aspnet/Internal/Resolvers/EnumInputValueResolver.cs b/src/graphql-aspnet/Execution/Resolvers/EnumInputValueResolver.cs similarity index 100% rename from src/graphql-aspnet/Internal/Resolvers/EnumInputValueResolver.cs rename to src/graphql-aspnet/Execution/Resolvers/EnumInputValueResolver.cs diff --git a/src/graphql-aspnet/Internal/Resolvers/EnumLeafValueResolver.cs b/src/graphql-aspnet/Execution/Resolvers/EnumLeafValueResolver.cs similarity index 100% rename from src/graphql-aspnet/Internal/Resolvers/EnumLeafValueResolver.cs rename to src/graphql-aspnet/Execution/Resolvers/EnumLeafValueResolver.cs diff --git a/src/graphql-aspnet/Internal/Resolvers/ExtendedGraphFieldResolver.cs b/src/graphql-aspnet/Execution/Resolvers/ExtendedGraphFieldResolver.cs similarity index 100% rename from src/graphql-aspnet/Internal/Resolvers/ExtendedGraphFieldResolver.cs rename to src/graphql-aspnet/Execution/Resolvers/ExtendedGraphFieldResolver.cs diff --git a/src/graphql-aspnet/Internal/Resolvers/FieldResolverMetaData.cs b/src/graphql-aspnet/Execution/Resolvers/FieldResolverMetaData.cs similarity index 100% rename from src/graphql-aspnet/Internal/Resolvers/FieldResolverMetaData.cs rename to src/graphql-aspnet/Execution/Resolvers/FieldResolverMetaData.cs diff --git a/src/graphql-aspnet/Internal/Resolvers/FieldResolverParameterMetaData.cs b/src/graphql-aspnet/Execution/Resolvers/FieldResolverParameterMetaData.cs similarity index 100% rename from src/graphql-aspnet/Internal/Resolvers/FieldResolverParameterMetaData.cs rename to src/graphql-aspnet/Execution/Resolvers/FieldResolverParameterMetaData.cs diff --git a/src/graphql-aspnet/Internal/Resolvers/FieldResolverParameterMetaDataCollection.cs b/src/graphql-aspnet/Execution/Resolvers/FieldResolverParameterMetaDataCollection.cs similarity index 100% rename from src/graphql-aspnet/Internal/Resolvers/FieldResolverParameterMetaDataCollection.cs rename to src/graphql-aspnet/Execution/Resolvers/FieldResolverParameterMetaDataCollection.cs diff --git a/src/graphql-aspnet/Internal/Resolvers/FunctionGraphFieldResolver{TSource,TReturn}.cs b/src/graphql-aspnet/Execution/Resolvers/FunctionGraphFieldResolver{TSource,TReturn}.cs similarity index 100% rename from src/graphql-aspnet/Internal/Resolvers/FunctionGraphFieldResolver{TSource,TReturn}.cs rename to src/graphql-aspnet/Execution/Resolvers/FunctionGraphFieldResolver{TSource,TReturn}.cs diff --git a/src/graphql-aspnet/Internal/Resolvers/GraphControllerActionResolver.cs b/src/graphql-aspnet/Execution/Resolvers/GraphControllerActionResolver.cs similarity index 100% rename from src/graphql-aspnet/Internal/Resolvers/GraphControllerActionResolver.cs rename to src/graphql-aspnet/Execution/Resolvers/GraphControllerActionResolver.cs diff --git a/src/graphql-aspnet/Internal/Resolvers/GraphControllerActionResolverBase.cs b/src/graphql-aspnet/Execution/Resolvers/GraphControllerActionResolverBase.cs similarity index 100% rename from src/graphql-aspnet/Internal/Resolvers/GraphControllerActionResolverBase.cs rename to src/graphql-aspnet/Execution/Resolvers/GraphControllerActionResolverBase.cs diff --git a/src/graphql-aspnet/Internal/Resolvers/GraphControllerRouteFieldResolver.cs b/src/graphql-aspnet/Execution/Resolvers/GraphControllerRouteFieldResolver.cs similarity index 100% rename from src/graphql-aspnet/Internal/Resolvers/GraphControllerRouteFieldResolver.cs rename to src/graphql-aspnet/Execution/Resolvers/GraphControllerRouteFieldResolver.cs diff --git a/src/graphql-aspnet/Internal/Resolvers/GraphDirectiveActionResolver.cs b/src/graphql-aspnet/Execution/Resolvers/GraphDirectiveActionResolver.cs similarity index 100% rename from src/graphql-aspnet/Internal/Resolvers/GraphDirectiveActionResolver.cs rename to src/graphql-aspnet/Execution/Resolvers/GraphDirectiveActionResolver.cs diff --git a/src/graphql-aspnet/Internal/Resolvers/InputObjectValueResolver.cs b/src/graphql-aspnet/Execution/Resolvers/InputObjectValueResolver.cs similarity index 100% rename from src/graphql-aspnet/Internal/Resolvers/InputObjectValueResolver.cs rename to src/graphql-aspnet/Execution/Resolvers/InputObjectValueResolver.cs diff --git a/src/graphql-aspnet/Internal/Resolvers/InputValueResolverBase.cs b/src/graphql-aspnet/Execution/Resolvers/InputValueResolverBase.cs similarity index 100% rename from src/graphql-aspnet/Internal/Resolvers/InputValueResolverBase.cs rename to src/graphql-aspnet/Execution/Resolvers/InputValueResolverBase.cs diff --git a/src/graphql-aspnet/Internal/Resolvers/InputValueResolverMethodGenerator.cs b/src/graphql-aspnet/Execution/Resolvers/InputValueResolverMethodGenerator.cs similarity index 100% rename from src/graphql-aspnet/Internal/Resolvers/InputValueResolverMethodGenerator.cs rename to src/graphql-aspnet/Execution/Resolvers/InputValueResolverMethodGenerator.cs diff --git a/src/graphql-aspnet/Internal/Resolvers/InternalFieldResolverMetaData.cs b/src/graphql-aspnet/Execution/Resolvers/InternalFieldResolverMetaData.cs similarity index 100% rename from src/graphql-aspnet/Internal/Resolvers/InternalFieldResolverMetaData.cs rename to src/graphql-aspnet/Execution/Resolvers/InternalFieldResolverMetaData.cs diff --git a/src/graphql-aspnet/Internal/Resolvers/Introspeection/Schema_TypeGraphFieldResolver.cs b/src/graphql-aspnet/Execution/Resolvers/Introspeection/Schema_TypeGraphFieldResolver.cs similarity index 100% rename from src/graphql-aspnet/Internal/Resolvers/Introspeection/Schema_TypeGraphFieldResolver.cs rename to src/graphql-aspnet/Execution/Resolvers/Introspeection/Schema_TypeGraphFieldResolver.cs diff --git a/src/graphql-aspnet/Internal/Resolvers/Introspeection/Type_EnumValuesGraphFieldResolver.cs b/src/graphql-aspnet/Execution/Resolvers/Introspeection/Type_EnumValuesGraphFieldResolver.cs similarity index 100% rename from src/graphql-aspnet/Internal/Resolvers/Introspeection/Type_EnumValuesGraphFieldResolver.cs rename to src/graphql-aspnet/Execution/Resolvers/Introspeection/Type_EnumValuesGraphFieldResolver.cs diff --git a/src/graphql-aspnet/Internal/Resolvers/Introspeection/Type_TypeGraphFieldResolver.cs b/src/graphql-aspnet/Execution/Resolvers/Introspeection/Type_TypeGraphFieldResolver.cs similarity index 100% rename from src/graphql-aspnet/Internal/Resolvers/Introspeection/Type_TypeGraphFieldResolver.cs rename to src/graphql-aspnet/Execution/Resolvers/Introspeection/Type_TypeGraphFieldResolver.cs diff --git a/src/graphql-aspnet/Internal/Resolvers/ListInputValueResolver.cs b/src/graphql-aspnet/Execution/Resolvers/ListInputValueResolver.cs similarity index 100% rename from src/graphql-aspnet/Internal/Resolvers/ListInputValueResolver.cs rename to src/graphql-aspnet/Execution/Resolvers/ListInputValueResolver.cs diff --git a/src/graphql-aspnet/Internal/Resolvers/ObjectMethodGraphFieldResolver.cs b/src/graphql-aspnet/Execution/Resolvers/ObjectMethodGraphFieldResolver.cs similarity index 100% rename from src/graphql-aspnet/Internal/Resolvers/ObjectMethodGraphFieldResolver.cs rename to src/graphql-aspnet/Execution/Resolvers/ObjectMethodGraphFieldResolver.cs diff --git a/src/graphql-aspnet/Internal/Resolvers/ObjectPropertyGraphFieldResolver.cs b/src/graphql-aspnet/Execution/Resolvers/ObjectPropertyGraphFieldResolver.cs similarity index 100% rename from src/graphql-aspnet/Internal/Resolvers/ObjectPropertyGraphFieldResolver.cs rename to src/graphql-aspnet/Execution/Resolvers/ObjectPropertyGraphFieldResolver.cs diff --git a/src/graphql-aspnet/Internal/Resolvers/ScalarInputValueResolver.cs b/src/graphql-aspnet/Execution/Resolvers/ScalarInputValueResolver.cs similarity index 100% rename from src/graphql-aspnet/Internal/Resolvers/ScalarInputValueResolver.cs rename to src/graphql-aspnet/Execution/Resolvers/ScalarInputValueResolver.cs diff --git a/src/graphql-aspnet/Execution/RulesEngine/RuleSets/FieldResolution/FieldCompletion/GraphDataItem_ResolveFieldStatus.cs b/src/graphql-aspnet/Execution/RulesEngine/RuleSets/FieldResolution/FieldCompletion/GraphDataItem_ResolveFieldStatus.cs index 9c7411a6a..d9194c806 100644 --- a/src/graphql-aspnet/Execution/RulesEngine/RuleSets/FieldResolution/FieldCompletion/GraphDataItem_ResolveFieldStatus.cs +++ b/src/graphql-aspnet/Execution/RulesEngine/RuleSets/FieldResolution/FieldCompletion/GraphDataItem_ResolveFieldStatus.cs @@ -12,6 +12,7 @@ namespace GraphQL.AspNet.Execution.RulesEngine.RuleSets.FieldResolution.FieldCom using GraphQL.AspNet.Execution.Contexts; using GraphQL.AspNet.Execution.FieldResolution; using GraphQL.AspNet.Execution.RulesEngine.RuleSets.FieldResolution.Common; + using GraphQL.AspNet.Schemas.TypeSystem; /// /// Updates the status of the data item on the context based on its current state. @@ -32,10 +33,18 @@ public override bool Execute(FieldValidationContext context) if (context.DataItem.Status == FieldDataItemResolutionStatus.ResultAssigned) { // if a data value was set ensure any potnetial children are processed - if (context.DataItem.ResultData == null || context.DataItem.FieldContext.Field.IsLeaf) + if (context.DataItem.ResultData == null) + { context.DataItem.Complete(); + } else - context.DataItem.RequireChildResolution(); + { + var graphType = context.Schema.KnownTypes.FindGraphType(context.Field.TypeExpression.TypeName); + if (graphType != null && graphType.Kind.IsLeafKind()) + context.DataItem.Complete(); + else + context.DataItem.RequireChildResolution(); + } } else { diff --git a/src/graphql-aspnet/GraphQLProviders.cs b/src/graphql-aspnet/GraphQLProviders.cs index f40e3f761..e4bcf853b 100644 --- a/src/graphql-aspnet/GraphQLProviders.cs +++ b/src/graphql-aspnet/GraphQLProviders.cs @@ -9,7 +9,13 @@ namespace GraphQL.AspNet { + using System; + using System.Reflection; + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Common.Extensions; + using GraphQL.AspNet.Common.Generics; using GraphQL.AspNet.Engine; + using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Interfaces.Engine; using GraphQL.AspNet.Interfaces.Schema; @@ -17,27 +23,33 @@ namespace GraphQL.AspNet /// A global set of providers used throughout GraphQL.AspNet. These objects are static, unchanged and expected to /// not change at runtime. Do not alter the contents of the static properties after calling .AddGraphQL(). /// - public static class GraphQLProviders + internal static class GraphQLProviders { /// - /// Gets or sets the globally available template provider used by this graphql server. This object manages the schema agnostic collection - /// of meta data for all .NET types being used as a graph type in a schema; be that controllers, interfaces, unions model/data POCOs. + /// attempts to instnatiate the provided type as a union proxy. /// - /// The global template provider. - public static IGraphTypeTemplateProvider TemplateProvider { get; set; } = new DefaultTypeTemplateProvider(); + /// Type of the proxy to create. + /// IGraphUnionProxy. + public static IGraphUnionProxy CreateUnionProxyFromType(Type proxyType) + { + if (proxyType == null) + return null; - /// - /// Gets or sets the globally available provider for managing scalars. This object manages all known scalars - /// across all schemas registered to this application domain. - /// - /// The global scalar provider. - public static IScalarGraphTypeProvider ScalarProvider { get; set; } = new DefaultScalarGraphTypeProvider(); + IGraphUnionProxy proxy = null; + if (Validation.IsCastable(proxyType)) + { + var paramlessConstructor = proxyType.GetConstructor(BindingFlags.Instance | BindingFlags.Public, null, Type.EmptyTypes, null); + if (paramlessConstructor == null) + { + throw new GraphTypeDeclarationException( + $"The union proxy type '{proxyType.FriendlyName()}' could not be instantiated. " + + "All union proxy types must declare a parameterless constructor."); + } - /// - /// Gets or sets an abstract factory that generates "type makers" that can create a new instance of - /// any from a template for use in a schema. - /// - /// The graph type maker provider. - public static IGraphTypeMakerProvider GraphTypeMakerProvider { get; set; } = new DefaultGraphTypeMakerProvider(); + proxy = InstanceFactory.CreateInstance(proxyType) as IGraphUnionProxy; + } + + return proxy; + } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Configuration/ISchemaConfigurationExtension.cs b/src/graphql-aspnet/Interfaces/Configuration/ISchemaExtension.cs similarity index 72% rename from src/graphql-aspnet/Interfaces/Configuration/ISchemaConfigurationExtension.cs rename to src/graphql-aspnet/Interfaces/Configuration/ISchemaExtension.cs index 1f26b78c5..eaf57ac96 100644 --- a/src/graphql-aspnet/Interfaces/Configuration/ISchemaConfigurationExtension.cs +++ b/src/graphql-aspnet/Interfaces/Configuration/ISchemaExtension.cs @@ -6,20 +6,21 @@ // -- // License: MIT // ************************************************************* + namespace GraphQL.AspNet.Interfaces.Configuration { using GraphQL.AspNet.Interfaces.Schema; /// - /// An object that needs to apply some configuration or setup to the schema + /// An object that needs to extend or apply some changes to the schema /// before its considered "complete" and ready to serve. /// - public interface ISchemaConfigurationExtension + public interface ISchemaExtension { /// /// Instructs this configuration mechanism to apply itself to the supplied schema. /// - /// The schema to inspect. - void Configure(ISchema schema); + /// The schema to extend. + void Extend(ISchema schema); } } \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Engine/IGraphQLSchemaFactory{TSchema}.cs b/src/graphql-aspnet/Interfaces/Engine/IGraphQLSchemaFactory{TSchema}.cs new file mode 100644 index 000000000..cba60b70e --- /dev/null +++ b/src/graphql-aspnet/Interfaces/Engine/IGraphQLSchemaFactory{TSchema}.cs @@ -0,0 +1,46 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Interfaces.Engine +{ + using System.Collections.Generic; + using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Interfaces.Configuration; + using GraphQL.AspNet.Interfaces.Configuration.Templates; + using GraphQL.AspNet.Interfaces.Schema; + using Microsoft.Extensions.DependencyInjection; + + /// + /// A factory that, for the given schema type, can generate a fully qualified and usable + /// schema instance. + /// + /// The type of the schema this factory will generate. + public interface IGraphQLSchemaFactory + where TSchema : class, ISchema + { + /// + /// Creates a new, fully populated instance of the schema + /// + /// The service scope used to generate service + /// instances when needed during schema generation. + /// The configuration options + /// that will govern how the schema instantiated. + /// The explicit types register + /// on the schema. + /// The runtime field and type definitions (i.e. minimal api) to add to the schema. + /// The schema extensions to apply to the schema. + /// The completed schema instance. + TSchema CreateInstance( + IServiceScope serviceScope, + ISchemaConfiguration configuration, + IEnumerable typesToRegister = null, + IEnumerable runtimeItemDefinitions = null, + IEnumerable schemaExtensions = null); + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Engine/IGraphQLTypeMakerFactory.cs b/src/graphql-aspnet/Interfaces/Engine/IGraphQLTypeMakerFactory.cs new file mode 100644 index 000000000..fa5a2f739 --- /dev/null +++ b/src/graphql-aspnet/Interfaces/Engine/IGraphQLTypeMakerFactory.cs @@ -0,0 +1,73 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Interfaces.Engine +{ + using System; + using GraphQL.AspNet.Interfaces.Internal; + using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Schemas.TypeSystem; + + /// + /// A factory used during schema generation to create templates and makers for creating + /// instances used to populate a schema. + /// + public interface IGraphQLTypeMakerFactory + { + /// + /// Initializes the maker for the given schema instance providing necessary contextual information + /// for any makers created by this factory. Not all implementers may use the provided schema. + /// + /// The schema instance to initialize for. + void Initialize(ISchema schemaInstance); + + /// + /// Creates a new template from the given type. This template is consumed during type generation. + /// + /// Type of the object to templatize. + /// The typekind of template to be created. If the kind can be + /// determined from the alone, this value is ignored. Largely used to seperate + /// an OBJECT template from an INPUT_OBJECT template for the same .NET type. + /// IGraphTypeTemplate. + IGraphTypeTemplate MakeTemplate(Type objectType, TypeKind? kind = null); + + /// + /// Parses the provided type, extracting the metadata used in type generation for the object graph. + /// + /// The type of the object to parse. + /// The graph to create a template for. If not supplied the template provider + /// will attempt to assign the best graph type possible. + /// IGraphTypeTemplate. + IGraphTypeMaker CreateTypeMaker(Type objectType, TypeKind? kind = null); + + /// + /// Creates a maker that can generate valid graph fields + /// + /// IGraphFieldMaker. + IGraphFieldMaker CreateFieldMaker(); + + /// + /// Creates a maker that can generate arguments for fields or directives. + /// + /// IGraphArgumentMaker. + IGraphArgumentMaker CreateArgumentMaker(); + + /// + /// Creates a maker that can generate special union graph types. + /// + /// IUnionGraphTypeMaker. + IUnionGraphTypeMaker CreateUnionMaker(); + + /// + /// Gets the schema this factory works against. + /// + /// The schema. + ISchema Schema { get; } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Engine/IGraphQLTypeMakerFactory{TSchema}.cs b/src/graphql-aspnet/Interfaces/Engine/IGraphQLTypeMakerFactory{TSchema}.cs new file mode 100644 index 000000000..f0085f553 --- /dev/null +++ b/src/graphql-aspnet/Interfaces/Engine/IGraphQLTypeMakerFactory{TSchema}.cs @@ -0,0 +1,23 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Interfaces.Engine +{ + using GraphQL.AspNet.Interfaces.Schema; + + /// + /// A factory used during schema generation to create templates and makers for creating + /// instances used to populate a schema. + /// + /// The type of the schema this maker factory is registered to . + public interface IGraphQLTypeMakerFactory : IGraphQLTypeMakerFactory + where TSchema : class, ISchema + { + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Engine/IGraphTypeMaker.cs b/src/graphql-aspnet/Interfaces/Engine/IGraphTypeMaker.cs index 41b2127ca..1651da336 100644 --- a/src/graphql-aspnet/Interfaces/Engine/IGraphTypeMaker.cs +++ b/src/graphql-aspnet/Interfaces/Engine/IGraphTypeMaker.cs @@ -11,6 +11,7 @@ namespace GraphQL.AspNet.Interfaces.Engine { using System; using GraphQL.AspNet.Engine.TypeMakers; + using GraphQL.AspNet.Interfaces.Internal; /// /// An object that can create a specific graph type from its associated concrete type according to a set of rules @@ -20,10 +21,11 @@ public interface IGraphTypeMaker { /// /// Inspects the given type and, in accordance with the rules of this maker, will - /// generate a complete set of necessary graph types required to support it. + /// generate a complete a graph type and a complete set of dependencies required to support it. /// - /// The concrete type to incorporate into the schema. + /// The graph type template to use when creating + /// a new graph type. /// GraphTypeCreationResult. - GraphTypeCreationResult CreateGraphType(Type concreteType); + GraphTypeCreationResult CreateGraphType(IGraphTypeTemplate typeTemplate); } } \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Engine/IGraphTypeMakerProvider.cs b/src/graphql-aspnet/Interfaces/Engine/IGraphTypeMakerProvider.cs deleted file mode 100644 index 6887c37eb..000000000 --- a/src/graphql-aspnet/Interfaces/Engine/IGraphTypeMakerProvider.cs +++ /dev/null @@ -1,51 +0,0 @@ -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - -namespace GraphQL.AspNet.Interfaces.Engine -{ - using System; - using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Schemas.TypeSystem; - - /// - /// A abstract factory interface for creating type generator for the various graph type creation operations. - /// - public interface IGraphTypeMakerProvider - { - /// - /// Creates an appropriate graph type maker for the given concrete type. - /// - /// The schema for which the maker should generate graph types for. - /// The kind of graph type to create. If null, the factory will attempt to deteremine the - /// most correct maker to use. - /// IGraphTypeMaker. - IGraphTypeMaker CreateTypeMaker(ISchema schema, TypeKind kind); - - /// - /// Creates a "maker" that can generate graph fields. - /// - /// The schema to which the created fields should belong. - /// IGraphFieldMaker. - IGraphFieldMaker CreateFieldMaker(ISchema schema); - - /// - /// Creates a "maker" that can generate unions for the target schema. - /// - /// The schema to generate unions for. - /// IUnionGraphTypeMaker. - IUnionGraphTypeMaker CreateUnionMaker(ISchema schema); - - /// - /// Attempts to create a union proxy from the given proxy type definition. - /// - /// The type definition of the union proxy to create. - /// IGraphUnionProxy. - IGraphUnionProxy CreateUnionProxyFromType(Type proxyType); - } -} \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Engine/IGraphTypeTemplateProvider.cs b/src/graphql-aspnet/Interfaces/Engine/IGraphTypeTemplateProvider.cs deleted file mode 100644 index 5589229eb..000000000 --- a/src/graphql-aspnet/Interfaces/Engine/IGraphTypeTemplateProvider.cs +++ /dev/null @@ -1,59 +0,0 @@ -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - -namespace GraphQL.AspNet.Interfaces.Engine -{ - using System; - using GraphQL.AspNet.Interfaces.Configuration.Templates; - using GraphQL.AspNet.Interfaces.Internal; - using GraphQL.AspNet.Schemas.TypeSystem; - - /// - /// An interface describing the templating classes used by a schema, at runtime, to parse C# types and build valid graph types. - /// This object is used as a singleton instance for this graphql server and any object implementing this interface - /// should be designed in a thread-safe, singleton fashion. Only one instance of this provider exists for the application instance. - /// - public interface IGraphTypeTemplateProvider - { - /// - /// Removes all cached templates. - /// - void Clear(); - - /// - /// Parses the provided type, extracting the metadata to used in type generation for the object graph. - /// - /// The type of the object to parse. - /// The graph to create a template for. If not supplied the template provider - /// will attempt to assign the best graph type possible. - /// IGraphItemTemplate. - ISchemaItemTemplate ParseType(TypeKind? kind = null); - - /// - /// Parses the provided type, extracting the metadata used in type generation for the object graph. - /// - /// The type of the object to parse. - /// The graph to create a template for. If not supplied the template provider - /// will attempt to assign the best graph type possible. - /// IGraphTypeTemplate. - IGraphTypeTemplate ParseType(Type objectType, TypeKind? kind = null); - - /// - /// Gets the count of registered objects. - /// - /// The count. - int Count { get; } - - /// - /// Gets or sets a value indicating whether templates, once parsed, are retained. - /// - /// true if templates are cached after the first creation; otherwise, false. - bool CacheTemplates { get; set; } - } -} \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Engine/IScalarGraphTypeProvider.cs b/src/graphql-aspnet/Interfaces/Engine/IScalarGraphTypeProvider.cs deleted file mode 100644 index c4dd8d435..000000000 --- a/src/graphql-aspnet/Interfaces/Engine/IScalarGraphTypeProvider.cs +++ /dev/null @@ -1,113 +0,0 @@ -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - -namespace GraphQL.AspNet.Interfaces.Engine -{ - using System; - using System.Collections.Generic; - using GraphQL.AspNet.Interfaces.Schema; - - /// - /// An interface describing the scalar collection used by a schema, at runtime. Scalars are a - /// fundimental unit of graphql and must be explicitly defined. - /// - /// - /// The object implementing this - /// provider should be designed in a thread-safe, singleton fashion. Only one - /// instance of this provider exists for the application instance. - /// - public interface IScalarGraphTypeProvider - { - /// - /// Determines whether the supplied type is considered a leaf type in the graph system - /// (i.e. is the type a scalar or an enumeration). - /// - /// The type to check. - /// true if the specified type is a leaf type; otherwise, false. - bool IsLeaf(Type type); - - /// - /// Converts the given type to its formal reference type removing any - /// nullability modifications that may be applied (e.g. converts int? to int). - /// If the supplied type is already a a formal reference or if it is not a valid scalar type - /// it is returned unchanged. - /// - /// The type to check. - /// The supplied type or the formal scalar type representation if the supplied type - /// is a scalar. - Type EnsureBuiltInTypeReference(Type type); - - /// - /// Determines whether the specified concrete type is a known scalar. - /// - /// Type of the concrete. - /// true if the specified concrete type is a scalar; otherwise, false. - bool IsScalar(Type concreteType); - - /// - /// Determines whether the specified name represents a known scalar. - /// - /// Name of the scalar. This value is case-sensitive. - /// true if the specified name is a scalar; otherwise, false. - bool IsScalar(string scalarName); - - /// - /// Retrieves the mapped concrete type assigned to the given scalar name or null if no - /// scalar is registered. - /// - /// - /// This method converts a scalar name to its primary represented type. (e.g. "Int" => int). - /// - /// Name of the scalar. - /// The system type representing the scalar. - Type RetrieveConcreteType(string scalarName); - - /// - /// Retrieves the name of the scalar registered for the given concrete type. - /// - /// - /// This method converts a type representation to the scalar's common name. (e.g. int => "Int"). - /// - /// The concrete type which is registered as a known scalars. - /// System.String. - string RetrieveScalarName(Type concreteType); - - /// - /// Creates a new instance of the scalar by its defined graph type name or null if no - /// scalar is registered. - /// - /// The common name of the scalar as it exists - /// in a schema. - /// IScalarType. - IScalarGraphType CreateScalar(string scalarName); - - /// - /// Creates a new instance of the scalar by an assigned concrete type or null if no - /// scalar is registered. - /// - /// The concrete type representing the scalar (e.g. int, float, string etc.). - /// IScalarType. - IScalarGraphType CreateScalar(Type concreteType); - - /// - /// Registers the custom scalar type as a pre-parsed template to the provider. This type - /// must implement . - /// - /// The graph type definition of the scalar to register. - /// This type must implement . - void RegisterCustomScalar(Type scalarType); - - /// - /// Gets a list of all registered scalar instance types (i.e. the types that - /// implement ). - /// - /// An enumeration of all registered scalar instance types. - IEnumerable ScalarInstanceTypes { get; } - } -} \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Internal/IScalarGraphTypeTemplate.cs b/src/graphql-aspnet/Interfaces/Internal/IScalarGraphTypeTemplate.cs new file mode 100644 index 000000000..aee5f6ff1 --- /dev/null +++ b/src/graphql-aspnet/Interfaces/Internal/IScalarGraphTypeTemplate.cs @@ -0,0 +1,26 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Interfaces.Internal +{ + using System; + using GraphQL.AspNet.Interfaces.Schema; + + /// + /// A template interface representing an SCALAR graph type. + /// + public interface IScalarGraphTypeTemplate : IGraphTypeTemplate + { + /// + /// Gets the type declared as the scalar; the type that implements . + /// + /// The type of the scalar. + Type ScalarType { get; } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Internal/IUnionGraphTypeTemplate.cs b/src/graphql-aspnet/Interfaces/Internal/IUnionGraphTypeTemplate.cs new file mode 100644 index 000000000..8fd0f8296 --- /dev/null +++ b/src/graphql-aspnet/Interfaces/Internal/IUnionGraphTypeTemplate.cs @@ -0,0 +1,26 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Interfaces.Internal +{ + using System; + using GraphQL.AspNet.Interfaces.Schema; + + /// + /// A template interface representing a UNION graph type. + /// + public interface IUnionGraphTypeTemplate : IGraphTypeTemplate + { + /// + /// Gets the type declared as the union proxy; the type that implements . + /// + /// The type of the union proxy. + Type ProxyType { get; } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Schema/IGraphField.cs b/src/graphql-aspnet/Interfaces/Schema/IGraphField.cs index 735ded683..c5ae023f0 100644 --- a/src/graphql-aspnet/Interfaces/Schema/IGraphField.cs +++ b/src/graphql-aspnet/Interfaces/Schema/IGraphField.cs @@ -42,13 +42,6 @@ public interface IGraphField : IDeprecatable, IGraphArgumentContainer, ISecurabl /// IGraphField. IGraphField Clone(IGraphType parent); - /// - /// Gets a value indicating whether this instance is a leaf field; one capable of generating - /// a real data item vs. generating data to be used in down stream projections. - /// - /// true if this instance is a leaf field; otherwise, false. - bool IsLeaf { get; } - /// /// Gets an object that will perform some operation against an execution /// context to fulfill the requirements of this resolvable entity. diff --git a/src/graphql-aspnet/Interfaces/Schema/IScalarGraphType.cs b/src/graphql-aspnet/Interfaces/Schema/IScalarGraphType.cs index 617f75516..6561b235d 100644 --- a/src/graphql-aspnet/Interfaces/Schema/IScalarGraphType.cs +++ b/src/graphql-aspnet/Interfaces/Schema/IScalarGraphType.cs @@ -49,6 +49,17 @@ public interface IScalarGraphType : IGraphType, ITypedSchemaItem /// The specified by URL. string SpecifiedByUrl { get; set; } + /// + /// Clones this scalar instance to an exact copy with a new type name. This new type name. + /// + /// The new name to assign to the scalar instance. + /// + /// This method is used during schema generation to generate a graph type named accoridng to the + /// schema's naming rules. + /// + /// IScalarGraphType. + IScalarGraphType Clone(string newName); + /// /// Serializes the scalar from its object representation to a /// value that can be used in JSON serialziation. For most scalars this is diff --git a/src/graphql-aspnet/Interfaces/Schema/ISchemaTypeCollection.cs b/src/graphql-aspnet/Interfaces/Schema/ISchemaTypeCollection.cs index eb4d476a0..fdf2e8f4c 100644 --- a/src/graphql-aspnet/Interfaces/Schema/ISchemaTypeCollection.cs +++ b/src/graphql-aspnet/Interfaces/Schema/ISchemaTypeCollection.cs @@ -57,7 +57,8 @@ public interface ISchemaTypeCollection : IEnumerable /// if no is found. /// /// The concrete type to search for. - /// The graph type to search for an association of. + /// An optional kind of graph type to search for. Only used in a tie breaker scenario + /// such as if a concrete type is registered as both an OBJECT and INPUT_OBJECT. /// IGraphType. IGraphType FindGraphType(Type concreteType, TypeKind kind); diff --git a/src/graphql-aspnet/Internal/TypeTemplates/GraphArgumentTemplate.cs b/src/graphql-aspnet/Internal/TypeTemplates/GraphArgumentTemplate.cs index fcb446f4c..1bd775e7e 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/GraphArgumentTemplate.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/GraphArgumentTemplate.cs @@ -122,7 +122,7 @@ public virtual void Parse() // set appropriate meta data about this parameter for inclusion in the type system this.TypeExpression = GraphTypeExpression.FromType(this.DeclaredArgumentType, this.DeclaredTypeWrappers); - this.TypeExpression = this.TypeExpression.CloneTo(GraphTypeNames.ParseName(this.ObjectType, TypeKind.INPUT_OBJECT)); + this.TypeExpression = this.TypeExpression.CloneTo("Type"); // when this argument accepts the same data type as the data returned by its owners target source type // i.e. if the source data supplied to the field for resolution is the same as this argument @@ -229,7 +229,7 @@ public void ValidateOrThrow() .FromType(this.DeclaredArgumentType) .CloneTo(GraphTypeNames.ParseName(this.ObjectType, TypeKind.INPUT_OBJECT)); - if (!GraphTypeExpression.AreTypesCompatiable(actualTypeExpression, this.TypeExpression)) + if (!GraphTypeExpression.AreTypesCompatiable(actualTypeExpression, this.TypeExpression, false)) { throw new GraphTypeDeclarationException( $"The item '{this.Parent.InternalFullName}' declares an argument '{this.Name}' that " + diff --git a/src/graphql-aspnet/Internal/TypeTemplates/GraphFieldTemplateBase.cs b/src/graphql-aspnet/Internal/TypeTemplates/GraphFieldTemplateBase.cs index 07410a6c1..ef82500e5 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/GraphFieldTemplateBase.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/GraphFieldTemplateBase.cs @@ -18,6 +18,7 @@ namespace GraphQL.AspNet.Internal.TypeTemplates using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Common; using GraphQL.AspNet.Common.Extensions; + using GraphQL.AspNet.Common.Generics; using GraphQL.AspNet.Execution; using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Interfaces.Controllers; @@ -85,7 +86,7 @@ protected override void ParseTemplateDefinition() var objectType = GraphValidation.EliminateWrappersFromCoreType(this.DeclaredReturnType); var typeExpression = GraphTypeExpression.FromType(this.DeclaredReturnType, this.DeclaredTypeWrappers); - typeExpression = typeExpression.CloneTo(GraphTypeNames.ParseName(objectType, this.Parent.Kind)); + typeExpression = typeExpression.CloneTo("Type"); // ------------------------------------ // Gather Possible Types and/or union definition @@ -161,11 +162,7 @@ protected override void ParseTemplateDefinition() } this.ObjectType = objectType; - - if (this.UnionProxy != null) - this.TypeExpression = typeExpression.CloneTo(this.UnionProxy.Name); - else - this.TypeExpression = typeExpression; + this.TypeExpression = typeExpression; // ------------------------------------ // Async Requirements @@ -242,7 +239,14 @@ public override void ValidateOrThrow() { if (enforceUnionRules) { - if (GraphQLProviders.ScalarProvider.IsScalar(type)) + if (type.IsEnum) + { + throw new GraphTypeDeclarationException( + $"The field '{this.InternalFullName}' declares a union with a possible type of '{type.FriendlyName()}' " + + "but that type is an enum. Only concrete, non-abstract classes may be used. Value types, such as structs or enumerations, are not allowed."); + } + + if (GraphValidation.MustBeLeafType(type)) { throw new GraphTypeDeclarationException( $"The field '{this.InternalFullName}' declares union with a possible type of '{type.FriendlyName()}' " + @@ -255,20 +259,6 @@ public override void ValidateOrThrow() $"The field '{this.InternalFullName}' declares union with a possible type of '{type.FriendlyName()}' " + "but that type is an interface. Interfaces cannot be included in a field's possible type collection, only object types can."); } - - if (type.IsEnum) - { - throw new GraphTypeDeclarationException( - $"The field '{this.InternalFullName}' declares a union with a possible type of '{type.FriendlyName()}' " + - "but that type is an enum. Only concrete, non-abstract classes may be used. Value types, such as structs or enumerations, are not allowed."); - } - - if (!type.IsClass) - { - throw new GraphTypeDeclarationException( - $"The field '{this.InternalFullName}' returns an interface named '{this.ObjectType.FriendlyName()}' and declares a possible type of '{type.FriendlyName()}' " + - "but that type is not a valid class. Only concrete, non-abstract classes may be used. Value types, such as structs or enumerations, are also not allowed."); - } } foreach (var invalidFieldType in Constants.InvalidFieldTemplateTypes) @@ -421,7 +411,7 @@ private void BuildUnionProxyInstance() { var proxyType = fieldAttribute.Types.FirstOrDefault(); if (proxyType != null) - proxy = GraphQLProviders.GraphTypeMakerProvider.CreateUnionProxyFromType(proxyType); + proxy = GraphQLProviders.CreateUnionProxyFromType(proxyType); } // when no proxy type is declared attempt to construct the proxy from types supplied diff --git a/src/graphql-aspnet/Internal/TypeTemplates/GraphTypeExtensionFieldTemplate.cs b/src/graphql-aspnet/Internal/TypeTemplates/GraphTypeExtensionFieldTemplate.cs index 7f2e727ae..116a51989 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/GraphTypeExtensionFieldTemplate.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/GraphTypeExtensionFieldTemplate.cs @@ -102,11 +102,11 @@ public override void ValidateOrThrow() "All methods wishing to be treated as type extensions must define one instance of this attribute to properly configure the runtime."); } - if (GraphQLProviders.ScalarProvider.IsLeaf(this.SourceObjectType)) + if (!this.SourceObjectType.IsClass && !this.SourceObjectType.IsStruct() && !this.SourceObjectType.IsInterface) { throw new GraphTypeDeclarationException( - $"The type extension '{this.InternalFullName}' is attempting to extend '{this.SourceObjectType.FriendlyName()}' which is a leaf type ({nameof(TypeKind.SCALAR)}, {nameof(TypeKind.ENUM)}). " + - "Leaf types cannot be extended."); + $"The type extension '{this.InternalFullName}' is attempting to extend '{this.SourceObjectType.FriendlyName()}'. " + + "Only classes, structs and interfaces can be extended."); } base.ValidateOrThrow(); diff --git a/src/graphql-aspnet/Internal/TypeTemplates/InputObjectGraphTypeTemplate.cs b/src/graphql-aspnet/Internal/TypeTemplates/InputObjectGraphTypeTemplate.cs index e4c602f58..d142f5cc8 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/InputObjectGraphTypeTemplate.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/InputObjectGraphTypeTemplate.cs @@ -52,9 +52,9 @@ public InputObjectGraphTypeTemplate(Type objectType) { rejectionReason = $"The type '{objectType.FriendlyName()}' is an enumeration and cannot be parsed as an {nameof(TypeKind.INPUT_OBJECT)} graph type. Use an {typeof(IEnumGraphType).FriendlyName()} instead."; } - else if (GraphQLProviders.ScalarProvider.IsScalar(objectType)) + else if (objectType.IsPrimitive) { - rejectionReason = $"The type '{objectType.FriendlyName()}' is a registered {nameof(TypeKind.SCALAR)} and cannot be parsed as an {nameof(TypeKind.INPUT_OBJECT)} graph type. Try using the scalar definition instead."; + rejectionReason = $"The type '{objectType.FriendlyName()}' is a primative data type and cannot be parsed as an {nameof(TypeKind.INPUT_OBJECT)} graph type."; } else if (objectType == typeof(string)) { diff --git a/src/graphql-aspnet/Internal/TypeTemplates/MethodGraphFieldTemplateBase.cs b/src/graphql-aspnet/Internal/TypeTemplates/MethodGraphFieldTemplateBase.cs index 3a54026ec..9555e8120 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/MethodGraphFieldTemplateBase.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/MethodGraphFieldTemplateBase.cs @@ -65,7 +65,7 @@ protected override void ParseTemplateDefinition() // parse all input parameters from the method signature foreach (var parameter in this.Method.GetParameters()) { - var argTemplate = this.CreateInputArgument(parameter); + var argTemplate = this.CreateArgument(parameter); argTemplate.Parse(); _arguments.Add(argTemplate); } @@ -82,7 +82,7 @@ protected override void ParseTemplateDefinition() /// /// The parameter information. /// IGraphFieldArgumentTemplate. - protected virtual GraphArgumentTemplate CreateInputArgument(ParameterInfo paramInfo) + protected virtual GraphArgumentTemplate CreateArgument(ParameterInfo paramInfo) { return new GraphArgumentTemplate(this, paramInfo); } diff --git a/src/graphql-aspnet/Internal/TypeTemplates/NonLeafGraphTypeTemplateBase.cs b/src/graphql-aspnet/Internal/TypeTemplates/NonLeafGraphTypeTemplateBase.cs index d7e87bcce..09960f193 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/NonLeafGraphTypeTemplateBase.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/NonLeafGraphTypeTemplateBase.cs @@ -65,9 +65,9 @@ internal NonLeafGraphTypeTemplateBase(Type objectType) { rejectionReason = $"The type '{objectType.FriendlyName()}' is an enumeration and cannot be parsed as an {nameof(TypeKind.OBJECT)} graph type. Use an {typeof(IEnumGraphType).FriendlyName()} instead."; } - else if (GraphQLProviders.ScalarProvider.IsScalar(objectType)) + else if (objectType.IsPrimitive) { - rejectionReason = $"The type '{objectType.FriendlyName()}' is a registered {nameof(TypeKind.SCALAR)} and cannot be parsed as an {nameof(TypeKind.OBJECT)} graph type. Try using the scalar definition instead."; + rejectionReason = $"The type '{objectType.FriendlyName()}' is a primative data type and cannot be parsed as an {nameof(TypeKind.OBJECT)} graph type."; } else if (objectType == typeof(string)) { diff --git a/src/graphql-aspnet/Internal/TypeTemplates/RuntimeGraphControllerTemplate.cs b/src/graphql-aspnet/Internal/TypeTemplates/RuntimeGraphControllerTemplate.cs index 91f85b2a3..7205863da 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/RuntimeGraphControllerTemplate.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/RuntimeGraphControllerTemplate.cs @@ -28,7 +28,7 @@ internal class RuntimeGraphControllerTemplate : GraphControllerTemplate /// /// A single, runtime configured, field definition /// to templatize for a specfic schema. - public RuntimeGraphControllerTemplate(IGraphQLResolvableSchemaItemDefinition fieldDefinition) + public RuntimeGraphControllerTemplate(IGraphQLRuntimeResolvedFieldDefinition fieldDefinition) : base(typeof(RuntimeFieldExecutionController)) { if (fieldDefinition.Resolver?.Method == null) diff --git a/src/graphql-aspnet/Internal/TypeTemplates/ScalarGraphTypeTemplate.cs b/src/graphql-aspnet/Internal/TypeTemplates/ScalarGraphTypeTemplate.cs new file mode 100644 index 000000000..f6bf9a1c4 --- /dev/null +++ b/src/graphql-aspnet/Internal/TypeTemplates/ScalarGraphTypeTemplate.cs @@ -0,0 +1,77 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Internal.TypeTemplates +{ + using System; + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Execution; + using GraphQL.AspNet.Execution.Exceptions; + using GraphQL.AspNet.Interfaces.Internal; + using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Schemas.Structural; + using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Schemas.TypeSystem.Scalars; + using GraphQL.AspNet.Security; + + /// + /// An graph type template describing a SCALAR graph type. + /// + public class ScalarGraphTypeTemplate : GraphTypeTemplateBase, IScalarGraphTypeTemplate + { + private readonly Type _scalarType; + + /// + /// Initializes a new instance of the class. + /// + /// The type to template. + public ScalarGraphTypeTemplate(Type typeToTemplate) + : base(GlobalScalars.FindBuiltInScalarType(typeToTemplate) ?? typeToTemplate) + { + Validation.ThrowIfNull(typeToTemplate, nameof(typeToTemplate)); + _scalarType = GlobalScalars.FindBuiltInScalarType(typeToTemplate) ?? typeToTemplate; + } + + /// + protected override void ParseTemplateDefinition() + { + base.ParseTemplateDefinition(); + + var instance = GlobalScalars.CreateScalarInstance(this.ScalarType); + + if (instance != null) + { + this.Route = new SchemaItemPath(SchemaItemPath.Join(SchemaItemCollections.Types, instance.Name)); + this.ObjectType = instance.ObjectType; + } + } + + /// + public override void ValidateOrThrow() + { + base.ValidateOrThrow(); + GlobalScalars.ValidateScalarTypeOrThrow(this.ScalarType); + } + + /// + public override AppliedSecurityPolicyGroup SecurityPolicies { get; } + + /// + public override TypeKind Kind => TypeKind.SCALAR; + + /// + public override string InternalFullName => _scalarType.Name; + + /// + public override string InternalName => _scalarType.Name; + + /// + public Type ScalarType => _scalarType; + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Internal/TypeTemplates/UnionGraphTypeTemplate.cs b/src/graphql-aspnet/Internal/TypeTemplates/UnionGraphTypeTemplate.cs new file mode 100644 index 000000000..c67bf40be --- /dev/null +++ b/src/graphql-aspnet/Internal/TypeTemplates/UnionGraphTypeTemplate.cs @@ -0,0 +1,98 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Internal.TypeTemplates +{ + using System; + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Common.Generics; + using GraphQL.AspNet.Execution; + using GraphQL.AspNet.Execution.Exceptions; + using GraphQL.AspNet.Interfaces.Internal; + using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Schemas.Structural; + using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Schemas.TypeSystem.Scalars; + using GraphQL.AspNet.Security; + + /// + /// An graph type template describing a SCALAR graph type. + /// + public class UnionGraphTypeTemplate : GraphTypeTemplateBase, IUnionGraphTypeTemplate + { + private readonly Type _proxyType; + + /// + /// Initializes a new instance of the class. + /// + /// The type that implements . + public UnionGraphTypeTemplate(Type proxyType) + : base(proxyType) + { + Validation.ThrowIfNull(proxyType, nameof(proxyType)); + _proxyType = proxyType; + } + + /// + protected override void ParseTemplateDefinition() + { + base.ParseTemplateDefinition(); + + try + { + if (_proxyType != null) + { + var instance = InstanceFactory.CreateInstance(_proxyType) as IGraphUnionProxy; + + if (instance != null) + { + this.Route = new SchemaItemPath(SchemaItemPath.Join(SchemaItemCollections.Types, instance.Name)); + this.ObjectType = null; + } + } + } + catch + { + } + } + + /// + public override void ValidateOrThrow() + { + base.ValidateOrThrow(); + if (_proxyType == null) + { + throw new GraphTypeDeclarationException( + "Unable to create a union graph type template from a null supplied proxy type."); + } + + if (!Validation.IsCastable(_proxyType)) + { + throw new GraphTypeDeclarationException( + $"The type {_proxyType.FriendlyGraphTypeName()} does not implement {nameof(IGraphUnionProxy)}. All " + + $"types being used as a declaration of a union must implement {nameof(IGraphUnionProxy)}."); + } + } + + /// + public override AppliedSecurityPolicyGroup SecurityPolicies { get; } + + /// + public override TypeKind Kind => TypeKind.SCALAR; + + /// + public override string InternalFullName => _proxyType?.Name; + + /// + public override string InternalName => _proxyType?.Name; + + /// + public Type ProxyType => _proxyType; + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Engine/TypeMakers/DependentTypeCollection.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/DependentTypeCollection.cs similarity index 100% rename from src/graphql-aspnet/Engine/TypeMakers/DependentTypeCollection.cs rename to src/graphql-aspnet/Schemas/Generation/TypeMakers/DependentTypeCollection.cs diff --git a/src/graphql-aspnet/Engine/TypeMakers/DirectiveMaker.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/DirectiveMaker.cs similarity index 64% rename from src/graphql-aspnet/Engine/TypeMakers/DirectiveMaker.cs rename to src/graphql-aspnet/Schemas/Generation/TypeMakers/DirectiveMaker.cs index 86981e3e8..f32fc85d7 100644 --- a/src/graphql-aspnet/Engine/TypeMakers/DirectiveMaker.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/DirectiveMaker.cs @@ -7,14 +7,17 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Engine.TypeMakers +namespace GraphQL.AspNet.Schemas.Generation.TypeMakers { using System; using System.Collections.Generic; using GraphQL.AspNet.Common; + using GraphQL.AspNet.Engine.TypeMakers; + using GraphQL.AspNet.Interfaces.Configuration; using GraphQL.AspNet.Interfaces.Engine; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Internal.TypeTemplates; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Security; @@ -23,30 +26,29 @@ namespace GraphQL.AspNet.Engine.TypeMakers /// public class DirectiveMaker : IGraphTypeMaker { - private readonly ISchema _schema; + private readonly ISchemaConfiguration _config; + private readonly IGraphArgumentMaker _argMaker; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// The schema. - public DirectiveMaker(ISchema schema) + /// The configuration used when setting up new directive types. + /// The maker used to generate new arguments on any created directives. + public DirectiveMaker(ISchemaConfiguration config, IGraphArgumentMaker argumentMaker) { - _schema = Validation.ThrowIfNullOrReturn(schema, nameof(schema)); + _config = Validation.ThrowIfNullOrReturn(config, nameof(config)); + _argMaker = Validation.ThrowIfNullOrReturn(argumentMaker, nameof(argumentMaker)); + } - /// - /// Inspects the given type and, in accordance with the rules of this maker, will - /// generate a complete set of necessary graph types required to support it. - /// - /// The concrete type to incorporate into the schema. - /// GraphTypeCreationResult. - public GraphTypeCreationResult CreateGraphType(Type concreteType) + /// + public virtual GraphTypeCreationResult CreateGraphType(IGraphTypeTemplate typeTemplate) { - var formatter = _schema.Configuration.DeclarationOptions.GraphNamingFormatter; - var template = GraphQLProviders.TemplateProvider.ParseType(concreteType) as IGraphDirectiveTemplate; - if (template == null) + if (!(typeTemplate is IGraphDirectiveTemplate template)) return null; + var formatter = _config.DeclarationOptions.GraphNamingFormatter; + var securityGroups = new List(); if (template.SecurityPolicies?.Count > 0) @@ -69,12 +71,11 @@ public GraphTypeCreationResult CreateGraphType(Type concreteType) // all arguments are required to have the same signature via validation // can use any method to fill the arg field list - var argMaker = new GraphArgumentMaker(_schema); foreach (var argTemplate in template.Arguments) { if (argTemplate.ArgumentModifiers.IsPartOfTheSchema()) { - var argumentResult = argMaker.CreateArgument(directive, argTemplate); + var argumentResult = _argMaker.CreateArgument(directive, argTemplate); directive.Arguments.AddArgument(argumentResult.Argument); result.MergeDependents(argumentResult); @@ -82,7 +83,7 @@ public GraphTypeCreationResult CreateGraphType(Type concreteType) } result.GraphType = directive; - result.ConcreteType = concreteType; + result.ConcreteType = template.ObjectType; return result; } } diff --git a/src/graphql-aspnet/Engine/TypeMakers/EnumGraphTypeMaker.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/EnumGraphTypeMaker.cs similarity index 69% rename from src/graphql-aspnet/Engine/TypeMakers/EnumGraphTypeMaker.cs rename to src/graphql-aspnet/Schemas/Generation/TypeMakers/EnumGraphTypeMaker.cs index 3ec4d6de3..2addfd48a 100644 --- a/src/graphql-aspnet/Engine/TypeMakers/EnumGraphTypeMaker.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/EnumGraphTypeMaker.cs @@ -7,15 +7,19 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Engine.TypeMakers +namespace GraphQL.AspNet.Schemas.Generation.TypeMakers { using System; using System.Linq; using GraphQL.AspNet.Common; using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Engine.TypeMakers; + using GraphQL.AspNet.Execution.RulesEngine.RuleSets.DirectiveExecution.DirectiveValidation; + using GraphQL.AspNet.Interfaces.Configuration; using GraphQL.AspNet.Interfaces.Engine; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Internal.TypeTemplates; using GraphQL.AspNet.Schemas.TypeSystem; /// @@ -24,32 +28,31 @@ namespace GraphQL.AspNet.Engine.TypeMakers /// public class EnumGraphTypeMaker : IGraphTypeMaker { - private readonly ISchema _schema; + private readonly ISchemaConfiguration _config; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// The schema this generator should follow. - public EnumGraphTypeMaker(ISchema schema) + /// The schema configuration to use when building the graph type. + public EnumGraphTypeMaker(ISchemaConfiguration config) { - _schema = Validation.ThrowIfNullOrReturn(schema, nameof(schema)); + _config = Validation.ThrowIfNullOrReturn(config, nameof(config)); } /// - public GraphTypeCreationResult CreateGraphType(Type concreteType) + public virtual GraphTypeCreationResult CreateGraphType(IGraphTypeTemplate typeTemplate) { - var template = GraphQLProviders.TemplateProvider.ParseType(concreteType, TypeKind.ENUM) as IEnumGraphTypeTemplate; - if (template == null) + if (!(typeTemplate is IEnumGraphTypeTemplate template)) return null; - var requirements = template.DeclarationRequirements ?? _schema.Configuration.DeclarationOptions.FieldDeclarationRequirements; + var requirements = template.DeclarationRequirements ?? _config.DeclarationOptions.FieldDeclarationRequirements; // enum level directives var enumDirectives = template.CreateAppliedDirectives(); var graphType = new EnumGraphType( - _schema.Configuration.DeclarationOptions.GraphNamingFormatter.FormatGraphTypeName(template.Name), - concreteType, + _config.DeclarationOptions.GraphNamingFormatter.FormatGraphTypeName(template.Name), + template.ObjectType, template.Route, enumDirectives) { @@ -60,7 +63,7 @@ public GraphTypeCreationResult CreateGraphType(Type concreteType) var result = new GraphTypeCreationResult() { GraphType = graphType, - ConcreteType = concreteType, + ConcreteType = template.ObjectType, }; // account for any potential type system directives @@ -75,7 +78,7 @@ public GraphTypeCreationResult CreateGraphType(Type concreteType) var valueOption = new EnumValue( graphType, - _schema.Configuration.DeclarationOptions.GraphNamingFormatter.FormatEnumValueName(value.Name), + _config.DeclarationOptions.GraphNamingFormatter.FormatEnumValueName(value.Name), value.Description, value.Route, value.Value, diff --git a/src/graphql-aspnet/Schemas/Generation/TypeMakers/FieldContainerGraphTypeMakerBase.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/FieldContainerGraphTypeMakerBase.cs new file mode 100644 index 000000000..60af6dd55 --- /dev/null +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/FieldContainerGraphTypeMakerBase.cs @@ -0,0 +1,65 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Schemas.Generation.TypeMakers +{ + using System.Collections.Generic; + using System.Linq; + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Interfaces.Configuration; + using GraphQL.AspNet.Interfaces.Internal; + using GraphQL.AspNet.Internal.TypeTemplates; + + /// + /// A base type maker for those types that generate fields. Used to centralize common code. + /// + public abstract class FieldContainerGraphTypeMakerBase + { + private readonly ISchemaConfiguration _config; + + /// + /// Initializes a new instance of the class. + /// + /// The configuration data to use when generating + /// field items. + public FieldContainerGraphTypeMakerBase(ISchemaConfiguration config) + { + _config = Validation.ThrowIfNullOrReturn(config, nameof(config)); + } + + /// + /// Creates the collection of graph fields that belong to the template. + /// + /// The template to generate fields for. + /// IEnumerable<IGraphField>. + protected virtual IEnumerable GatherFieldTemplates(IGraphTypeFieldTemplateContainer template) + { + // gather the fields to include in the graph type + var requiredDeclarations = template.DeclarationRequirements ?? _config.DeclarationOptions.FieldDeclarationRequirements; + + return template.FieldTemplates.Values.Where(x => + { + if (x.IsExplicitDeclaration) + return true; + + switch (x.FieldSource) + { + case GraphFieldSource.Method: + return requiredDeclarations.AllowImplicitMethods(); + + case GraphFieldSource.Property: + return requiredDeclarations.AllowImplicitProperties(); + } + + return false; + }); + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Engine/TypeMakers/GraphArgumentCreationResult.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphArgumentCreationResult.cs similarity index 100% rename from src/graphql-aspnet/Engine/TypeMakers/GraphArgumentCreationResult.cs rename to src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphArgumentCreationResult.cs diff --git a/src/graphql-aspnet/Engine/TypeMakers/GraphArgumentMaker.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphArgumentMaker.cs similarity index 52% rename from src/graphql-aspnet/Engine/TypeMakers/GraphArgumentMaker.cs rename to src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphArgumentMaker.cs index 564ba372d..a50907e5d 100644 --- a/src/graphql-aspnet/Engine/TypeMakers/GraphArgumentMaker.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphArgumentMaker.cs @@ -7,13 +7,18 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Engine.TypeMakers +namespace GraphQL.AspNet.Schemas.Generation.TypeMakers { using GraphQL.AspNet.Common; + using GraphQL.AspNet.Configuration.Formatting; + using GraphQL.AspNet.Engine.TypeMakers; + using GraphQL.AspNet.Interfaces.Configuration; using GraphQL.AspNet.Interfaces.Engine; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Internal; using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Schemas.TypeSystem.Scalars; /// /// A maker capable of turning a into a usable on a graph field. @@ -21,28 +26,54 @@ namespace GraphQL.AspNet.Engine.TypeMakers public class GraphArgumentMaker : IGraphArgumentMaker { private readonly ISchema _schema; + private readonly ISchemaConfiguration _config; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// The schema. + /// The schema being built. public GraphArgumentMaker(ISchema schema) { _schema = Validation.ThrowIfNullOrReturn(schema, nameof(schema)); + _config = _schema.Configuration; } /// public GraphArgumentCreationResult CreateArgument(ISchemaItem owner, IGraphArgumentTemplate template) { Validation.ThrowIfNull(owner, nameof(owner)); - var formatter = _schema.Configuration.DeclarationOptions.GraphNamingFormatter; + var formatter = _config.DeclarationOptions.GraphNamingFormatter; var directives = template.CreateAppliedDirectives(); + // all arguments are either leafs or input objects + var existingGraphType = _schema.KnownTypes.FindGraphType(template.ObjectType, TypeKind.INPUT_OBJECT); + + string schemaTypeName; + if (existingGraphType != null && existingGraphType.Kind.IsValidInputKind()) + { + // when the type already exists on the target schema + // and is usable as an input type then just use the name + schemaTypeName = existingGraphType.Name; + } + else + { + // guess on what the name of the schema item will be + // this is guaranteed correct for all but scalars + schemaTypeName = GraphTypeNames.ParseName(template.ObjectType, TypeKind.INPUT_OBJECT); + } + + // enforce non-renaming standards in the maker since the + // directly controls the formatter + if (GlobalScalars.CanBeRenamed(schemaTypeName)) + schemaTypeName = formatter.FormatGraphTypeName(schemaTypeName); + + var typeExpression = template.TypeExpression.CloneTo(schemaTypeName); + var argument = new GraphFieldArgument( owner, formatter.FormatFieldName(template.Name), - template.TypeExpression.CloneTo(formatter.FormatGraphTypeName(template.TypeExpression.TypeName)), + typeExpression, template.Route, template.ParameterName, template.InternalFullName, diff --git a/src/graphql-aspnet/Engine/TypeMakers/GraphFieldCreationResult.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphFieldCreationResult.cs similarity index 100% rename from src/graphql-aspnet/Engine/TypeMakers/GraphFieldCreationResult.cs rename to src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphFieldCreationResult.cs diff --git a/src/graphql-aspnet/Engine/TypeMakers/GraphFieldMaker.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphFieldMaker.cs similarity index 65% rename from src/graphql-aspnet/Engine/TypeMakers/GraphFieldMaker.cs rename to src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphFieldMaker.cs index 81eb05a95..15ec5d4d9 100644 --- a/src/graphql-aspnet/Engine/TypeMakers/GraphFieldMaker.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphFieldMaker.cs @@ -7,27 +7,24 @@ // License: MIT // ************************************************************* -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* -namespace GraphQL.AspNet.Engine.TypeMakers +namespace GraphQL.AspNet.Schemas.Generation.TypeMakers { using System; using System.Collections.Generic; + using System.Runtime.CompilerServices; using GraphQL.AspNet.Common; using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Common.Generics; using GraphQL.AspNet.Configuration.Formatting; + using GraphQL.AspNet.Engine.TypeMakers; + using GraphQL.AspNet.Interfaces.Configuration; using GraphQL.AspNet.Interfaces.Engine; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Internal; using GraphQL.AspNet.Internal.TypeTemplates; using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Schemas.TypeSystem.Scalars; using GraphQL.AspNet.Security; /// @@ -35,25 +32,38 @@ namespace GraphQL.AspNet.Engine.TypeMakers /// public class GraphFieldMaker : IGraphFieldMaker { + private readonly ISchema _schema; + private readonly ISchemaConfiguration _config; + private readonly IGraphQLTypeMakerFactory _makerFactory; + /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// The schema. - public GraphFieldMaker(ISchema schema) + /// The schema instance to reference when creating fields. + /// The maker factory to create dependnet makers + /// if and when necessary. + public GraphFieldMaker(ISchema schema, IGraphQLTypeMakerFactory makerFactory) { - this.Schema = Validation.ThrowIfNullOrReturn(schema, nameof(schema)); + _schema = Validation.ThrowIfNullOrReturn(schema, nameof(schema)); + _config = _schema.Configuration; + _makerFactory = Validation.ThrowIfNullOrReturn(makerFactory, nameof(makerFactory)); } /// public virtual GraphFieldCreationResult CreateField(IGraphFieldTemplate template) { - var formatter = this.Schema.Configuration.DeclarationOptions.GraphNamingFormatter; + var formatter = _config.DeclarationOptions.GraphNamingFormatter; var result = new GraphFieldCreationResult(); // if the owner of this field declared top level objects append them to the // field for evaluation var securityGroups = new List(); + if (template.Parent.ObjectType.Name == "ParentWithNullableChildObject") + { + string str = ""; + } + if (template.Parent?.SecurityPolicies?.Count > 0) securityGroups.Add(template.Parent.SecurityPolicies); @@ -66,16 +76,14 @@ public virtual GraphFieldCreationResult CreateField(IGraphFieldTemp field.Complexity = template.Complexity; field.FieldSource = template.FieldSource; - if (template.Arguments != null) + if (template.Arguments != null && template.Arguments.Count > 0) { - var argumentMaker = this.CreateArgumentMaker(); - Validation.ThrowIfNull(argumentMaker, nameof(argumentMaker)); - + var argMaker = _makerFactory.CreateArgumentMaker(); foreach (var argTemplate in template.Arguments) { if (argTemplate.ArgumentModifiers.IsPartOfTheSchema()) { - var argumentResult = argumentMaker.CreateArgument(field, argTemplate); + var argumentResult = argMaker.CreateArgument(field, argTemplate); field.Arguments.AddArgument(argumentResult.Argument); result.MergeDependents(argumentResult); @@ -87,7 +95,7 @@ public virtual GraphFieldCreationResult CreateField(IGraphFieldTemp if (template.UnionProxy != null) { - var unionMaker = GraphQLProviders.GraphTypeMakerProvider.CreateUnionMaker(this.Schema); + var unionMaker = _makerFactory.CreateUnionMaker(); var unionResult = unionMaker.CreateUnionFromProxy(template.UnionProxy); if (unionResult != null) { @@ -100,16 +108,6 @@ public virtual GraphFieldCreationResult CreateField(IGraphFieldTemp return result; } - /// - /// Creates an argument maker that will be used to create all the - /// arguments of a given field. - /// - /// IGraphArgumentMaker. - protected virtual IGraphArgumentMaker CreateArgumentMaker() - { - return new GraphArgumentMaker(this.Schema); - } - /// /// Instantiates the graph field according to the data provided. /// @@ -124,13 +122,53 @@ protected virtual MethodGraphField InstantiateField( { var directives = template.CreateAppliedDirectives(); + // all fields return either an object, interface, union, scalar or enum + IGraphType existingGraphType; + string fallbackTypeName; + if (template.UnionProxy != null) + { + existingGraphType = _schema.KnownTypes.FindGraphType(template.UnionProxy.Name); + fallbackTypeName = template.UnionProxy.Name; + } + else + { + existingGraphType = _schema.KnownTypes.FindGraphType(template.ObjectType, template.OwnerTypeKind); + fallbackTypeName = null; + } + + string schemaTypeName; + + // when the type already exists on the target schema + // and is usable as an input type then just use the name + if (existingGraphType != null && existingGraphType.Kind.IsValidInputKind()) + { + schemaTypeName = existingGraphType.Name; + } + else if (fallbackTypeName != null) + { + schemaTypeName = fallbackTypeName; + } + else + { + // guess on what the name of the schema item will be + // this is guaranteed correct for all but scalars + schemaTypeName = GraphTypeNames.ParseName(template.ObjectType, template.OwnerTypeKind); + } + + // enforce non-renaming standards in the maker since the + // directly controls the formatter + if (GlobalScalars.CanBeRenamed(schemaTypeName)) + schemaTypeName = formatter.FormatGraphTypeName(schemaTypeName); + + var typeExpression = template.TypeExpression.CloneTo(schemaTypeName); + switch (template.FieldSource) { case GraphFieldSource.Method: case GraphFieldSource.Action: return new MethodGraphField( formatter.FormatFieldName(template.Name), - template.TypeExpression.CloneTo(formatter.FormatGraphTypeName(template.TypeExpression.TypeName)), + typeExpression, template.Route, template.DeclaredName, template.ObjectType, @@ -143,7 +181,7 @@ protected virtual MethodGraphField InstantiateField( case GraphFieldSource.Property: return new PropertyGraphField( formatter.FormatFieldName(template.Name), - template.TypeExpression.CloneTo(formatter.FormatGraphTypeName(template.TypeExpression.TypeName)), + typeExpression, template.Route, template.DeclaredName, template.ObjectType, @@ -161,7 +199,7 @@ protected virtual MethodGraphField InstantiateField( /// public GraphFieldCreationResult CreateField(IInputGraphFieldTemplate template) { - var formatter = this.Schema.Configuration.DeclarationOptions.GraphNamingFormatter; + var formatter = _config.DeclarationOptions.GraphNamingFormatter; var defaultInputObject = InstanceFactory.CreateInstance(template.Parent.ObjectType); var propGetters = InstanceFactory.CreatePropertyGetterInvokerCollection(template.Parent.ObjectType); @@ -195,11 +233,5 @@ public GraphFieldCreationResult CreateField(IInputGraphFieldTe result.Field = field; return result; } - - /// - /// Gets the schema this field maker is creating fields for. - /// - /// The schema. - protected ISchema Schema { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Engine/TypeMakers/GraphMakerExtensions.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphMakerExtensions.cs similarity index 100% rename from src/graphql-aspnet/Engine/TypeMakers/GraphMakerExtensions.cs rename to src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphMakerExtensions.cs diff --git a/src/graphql-aspnet/Engine/TypeMakers/GraphTypeCreationResult.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphTypeCreationResult.cs similarity index 100% rename from src/graphql-aspnet/Engine/TypeMakers/GraphTypeCreationResult.cs rename to src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphTypeCreationResult.cs diff --git a/src/graphql-aspnet/Engine/TypeMakers/InputObjectGraphTypeMaker.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/InputObjectGraphTypeMaker.cs similarity index 62% rename from src/graphql-aspnet/Engine/TypeMakers/InputObjectGraphTypeMaker.cs rename to src/graphql-aspnet/Schemas/Generation/TypeMakers/InputObjectGraphTypeMaker.cs index ab36bb9b3..9fef91d19 100644 --- a/src/graphql-aspnet/Engine/TypeMakers/InputObjectGraphTypeMaker.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/InputObjectGraphTypeMaker.cs @@ -7,15 +7,18 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Engine.TypeMakers +namespace GraphQL.AspNet.Schemas.Generation.TypeMakers { using System; using System.Linq; using GraphQL.AspNet.Common; using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Engine.TypeMakers; + using GraphQL.AspNet.Interfaces.Configuration; using GraphQL.AspNet.Interfaces.Engine; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Internal.TypeTemplates; using GraphQL.AspNet.Schemas.TypeSystem; /// @@ -23,25 +26,29 @@ namespace GraphQL.AspNet.Engine.TypeMakers /// public class InputObjectGraphTypeMaker : IGraphTypeMaker { - private readonly ISchema _schema; + private readonly ISchemaConfiguration _config; + private readonly IGraphFieldMaker _fieldMaker; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// The schema defining the graph type creation rules this generator should follow. - public InputObjectGraphTypeMaker(ISchema schema) + /// The configuration to use when constructing the input graph type. + /// The field maker used to create input field instances. + public InputObjectGraphTypeMaker( + ISchemaConfiguration config, + IGraphFieldMaker fieldMaker) { - _schema = Validation.ThrowIfNullOrReturn(schema, nameof(schema)); + _config = Validation.ThrowIfNullOrReturn(config, nameof(config)); + _fieldMaker = Validation.ThrowIfNullOrReturn(fieldMaker, nameof(fieldMaker)); } /// - public virtual GraphTypeCreationResult CreateGraphType(Type concreteType) + public virtual GraphTypeCreationResult CreateGraphType(IGraphTypeTemplate typeTemplate) { - var template = GraphQLProviders.TemplateProvider.ParseType(concreteType, TypeKind.INPUT_OBJECT) as IInputObjectGraphTypeTemplate; - if (template == null) + if (!(typeTemplate is IInputObjectGraphTypeTemplate template)) return null; - var formatter = _schema.Configuration.DeclarationOptions.GraphNamingFormatter; + var formatter = _config.DeclarationOptions.GraphNamingFormatter; var result = new GraphTypeCreationResult(); // gather directives @@ -49,7 +56,7 @@ public virtual GraphTypeCreationResult CreateGraphType(Type concreteType) var inputObjectType = new InputObjectGraphType( formatter.FormatGraphTypeName(template.Name), - concreteType, + template.ObjectType, template.Route, directives) { @@ -62,22 +69,21 @@ public virtual GraphTypeCreationResult CreateGraphType(Type concreteType) // gather the fields to include in the graph type var requiredDeclarations = template.DeclarationRequirements - ?? _schema.Configuration.DeclarationOptions.FieldDeclarationRequirements; + ?? _config.DeclarationOptions.FieldDeclarationRequirements; var fieldTemplates = template.FieldTemplates.Values.Where(x => x.IsExplicitDeclaration || requiredDeclarations.AllowImplicitProperties()); // create the fields for the graph type - var fieldMaker = GraphQLProviders.GraphTypeMakerProvider.CreateFieldMaker(_schema); foreach (var fieldTemplate in fieldTemplates) { - var fieldResult = fieldMaker.CreateField(fieldTemplate); + var fieldResult = _fieldMaker.CreateField(fieldTemplate); inputObjectType.AddField(fieldResult.Field); result.MergeDependents(fieldResult); } result.GraphType = inputObjectType; - result.ConcreteType = concreteType; + result.ConcreteType = template.ObjectType; return result; } } diff --git a/src/graphql-aspnet/Engine/TypeMakers/InterfaceGraphTypeMaker.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/InterfaceGraphTypeMaker.cs similarity index 58% rename from src/graphql-aspnet/Engine/TypeMakers/InterfaceGraphTypeMaker.cs rename to src/graphql-aspnet/Schemas/Generation/TypeMakers/InterfaceGraphTypeMaker.cs index 8ea787bcc..d06c4041f 100644 --- a/src/graphql-aspnet/Engine/TypeMakers/InterfaceGraphTypeMaker.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/InterfaceGraphTypeMaker.cs @@ -7,44 +7,50 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Engine.TypeMakers +namespace GraphQL.AspNet.Schemas.Generation.TypeMakers { using System; using GraphQL.AspNet.Common; + using GraphQL.AspNet.Engine.TypeMakers; + using GraphQL.AspNet.Interfaces.Configuration; using GraphQL.AspNet.Interfaces.Engine; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Internal; + using GraphQL.AspNet.Internal.TypeTemplates; using GraphQL.AspNet.Schemas.TypeSystem; /// /// A "maker" capable of producing a qualified from its related template. /// - public class InterfaceGraphTypeMaker : IGraphTypeMaker + public class InterfaceGraphTypeMaker : FieldContainerGraphTypeMakerBase, IGraphTypeMaker { - private readonly ISchema _schema; + private readonly ISchemaConfiguration _config; + private readonly IGraphFieldMaker _fieldMaker; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// The schema. - public InterfaceGraphTypeMaker(ISchema schema) + /// The configuration data to use when generating any graph types. + /// The field maker to use when generating fields on any + /// created interface types. + public InterfaceGraphTypeMaker( + ISchemaConfiguration config, + IGraphFieldMaker fieldMaker) + : base(config) { - _schema = Validation.ThrowIfNullOrReturn(schema, nameof(schema)); + _config = Validation.ThrowIfNullOrReturn(config, nameof(config)); + _fieldMaker = Validation.ThrowIfNullOrReturn(fieldMaker, nameof(fieldMaker)); } /// - public GraphTypeCreationResult CreateGraphType(Type concreteType) + public virtual GraphTypeCreationResult CreateGraphType(IGraphTypeTemplate typeTemplate) { - if (concreteType == null) - return null; - - var template = GraphQLProviders.TemplateProvider.ParseType(concreteType, TypeKind.INTERFACE) as IInterfaceGraphTypeTemplate; - if (template == null) + if (!(typeTemplate is IInterfaceGraphTypeTemplate template)) return null; var result = new GraphTypeCreationResult(); - var formatter = _schema.Configuration.DeclarationOptions.GraphNamingFormatter; + var formatter = _config.DeclarationOptions.GraphNamingFormatter; var directives = template.CreateAppliedDirectives(); @@ -61,10 +67,9 @@ public GraphTypeCreationResult CreateGraphType(Type concreteType) // account for any potential type system directives result.AddDependentRange(template.RetrieveRequiredTypes()); - var fieldMaker = GraphQLProviders.GraphTypeMakerProvider.CreateFieldMaker(_schema); - foreach (var fieldTemplate in ObjectGraphTypeMaker.GatherFieldTemplates(template, _schema)) + foreach (var fieldTemplate in this.GatherFieldTemplates(template)) { - var fieldResult = fieldMaker.CreateField(fieldTemplate); + var fieldResult = _fieldMaker.CreateField(fieldTemplate); interfaceType.Extend(fieldResult.Field); result.MergeDependents(fieldResult); @@ -77,7 +82,7 @@ public GraphTypeCreationResult CreateGraphType(Type concreteType) } result.GraphType = interfaceType; - result.ConcreteType = concreteType; + result.ConcreteType = template.ObjectType; return result; } } diff --git a/src/graphql-aspnet/Schemas/Generation/TypeMakers/ObjectGraphTypeMaker.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/ObjectGraphTypeMaker.cs new file mode 100644 index 000000000..b4edaf042 --- /dev/null +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/ObjectGraphTypeMaker.cs @@ -0,0 +1,93 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Schemas.Generation.TypeMakers +{ + using System; + using System.Collections.Generic; + using System.Linq; + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Engine.TypeMakers; + using GraphQL.AspNet.Interfaces.Configuration; + using GraphQL.AspNet.Interfaces.Engine; + using GraphQL.AspNet.Interfaces.Internal; + using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Internal; + using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Schemas.TypeSystem; + + /// + /// A "maker" capable of producing a qualified from its related template. + /// + public class ObjectGraphTypeMaker : FieldContainerGraphTypeMakerBase, IGraphTypeMaker + { + private readonly ISchemaConfiguration _config; + private readonly IGraphFieldMaker _fieldMaker; + + /// + /// Initializes a new instance of the class. + /// + /// The schema configuration and setup options to use + /// when building out the graph type. + /// The field maker instnace used to create fields + /// on any created graph types. + public ObjectGraphTypeMaker( + ISchemaConfiguration config, + IGraphFieldMaker fieldMaker) + : base(config) + { + _config = Validation.ThrowIfNullOrReturn(config, nameof(config)); + _fieldMaker = Validation.ThrowIfNullOrReturn(fieldMaker, nameof(fieldMaker)); + } + + /// + public virtual GraphTypeCreationResult CreateGraphType(IGraphTypeTemplate typeTemplate) + { + if (!(typeTemplate is IObjectGraphTypeTemplate template)) + return null; + + var result = new GraphTypeCreationResult(); + + var formatter = _config.DeclarationOptions.GraphNamingFormatter; + var directives = template.CreateAppliedDirectives(); + + var objectType = new ObjectGraphType( + formatter.FormatGraphTypeName(template.Name), + template.ObjectType, + template.Route, + directives) + { + Description = template.Description, + Publish = template.Publish, + }; + + result.GraphType = objectType; + result.ConcreteType = template.ObjectType; + + // account for any potential type system directives + result.AddDependentRange(template.RetrieveRequiredTypes()); + + foreach (var fieldTemplate in this.GatherFieldTemplates(template)) + { + var fieldResult = _fieldMaker.CreateField(fieldTemplate); + objectType.Extend(fieldResult.Field); + result.MergeDependents(fieldResult); + } + + // add in declared interfaces by name + foreach (var iface in template.DeclaredInterfaces) + { + objectType.InterfaceNames.Add(formatter.FormatGraphTypeName(GraphTypeNames.ParseName(iface, TypeKind.INTERFACE))); + } + + return result; + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/Generation/TypeMakers/ScalarGraphTypeMaker.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/ScalarGraphTypeMaker.cs new file mode 100644 index 000000000..94a36150a --- /dev/null +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/ScalarGraphTypeMaker.cs @@ -0,0 +1,66 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Schemas.Generation.TypeMakers +{ + using System; + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Common.Extensions; + using GraphQL.AspNet.Engine.TypeMakers; + using GraphQL.AspNet.Interfaces.Configuration; + using GraphQL.AspNet.Interfaces.Engine; + using GraphQL.AspNet.Interfaces.Internal; + using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Schemas.TypeSystem.Scalars; + + /// + /// A "maker" capable of producing a qualified from its related template. + /// + public class ScalarGraphTypeMaker : IGraphTypeMaker + { + private readonly ISchemaConfiguration _config; + + /// + /// Initializes a new instance of the class. + /// + /// The configuration object used for configuring scalar types. + public ScalarGraphTypeMaker(ISchemaConfiguration config) + { + _config = Validation.ThrowIfNullOrReturn(config, nameof(config)); + } + + /// + public GraphTypeCreationResult CreateGraphType(IGraphTypeTemplate typeTemplate) + { + if (!(typeTemplate is IScalarGraphTypeTemplate scalarTemplate)) + return null; + + + var scalarType = GlobalScalars.CreateScalarInstanceOrThrow(scalarTemplate.ScalarType); + scalarType = scalarType.Clone(_config.DeclarationOptions.GraphNamingFormatter.FormatGraphTypeName(scalarType.Name)); + + var result = new GraphTypeCreationResult() + { + GraphType = scalarType, + ConcreteType = scalarType.ObjectType, + }; + + // add any known directives as dependents + // to be added to the schema + foreach (var directiveToApply in scalarType.AppliedDirectives) + { + if (directiveToApply.DirectiveType != null) + result.AddDependent(directiveToApply.DirectiveType, TypeKind.DIRECTIVE); + } + + return result; + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Engine/TypeMakers/UnionGraphTypeMaker.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/UnionGraphTypeMaker.cs similarity index 65% rename from src/graphql-aspnet/Engine/TypeMakers/UnionGraphTypeMaker.cs rename to src/graphql-aspnet/Schemas/Generation/TypeMakers/UnionGraphTypeMaker.cs index 27ad7df53..7c2af79fe 100644 --- a/src/graphql-aspnet/Engine/TypeMakers/UnionGraphTypeMaker.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/UnionGraphTypeMaker.cs @@ -7,12 +7,20 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Engine.TypeMakers +namespace GraphQL.AspNet.Schemas.Generation.TypeMakers { + using System; using System.Linq; + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Common.Extensions; + using GraphQL.AspNet.Common.Generics; + using GraphQL.AspNet.Engine.TypeMakers; using GraphQL.AspNet.Execution; + using GraphQL.AspNet.Execution.Exceptions; + using GraphQL.AspNet.Interfaces.Configuration; using GraphQL.AspNet.Interfaces.Engine; using GraphQL.AspNet.Interfaces.Execution; + using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Internal; using GraphQL.AspNet.Internal.TypeTemplates; @@ -22,17 +30,28 @@ namespace GraphQL.AspNet.Engine.TypeMakers /// /// An object responsible for generating a union graph type from a proxy. /// - public sealed class UnionGraphTypeMaker : IUnionGraphTypeMaker + public sealed class UnionGraphTypeMaker : IGraphTypeMaker, IUnionGraphTypeMaker { - private readonly ISchema _schema; + private readonly ISchemaConfiguration _config; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// The schema. - public UnionGraphTypeMaker(ISchema schema) + /// The schema configuration used to determine what to incude + /// and how to build the union. + public UnionGraphTypeMaker(ISchemaConfiguration config) { - _schema = schema; + _config = Validation.ThrowIfNullOrReturn(config, nameof(config)); + } + + /// + public GraphTypeCreationResult CreateGraphType(IGraphTypeTemplate typeTemplate) + { + if (!(typeTemplate is IUnionGraphTypeTemplate template)) + return null; + + var proxy = GraphQLProviders.CreateUnionProxyFromType(template.ProxyType); + return this.CreateUnionFromProxy(proxy); } /// @@ -49,7 +68,7 @@ public GraphTypeCreationResult CreateUnionFromProxy(IGraphUnionProxy proxy) var directives = directiveTemplates.CreateAppliedDirectives(); - var formatter = _schema.Configuration.DeclarationOptions.GraphNamingFormatter; + var formatter = _config.DeclarationOptions.GraphNamingFormatter; var name = formatter.FormatGraphTypeName(proxy.Name); var union = new UnionGraphType( name, diff --git a/src/graphql-aspnet/Schemas/GraphSchemaManager.cs b/src/graphql-aspnet/Schemas/GraphSchemaManager.cs deleted file mode 100644 index 052ded9fb..000000000 --- a/src/graphql-aspnet/Schemas/GraphSchemaManager.cs +++ /dev/null @@ -1,499 +0,0 @@ -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - -namespace GraphQL.AspNet.Schemas -{ - using System; - using System.Collections.Generic; - using System.Linq; - using GraphQL.AspNet.Common; - using GraphQL.AspNet.Configuration.Formatting; - using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Engine.TypeMakers; - using GraphQL.AspNet.Execution; - using GraphQL.AspNet.Execution.Exceptions; - using GraphQL.AspNet.Interfaces.Configuration.Templates; - using GraphQL.AspNet.Interfaces.Internal; - using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal; - using GraphQL.AspNet.Internal.TypeTemplates; - using GraphQL.AspNet.Schemas.SchemaItemValidators; - using GraphQL.AspNet.Schemas.Structural; - using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Schemas.TypeSystem.Introspection; - using GraphQL.AspNet.Schemas.TypeSystem.Introspection.Fields; - using GraphQL.AspNet.Schemas.TypeSystem.Introspection.Model; - using Microsoft.AspNetCore.Mvc; - - /// - /// Assists with the creation of data - /// parsed from any or any manually added - /// to the this instance is managing. - /// - internal sealed class GraphSchemaManager - { - private readonly GraphNameFormatter _formatter; - private readonly Func _externalTypeChecker; - - /// - /// Initializes a new instance of the class. - /// - /// The schema instance to be managed. - public GraphSchemaManager(ISchema schema) - { - this.Schema = Validation.ThrowIfNullOrReturn(schema, nameof(schema)); - _formatter = this.Schema.Configuration.DeclarationOptions.GraphNamingFormatter; - - this.EnsureSchemaDependencies(); - this.EnsureGraphOperationType(GraphOperationType.Query); - } - - /// - /// Inspects the schema instance for any necessary dependencies - /// and adds them to itself (e.g. schema declared directives). - /// - private void EnsureSchemaDependencies() - { - // all schemas depend on String because of the __typename field - this.EnsureGraphType(); - - // ensure top level schema directives are accounted for - foreach (var directive in this.Schema.GetType().ExtractAppliedDirectives()) - { - this.Schema.AppliedDirectives.Add(directive); - } - - foreach (var appliedDirective in this.Schema.AppliedDirectives.Where(x => x.DirectiveType != null)) - { - this.EnsureGraphType( - appliedDirective.DirectiveType, - TypeKind.DIRECTIVE); - } - } - - /// - /// Adds the internal introspection fields to the query operation type if and only if the contained schema allows - /// it through its internal configuration. This method is idempotent. - /// - private void AddIntrospectionFields() - { - this.EnsureGraphOperationType(GraphOperationType.Query); - var queryField = this.Schema.Operations[GraphOperationType.Query]; - - // Note: introspection fields are defined by the graphql spec, no custom name or item formatting is allowed - // for Type and field name formatting. - // spec: https://graphql.github.io/graphql-spec/October2021/#sec-Schema-Introspection - if (!queryField.Fields.ContainsKey(Constants.ReservedNames.SCHEMA_FIELD)) - { - var introspectedSchema = new IntrospectedSchema(this.Schema); - queryField.Extend(new Introspection_SchemaField(introspectedSchema)); - queryField.Extend(new Introspection_TypeGraphField(introspectedSchema)); - - this.EnsureGraphType(typeof(string)); - this.EnsureGraphType(typeof(bool)); - this.Schema.KnownTypes.EnsureGraphType(new Introspection_DirectiveLocationType(), typeof(DirectiveLocation)); - this.Schema.KnownTypes.EnsureGraphType(new Introspection_DirectiveType(), typeof(IntrospectedDirective)); - this.Schema.KnownTypes.EnsureGraphType(new Introspection_EnumValueType(), typeof(IntrospectedEnumValue)); - this.Schema.KnownTypes.EnsureGraphType(new Introspection_FieldType(), typeof(IntrospectedField)); - this.Schema.KnownTypes.EnsureGraphType(new Introspection_InputValueType(), typeof(IntrospectedInputValueType)); - this.Schema.KnownTypes.EnsureGraphType(new Introspection_SchemaType(), typeof(IntrospectedSchema)); - this.Schema.KnownTypes.EnsureGraphType(new Introspection_TypeKindType(), typeof(TypeKind)); - this.Schema.KnownTypes.EnsureGraphType(new Introspection_TypeType(), typeof(IntrospectedType)); - } - } - - /// - /// Adds the built in directives supported by the graphql runtime. - /// - public void AddBuiltInDirectives() - { - foreach (var type in Constants.GlobalDirectives) - { - this.EnsureGraphType(type); - } - } - - /// - /// Adds the and all associated types and virtual types to the schema. - /// - /// The template fully describing the controller. - private void AddController(IGraphControllerTemplate gcd) - { - foreach (var action in gcd.Actions) - this.AddAction(action); - - foreach (var extension in gcd.Extensions) - this.AddTypeExtension(extension); - } - - /// - /// Adds the type extension to the schema for the configured concrete type. If the type - /// is not registered to the schema the field extension is queued for when it is added (if ever). - /// - /// The extension to add. - private void AddTypeExtension(IGraphFieldTemplate extension) - { - var fieldMaker = GraphQLProviders.GraphTypeMakerProvider.CreateFieldMaker(this.Schema); - var fieldResult = fieldMaker.CreateField(extension); - - if (fieldResult != null) - { - this.Schema.KnownTypes.EnsureGraphFieldExtension(extension.SourceObjectType, fieldResult.Field); - this.EnsureDependents(fieldResult); - } - } - - /// - /// Adds the to the schema. Any required parent fields - /// will be automatically created if necessary to ensure proper nesting. - /// - /// The action to add to the schema. - private void AddAction(IGraphFieldTemplate action) - { - if (this.Schema.Configuration.DeclarationOptions.AllowedOperations.Contains(action.Route.RootCollection.ToGraphOperationType())) - { - var operation = action.Route.RootCollection.ToGraphOperationType(); - this.EnsureGraphOperationType(operation); - var parentField = this.AddOrRetrieveControllerRoutePath(action); - this.AddActionAsField(parentField, action); - } - else - { - throw new ArgumentOutOfRangeException( - nameof(action), - $"The '{action.InternalFullName}' action's operation root ({action.Route.RootCollection}) is not " + - $"allowed by the target schema (Name: {this.Schema.Name})."); - } - } - - /// - /// Ensures that the root operation type (query, mutation etc.) exists on this schema and the associated virtual - /// type representing it also exists in the schema's type collection. - /// - /// Type of the operation. - private void EnsureGraphOperationType(GraphOperationType operationType) - { - if (operationType == GraphOperationType.Unknown) - { - throw new ArgumentOutOfRangeException($"The operation type '{operationType}' is " + - $"not supported by graphql."); - } - - if (!this.Schema.Operations.ContainsKey(operationType)) - { - var operation = new GraphOperation(operationType); - this.Schema.KnownTypes.EnsureGraphType(operation); - this.Schema.Operations.Add(operation.OperationType, operation); - } - } - - /// - /// Inspects the root and ensures that any intermediate, virtual fields - /// are accounted for and returns a reference to the immediate parent this action should be added to. - /// - /// The action. - /// IGraphField. - private IObjectGraphType AddOrRetrieveControllerRoutePath(IGraphFieldTemplate action) - { - var pathSegments = action.Route.GenerateParentPathSegments(); - - // loop through all parent path parts of this action - // creating virtual fields as necessary or using existing ones and adding on to them - IObjectGraphType parentType = this.Schema.Operations[action.Route.RootCollection.ToGraphOperationType()]; - - for (var i = 0; i < pathSegments.Count; i++) - { - var segment = pathSegments[i]; - var formattedName = _formatter.FormatFieldName(segment.Name); - if (parentType.Fields.ContainsKey(formattedName)) - { - var field = parentType[formattedName]; - var foundType = Schema.KnownTypes.FindGraphType(field.TypeExpression.TypeName); - - var ogt = foundType as IObjectGraphType; - if (ogt != null) - { - if (ogt.IsVirtual) - { - parentType = ogt; - continue; - } - - throw new GraphTypeDeclarationException( - $"The action '{action.Route}' attempted to nest itself under the {foundType.Kind} graph type '{foundType.Name}', which is returned by " + - $"the route '{field.Route}'. Actions can only be added to virtual graph types created by their parent controller."); - } - - if (foundType != null) - { - throw new GraphTypeDeclarationException( - $"The action '{action.Route.Path}' attempted to nest itself under the graph type '{foundType.Name}'. {foundType.Kind} graph types cannot " + - "accept fields."); - } - else - { - throw new GraphTypeDeclarationException( - $"The action '{action.Route.Path}' attempted to nest itself under the field '{field.Route}' but no graph type was found " + - "that matches its type."); - } - } - - parentType = this.CreateVirtualFieldOnParent( - parentType, - formattedName, - segment, - i == 0 ? action.Parent : null); - } - - return parentType; - } - - /// - /// Performs an out-of-band append of a new graph field to a parent. Accounts for type updates in this schema ONLY. - /// - /// the parent type to add the new field to. - /// Name of the field. - /// The path segment to represent the new field. - /// The definition item from which graph attributes should be used, if any. Attributes will be set to an empty string if not supplied. - /// The type associated with the field added to the parent type. - private IObjectGraphType CreateVirtualFieldOnParent( - IObjectGraphType parentType, - string fieldName, - SchemaItemPath path, - ISchemaItemTemplate definition = null) - { - var childField = new VirtualGraphField( - parentType, - fieldName, - path, - this.MakeSafeTypeNameFromRoutePath(path)) - { - IsDepreciated = false, - DepreciationReason = string.Empty, - Description = definition?.Description ?? string.Empty, - }; - - parentType.Extend(childField); - this.Schema.KnownTypes.EnsureGraphType(childField.AssociatedGraphType); - this.EnsureDependents(childField); - - return childField.AssociatedGraphType; - } - - /// - /// Makes the unique route being used for this virtual field type safe, removing special control characters - /// but retaining its uniqueness. - /// - /// The path. - /// System.String. - private string MakeSafeTypeNameFromRoutePath(SchemaItemPath path) - { - var segments = new List(); - foreach (var pathSegmentName in path) - { - switch (pathSegmentName) - { - case Constants.Routing.QUERY_ROOT: - segments.Add(Constants.ReservedNames.QUERY_TYPE_NAME); - break; - - case Constants.Routing.MUTATION_ROOT: - segments.Add(Constants.ReservedNames.MUTATION_TYPE_NAME); - break; - - case Constants.Routing.SUBSCRIPTION_ROOT: - segments.Add(Constants.ReservedNames.SUBSCRIPTION_TYPE_NAME); - break; - - default: - segments.Add(_formatter.FormatGraphTypeName(pathSegmentName)); - break; - } - } - - segments.Reverse(); - return string.Join("_", segments); - } - - /// - /// Iterates the given and adds - /// all found types to the type system for this . Generates - /// a field reference on the provided parent with a resolver pointing to the provided graph action. - /// - /// The parent which will own the generated action field. - /// The action. - private void AddActionAsField(IObjectGraphType parentType, IGraphFieldTemplate action) - { - // apend the action as a field on the parent - var maker = GraphQLProviders.GraphTypeMakerProvider.CreateFieldMaker(this.Schema); - var fieldResult = maker.CreateField(action); - - if (fieldResult != null) - { - if (parentType.Fields.ContainsKey(fieldResult.Field.Name)) - { - throw new GraphTypeDeclarationException( - $"The '{parentType.Kind}' graph type '{parentType.Name}' already contains a field named '{fieldResult.Field.Name}'. " + - $"The action method '{action.InternalFullName}' cannot be added to the graph type with the same name."); - } - - parentType.Extend(fieldResult.Field); - this.EnsureDependents(fieldResult); - } - } - - /// - /// Adds a runtime declared field (with its assigned resolver) as a field in the schema. - /// - /// The field definition to add to the schema. - public void AddRuntimeFieldDeclaration(IGraphQLRuntimeResolvedFieldDefinition fieldDefinition) - { - Validation.ThrowIfNull(fieldDefinition, nameof(fieldDefinition)); - var template = new RuntimeGraphControllerTemplate(fieldDefinition); - - template.Parse(); - template.ValidateOrThrow(); - - this.AddController(template); - } - - /// - /// Inspects and adds the given type to the schema as a graph type or a registered controller depending - /// on the type. The type kind will be automatically inferred or an error will be thrown. - /// - /// The type of the item to add to the schema. - public void EnsureGraphType() - { - this.EnsureGraphType(typeof(TItem)); - } - - /// - /// Inspects and adds the given type to the schema as a graph type or a registered controller depending - /// on the type. The type kind will be automatically inferred or an error will be thrown. - /// - /// The type of the item to add to the schema. - /// The kind of graph type to create from the supplied concrete type. - /// Only necessary to differentiate between OBJECT and INPUT_OBJECT types. - public void EnsureGraphType(TypeKind? kind = null) - { - this.EnsureGraphType(typeof(TItem), kind); - } - - /// - /// Adds the given type to the schema as a graph type or a registered controller depending - /// on the type. - /// - /// The concrete type to add. - /// The kind of graph type to create from the supplied concrete type. If not supplied the concrete type will - /// attempt to auto assign a type of scalar, enum or object as necessary. - public void EnsureGraphType(Type type, TypeKind? kind = null) - { - Validation.ThrowIfNull(type, nameof(type)); - if (Validation.IsCastable(type)) - { - if (GraphQLProviders.TemplateProvider.ParseType(type) is IGraphControllerTemplate controllerTemplate) - this.AddController(controllerTemplate); - - return; - } - - type = GraphValidation.EliminateWrappersFromCoreType(type); - - // if the type is already registered, early exit no point in running it through again - var actualKind = GraphValidation.ResolveTypeKindOrThrow(type, kind); - if (this.Schema.KnownTypes.Contains(type, actualKind)) - return; - - GraphTypeCreationResult makerResult = null; - var maker = GraphQLProviders.GraphTypeMakerProvider.CreateTypeMaker(this.Schema, actualKind); - if (maker != null) - { - // if a maker can be assigned for this graph type - // create the graph type directly - makerResult = maker.CreateGraphType(type); - } - else if (Validation.IsCastable(type)) - { - // if this type represents a well-known union proxy try and add in the union proxy - // directly - var unionProxy = GraphQLProviders.GraphTypeMakerProvider.CreateUnionProxyFromType(type); - if (unionProxy != null) - { - var unionMaker = GraphQLProviders.GraphTypeMakerProvider.CreateUnionMaker(this.Schema); - makerResult = unionMaker.CreateUnionFromProxy(unionProxy); - } - } - - if (makerResult != null) - { - this.Schema.KnownTypes.EnsureGraphType(makerResult.GraphType, makerResult.ConcreteType); - this.EnsureDependents(makerResult); - } - } - - /// - /// Ensures the dependents in teh given collection are part of the target . - /// - /// The dependency set. - private void EnsureDependents(IGraphItemDependencies dependencySet) - { - foreach (var abstractType in dependencySet.AbstractGraphTypes) - { - this.Schema.KnownTypes.EnsureGraphType(abstractType); - } - - foreach (var dependent in dependencySet.DependentTypes) - { - this.EnsureGraphType(dependent.Type, dependent.ExpectedKind); - } - } - - /// - /// Clears, builds and caches the introspection metadata used to describe this schema. If introspection - /// fields have not been added to the schema this method does nothing. No changes to the schema - /// items themselves happens during this method call. - /// - public void RebuildIntrospectionData() - { - if (this.Schema.Configuration.DeclarationOptions.DisableIntrospection) - return; - - this.EnsureGraphOperationType(GraphOperationType.Query); - this.AddIntrospectionFields(); - - var queryType = this.Schema.Operations[GraphOperationType.Query]; - if (!queryType.Fields.ContainsKey(Constants.ReservedNames.SCHEMA_FIELD)) - return; - - var field = queryType.Fields[Constants.ReservedNames.SCHEMA_FIELD] as Introspection_SchemaField; - field.IntrospectedSchema.Rebuild(); - } - - /// - /// Validates each registered type, field, argument and directive to ensure that its - /// internally consistance with itself and that the schema is in a usable state. - /// - public void ValidateSchemaIntegrity() - { - var allItems = this.Schema.AllSchemaItems(includeDirectives: true); - - foreach (var item in allItems) - { - var validator = SchemaItemValidationFactory.CreateValidator(item); - validator.ValidateOrThrow(item, this.Schema); - } - } - - /// - /// Gets the schema being managed and built by this instance. - /// - /// The schema. - public ISchema Schema { get; } - } -} \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/GraphTypeExpression_Statics.cs b/src/graphql-aspnet/Schemas/GraphTypeExpression_Statics.cs index 2f89136b1..1e49ce56e 100644 --- a/src/graphql-aspnet/Schemas/GraphTypeExpression_Statics.cs +++ b/src/graphql-aspnet/Schemas/GraphTypeExpression_Statics.cs @@ -15,6 +15,7 @@ namespace GraphQL.AspNet.Schemas using System.Linq; using GraphQL.AspNet.Common; using GraphQL.AspNet.Execution.Parsing.Lexing.Tokens; + using GraphQL.AspNet.Execution.RulesEngine.RuleSets.DocumentValidation.QueryFragmentSteps; using GraphQL.AspNet.Internal; using GraphQL.AspNet.Schemas.TypeSystem; @@ -249,41 +250,43 @@ public static GraphTypeExpression FromType(Type typeToCheck, MetaGraphTypes[] ty /// /// The target expression to which a value is being given. /// The expression of the value to be supplied to the target. + /// When true, the inner type name of the expression must match exactly (case-sensitive) to + /// that of the expression. /// true if a value of the expression is /// compatiable and could be supplied or used as an input value to an item of the expression, false otherwise. - public static bool AreTypesCompatiable(GraphTypeExpression target, GraphTypeExpression supplied) + public static bool AreTypesCompatiable(GraphTypeExpression target, GraphTypeExpression supplied, bool matchTypeName = true) { if (target == null || supplied == null) return false; - // when root types don't match they can never be compatible - if (target.TypeName != supplied.TypeName) - return false; - if (!target.IsNullable) { if (supplied.IsNullable) return false; - return AreTypesCompatiable(target.UnWrapExpression(), supplied.UnWrapExpression()); + return AreTypesCompatiable(target.UnWrapExpression(), supplied.UnWrapExpression(), matchTypeName); } else if (!supplied.IsNullable) { - return AreTypesCompatiable(target, supplied.UnWrapExpression()); + return AreTypesCompatiable(target, supplied.UnWrapExpression(), matchTypeName); } else if (target.IsListOfItems) { if (!supplied.IsListOfItems) return false; - return AreTypesCompatiable(target.UnWrapExpression(), supplied.UnWrapExpression()); + return AreTypesCompatiable(target.UnWrapExpression(), supplied.UnWrapExpression(), matchTypeName); } else if (supplied.IsListOfItems) { return false; } - return target == supplied; + // when root types don't match they can never be compatible + if (matchTypeName) + return target == supplied; + + return true; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Internal/GraphTypeNames.cs b/src/graphql-aspnet/Schemas/GraphTypeNames.cs similarity index 97% rename from src/graphql-aspnet/Internal/GraphTypeNames.cs rename to src/graphql-aspnet/Schemas/GraphTypeNames.cs index 2c06d6775..762569144 100644 --- a/src/graphql-aspnet/Internal/GraphTypeNames.cs +++ b/src/graphql-aspnet/Schemas/GraphTypeNames.cs @@ -17,6 +17,7 @@ namespace GraphQL.AspNet.Internal using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Schemas.TypeSystem.Scalars; /// /// A global collection of known graph type names and their concrete type references. @@ -97,9 +98,9 @@ public static string ParseName(Type type, TypeKind kind) return typeName; type = GraphValidation.EliminateWrappersFromCoreType(type); - if (GraphQLProviders.ScalarProvider.IsScalar(type)) + if (GlobalScalars.IsBuiltInScalar(type)) { - typeName = GraphQLProviders.ScalarProvider.RetrieveScalarName(type); + typeName = GlobalScalars.CreateScalarInstanceOrThrow(type).Name; } else if (type.IsEnum) { diff --git a/src/graphql-aspnet/Internal/GraphValidation.cs b/src/graphql-aspnet/Schemas/GraphValidation.cs similarity index 95% rename from src/graphql-aspnet/Internal/GraphValidation.cs rename to src/graphql-aspnet/Schemas/GraphValidation.cs index b2e32daf9..8493baefb 100644 --- a/src/graphql-aspnet/Internal/GraphValidation.cs +++ b/src/graphql-aspnet/Schemas/GraphValidation.cs @@ -18,6 +18,7 @@ namespace GraphQL.AspNet.Internal using System.Threading.Tasks; using GraphQL.AspNet.Common; using GraphQL.AspNet.Common.Extensions; + using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Directives; using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Interfaces.Schema; @@ -93,30 +94,20 @@ public static TypeKind ResolveTypeKind(Type type, TypeKind? overrideValue = null { if (type != null) { - if (GraphQLProviders.ScalarProvider.IsScalar(type)) - { - return TypeKind.SCALAR; - } - if (type.IsEnum) - { return TypeKind.ENUM; - } if (Validation.IsCastable(type)) - { return TypeKind.UNION; - } if (type.IsInterface) - { return TypeKind.INTERFACE; - } + + if (Validation.IsCastable(type)) + return TypeKind.CONTROLLER; if (Validation.IsCastable(type)) - { return TypeKind.DIRECTIVE; - } } return overrideValue ?? TypeKind.OBJECT; @@ -345,6 +336,19 @@ public static bool IsValidGraphType(Type type, bool throwOnFailure = false) return true; } + /// + /// Determines if the provided type, if converted to a graph type, must be a + /// leaf type and will never contain fields. + /// + /// The type to check. + /// true if the type must be converted to a leaf graph type, false otherwise. + public static bool MustBeLeafType(Type typeToCheck) + { + Validation.ThrowIfNull(typeToCheck, nameof(typeToCheck)); + + return typeToCheck.IsPrimitive || typeToCheck.IsEnum; + } + /// /// Checks if the concrete type MUST be provided on the object graph or if it can be represented with 'null'. /// diff --git a/src/graphql-aspnet/Schemas/SchemaItemValidators/GraphFieldValidator.cs b/src/graphql-aspnet/Schemas/SchemaItemValidators/GraphFieldValidator.cs new file mode 100644 index 000000000..270a39c6d --- /dev/null +++ b/src/graphql-aspnet/Schemas/SchemaItemValidators/GraphFieldValidator.cs @@ -0,0 +1,22 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Schemas.SchemaItemValidators +{ + using System; + using GraphQL.AspNet.Interfaces.Schema; + + internal class GraphFieldValidator : BaseSchemaItemValidator + { + public override void ValidateOrThrow(ISchemaItem schemaItem, ISchema schema) + { + + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/TypeSystem/GraphFieldArgument.cs b/src/graphql-aspnet/Schemas/TypeSystem/GraphFieldArgument.cs index 2e32edf51..ed1e14d37 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/GraphFieldArgument.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/GraphFieldArgument.cs @@ -91,7 +91,7 @@ public IGraphArgument Clone(ISchemaItem parent) } /// - public string Name { get; set; } + public string Name { get; } /// public string Description { get; set; } diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedDirective.cs b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedDirective.cs index 34e01c5e4..740c2eaa9 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedDirective.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedDirective.cs @@ -41,6 +41,10 @@ public override void Initialize(IntrospectedSchema introspectedSchema) foreach (var arg in directiveArguments) { var introspectedType = introspectedSchema.FindIntrospectedType(arg.TypeExpression.TypeName); + if(introspectedType == null) + { + var str = ""; + } introspectedType = Introspection.WrapBaseTypeWithModifiers(introspectedType, arg.TypeExpression); var inputValue = new IntrospectedInputValueType(arg, introspectedType); list.Add(inputValue); diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedField.cs b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedField.cs index 55c4e3f87..be0dadaf6 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedField.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedField.cs @@ -44,6 +44,11 @@ public override void Initialize(IntrospectedSchema introspectedSchema) { var introspectedType = introspectedSchema.FindIntrospectedType(arg.TypeExpression.TypeName); introspectedType = Introspection.WrapBaseTypeWithModifiers(introspectedType, arg.TypeExpression); + if(introspectedType == null) + { + var str = ""; + } + var inputValue = new IntrospectedInputValueType(arg, introspectedType); inputValue.Initialize(introspectedSchema); list.Add(inputValue); diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedType.cs b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedType.cs index 8ce45b326..1b235336b 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedType.cs @@ -115,7 +115,16 @@ private void LoadFields(IntrospectedSchema schema) foreach (var field in fieldContainer.Fields.Where(x => x.Publish)) { IntrospectedType introspectedType = schema.FindIntrospectedType(field.TypeExpression.TypeName); + if (introspectedType == null) + { + string str = ""; + } + introspectedType = Introspection.WrapBaseTypeWithModifiers(introspectedType, field.TypeExpression); + if(introspectedType == null) + { + string str = ""; + } var introField = new IntrospectedField(field, introspectedType); fields.Add(introField); introField.Initialize(schema); diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/Introspection.cs b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/Introspection.cs index c5ac10da1..d36adf383 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/Introspection.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/Introspection.cs @@ -41,6 +41,11 @@ public static IntrospectedType WrapBaseTypeWithModifiers(IntrospectedType baseTy { for (var i = wrappers.Count - 1; i >= 0; i--) { + if(baseType == null) + { + string str = ""; + } + switch (wrappers[i]) { case MetaGraphTypes.IsNotNull: diff --git a/src/graphql-aspnet/Schemas/TypeSystem/MethodGraphField.cs b/src/graphql-aspnet/Schemas/TypeSystem/MethodGraphField.cs index 79e433a5a..d5fa64702 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/MethodGraphField.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/MethodGraphField.cs @@ -69,7 +69,6 @@ public MethodGraphField( this.SecurityGroups = new AppliedSecurityPolicyGroups(securityPolicies); - this.IsLeaf = GraphQLProviders.ScalarProvider.IsLeaf(this.ObjectType); this.UpdateResolver(resolver, mode); this.Publish = true; } @@ -194,9 +193,6 @@ protected virtual MethodGraphField CreateNewInstance(IGraphType parent) /// public FieldResolutionMode Mode { get; protected set; } - /// - public bool IsLeaf { get; protected set; } - /// public bool IsDeprecated { get; set; } diff --git a/src/graphql-aspnet/Schemas/TypeSystem/PropertyGraphField.cs b/src/graphql-aspnet/Schemas/TypeSystem/PropertyGraphField.cs index 71845864d..69e6e91a2 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/PropertyGraphField.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/PropertyGraphField.cs @@ -41,8 +41,8 @@ public PropertyGraphField( GraphTypeExpression typeExpression, SchemaItemPath route, string declaredPropertyName, - Type objectType = null, - Type declaredReturnType = null, + Type objectType, + Type declaredReturnType, FieldResolutionMode mode = FieldResolutionMode.PerSourceItem, IGraphFieldResolver resolver = null, IEnumerable securityPolicies = null, diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/GlobalScalars.cs b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/GlobalScalars.cs new file mode 100644 index 000000000..a172f2bda --- /dev/null +++ b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/GlobalScalars.cs @@ -0,0 +1,313 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Schemas.TypeSystem.Scalars +{ + using System; + using System.Collections.Generic; + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Common.Extensions; + using GraphQL.AspNet.Common.Generics; + using GraphQL.AspNet.Execution.Exceptions; + using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Internal; + + /// + /// A map of .NET types and their related built in scalar types. + /// + public static class GlobalScalars + { + private static readonly Dictionary _scalarGraphTypeTypesByConcreteType; + private static readonly Dictionary _scalarsByName; + private static readonly HashSet _fixedNamedScalars; + + static GlobalScalars() + { + _scalarGraphTypeTypesByConcreteType = new Dictionary(); + _scalarsByName = new Dictionary(StringComparer.OrdinalIgnoreCase); + _fixedNamedScalars = new HashSet(); + + ValidateAndRegisterBuiltInScalar(true); + ValidateAndRegisterBuiltInScalar(); + ValidateAndRegisterBuiltInScalar(); + ValidateAndRegisterBuiltInScalar(); + ValidateAndRegisterBuiltInScalar(true); + ValidateAndRegisterBuiltInScalar(); + ValidateAndRegisterBuiltInScalar(); + ValidateAndRegisterBuiltInScalar(true); + ValidateAndRegisterBuiltInScalar(true); + ValidateAndRegisterBuiltInScalar(); + ValidateAndRegisterBuiltInScalar(); + ValidateAndRegisterBuiltInScalar(); + ValidateAndRegisterBuiltInScalar(); + ValidateAndRegisterBuiltInScalar(); + ValidateAndRegisterBuiltInScalar(); + ValidateAndRegisterBuiltInScalar(true); + ValidateAndRegisterBuiltInScalar(); + ValidateAndRegisterBuiltInScalar(); + ValidateAndRegisterBuiltInScalar(); + ValidateAndRegisterBuiltInScalar(); + } + + private static void ValidateAndRegisterBuiltInScalar(bool isFixedName = false) + where T : IScalarGraphType + { + var instance = CreateScalarInstanceOrThrow(typeof(T)); + if (_scalarGraphTypeTypesByConcreteType.ContainsKey(instance.ObjectType)) + { + var registeredType = _scalarGraphTypeTypesByConcreteType[instance.ObjectType]; + throw new GraphTypeDeclarationException( + $"The scalar '{typeof(T).FriendlyName()}' is attempting to register a known type of '{instance.ObjectType.FriendlyName()}' but it is " + + $"already reserved by the scalar '{registeredType.FriendlyName()}'. Built in scalar type mappings must be unique."); + } + + if (_scalarsByName.ContainsKey(instance.Name)) + { + var registeredType = _scalarsByName[instance.Name]; + throw new GraphTypeDeclarationException( + $"The scalar '{typeof(T).FriendlyName()}' is attempting to register with the name '{instance.Name}' but it is " + + $"already reserved by the scalar '{registeredType.FriendlyName()}'. Built in scalar type names must be globally unique."); + } + + _scalarGraphTypeTypesByConcreteType.Add(instance.ObjectType, typeof(T)); + _scalarsByName.Add(instance.Name, typeof(T)); + + if (isFixedName) + _fixedNamedScalars.Add(typeof(T)); + } + + /// + /// If the provided represents a known, built in scalar + /// the representing the associated + /// is returned. If the is not a built in scalar, + /// null is returned. + /// + /// + /// e.g. if is provided, then + /// is returned. + /// + /// The type to check. + /// The concrete type that represents the scalar. This type + /// is guaranteed to implement . + public static Type FindBuiltInScalarType(Type typeToCheck) + { + if (typeToCheck == null) + return null; + + if (typeToCheck.IsNullableOfT()) + { + typeToCheck = GraphValidation.EliminateWrappersFromCoreType( + typeToCheck, + eliminateEnumerables: false, + eliminateTask: false, + eliminateNullableT: true); + } + + if (_scalarGraphTypeTypesByConcreteType.ContainsKey(typeToCheck)) + return _scalarGraphTypeTypesByConcreteType[typeToCheck]; + + return null; + } + + /// + /// Determines whether the provided type represents a known, globally available scalar. + /// + /// The type to check. + /// true if the type is a built in scalar; otherwise, false. + public static bool IsBuiltInScalar(Type typeToCheck) + { + return FindBuiltInScalarType(typeToCheck) != null; + } + + /// + /// Determines whether the assigned name is the name of a known global sclar. This check is not + /// case-sensitive. + /// + /// Name of the scalar. + /// true if the name is a known global scalar; otherwise, false. + internal static bool IsBuiltInScalar(string scalarName) + { + if (scalarName == null) + return false; + + return _scalarsByName.ContainsKey(scalarName); + } + + /// + /// Determines whether the scalar matching the required name can be reformatted or re-cased to a different name. + /// + /// + /// The five specification-defined scalars (Int, Float, String, Boolean, ID) cannot be renamed and are used + /// as part of the introspection system. All other internal scalars can be renamed to match any casing rules + /// for a target schema. + /// + /// Name of the scalar. + /// true the name can be reformatted, otherwise false. + public static bool CanBeRenamed(string scalarName) + { + // meh, its not a built in scalar, doesnt really matter + if (scalarName == null) + return true; + + // if the name represents a globally defined scalar + // and if that scalar is declared as a fixed name + // then don't allow it to be renamed named + if (_scalarsByName.ContainsKey(scalarName)) + { + var scalarType = _scalarsByName[scalarName]; + return !_fixedNamedScalars.Contains(scalarType); + } + + return true; + } + + /// + /// Validates that the supplied type can be used to build a scalar instance + /// that is usable by a schema. + /// + /// The type representing an . + public static void ValidateScalarTypeOrThrow(Type scalarType) + { + Validation.ThrowIfNull(scalarType, nameof(scalarType)); + + if (!Validation.IsCastable(scalarType)) + { + throw new GraphTypeDeclarationException( + $"The scalar must implement the interface '{typeof(IScalarGraphType).FriendlyName()}'."); + } + + var paramlessConstructor = scalarType.GetConstructor(new Type[0]); + if (paramlessConstructor == null) + { + throw new GraphTypeDeclarationException( + "The scalar must declare a public, parameterless constructor."); + } + + var graphType = InstanceFactory.CreateInstance(scalarType) as IScalarGraphType; + ValidateScalarTypeOrThrow(graphType); + } + + /// + /// Validates that the supplied scalar instance is valid and could be used by a schema + /// instance. + /// + /// The graph type instance to check. + public static void ValidateScalarTypeOrThrow(IScalarGraphType graphType) + { + if (string.IsNullOrWhiteSpace(graphType.Name)) + { + throw new GraphTypeDeclarationException( + "The scalar must supply a name that is not null or whitespace."); + } + + if (!GraphValidation.IsValidGraphName(graphType.Name)) + { + throw new GraphTypeDeclarationException( + $"The scalar must supply a name that that conforms to the standard rules for GraphQL. (Regex: {Constants.RegExPatterns.NameRegex})"); + } + + if (graphType.Kind != TypeKind.SCALAR) + { + throw new GraphTypeDeclarationException( + $"The '{graphType.Name}' scalar's type kind must be set to '{nameof(TypeKind.SCALAR)}'."); + } + + if (graphType.ObjectType == null) + { + throw new GraphTypeDeclarationException( + $"The scalar '{graphType.Name}' must supply a value for '{nameof(graphType.ObjectType)}', is cannot be null."); + } + + if (Validation.IsNullableOfT(graphType.ObjectType)) + { + throw new GraphTypeDeclarationException( + $"The scalar '{graphType.Name}' must supply the root,non-nullable type derivation for '{nameof(graphType.ObjectType)}' (e.g. 'int' not 'int?'). " + + $" The current value of {nameof(IScalarGraphType.ObjectType)} is a nullable type derivation."); + } + + if (graphType.SourceResolver == null) + { + throw new GraphTypeDeclarationException( + $"The scalar must supply a value for '{nameof(graphType.SourceResolver)}' that can convert data from a " + + $"query into the primary object type of '{graphType.ObjectType.FriendlyName()}'."); + } + + if (graphType.ValueType == ScalarValueType.Unknown) + { + throw new GraphTypeDeclarationException( + $"The scalar must supply a value for '{nameof(graphType.ValueType)}'. This lets the validation engine " + + "know what data types submitted on a user query could be parsed into a value for this scale."); + } + + if (graphType.OtherKnownTypes == null) + { + throw new GraphTypeDeclarationException( + $"Custom scalars must supply a value for '{nameof(graphType.OtherKnownTypes)}', it cannot be null. " + + $"Use '{nameof(TypeCollection)}.{nameof(TypeCollection.Empty)}' if there are no other known types."); + } + + if (graphType.AppliedDirectives == null || graphType.AppliedDirectives.Parent != graphType) + { + throw new GraphTypeDeclarationException( + $"Custom scalars must supply a value for '{nameof(graphType.AppliedDirectives)}', it cannot be null. " + + $"The '{nameof(IAppliedDirectiveCollection.Parent)}' property of the directive collection must also be set to the scalar itself."); + } + } + + /// + /// Creates a new instance of the scalar. If the supplied type cannot be created + /// a valid an exception is thrown. + /// + /// The scalar type to create. + /// IScalarGraphType. + public static IScalarGraphType CreateScalarInstanceOrThrow(Type scalarType) + { + scalarType = GraphValidation.EliminateNextWrapperFromCoreType(scalarType); + scalarType = FindBuiltInScalarType(scalarType) ?? scalarType; + + ValidateScalarTypeOrThrow(scalarType); + return InstanceFactory.CreateInstance(scalarType) as IScalarGraphType; + } + + /// + /// Creates a new instance of the scalar. If the supplied type cannot be created + /// a valid null is returned. + /// + /// The scalar type to create. + /// IScalarGraphType. + public static IScalarGraphType CreateScalarInstance(Type scalarType) + { + scalarType = GraphValidation.EliminateNextWrapperFromCoreType(scalarType); + scalarType = FindBuiltInScalarType(scalarType) ?? scalarType; + + try + { + ValidateScalarTypeOrThrow(scalarType); + } + catch + { + return null; + } + + return InstanceFactory.CreateInstance(scalarType) as IScalarGraphType; + } + + /// + /// Gets the list of concrete types that represent all known scalars. + /// + /// The set of concrete types for all the global scalars. + public static IEnumerable ConcreteTypes => _scalarGraphTypeTypesByConcreteType.Keys; + + /// + /// Gets the types that represent the object for all known scalars. + /// + /// The set of scalar instance types for all global scalars. + public static IEnumerable ScalarInstanceTypes => _scalarGraphTypeTypesByConcreteType.Values; + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/ScalarGraphTypeBase.cs b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/ScalarGraphTypeBase.cs index ea55756b5..d8685a12b 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/ScalarGraphTypeBase.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/ScalarGraphTypeBase.cs @@ -100,7 +100,21 @@ public virtual string SerializeToQueryLanguage(object item) } /// - public virtual string Name { get; set; } + public virtual IScalarGraphType Clone(string newName) + { + newName = Validation.ThrowIfNullWhiteSpaceOrReturn(newName, nameof(newName)); + var newInstance = GlobalScalars.CreateScalarInstanceOrThrow(this.GetType()) as ScalarGraphTypeBase; + + // some built in scalars (defined against this class) + // should never be renameable (string, int, float, id, boolean) + if (GlobalScalars.CanBeRenamed(this.Name)) + newInstance.Name = newName; + + return newInstance; + } + + /// + public virtual string Name { get; protected set; } /// public virtual Type ObjectType { get; } diff --git a/src/graphql-aspnet/Schemas/TypeSystem/SchemaExtensions.cs b/src/graphql-aspnet/Schemas/TypeSystem/SchemaExtensions.cs index 4fcea98eb..c24886770 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/SchemaExtensions.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/SchemaExtensions.cs @@ -10,6 +10,7 @@ namespace GraphQL.AspNet.Schemas.TypeSystem { using System.Collections.Generic; using System.Linq; + using GraphQL.AspNet.Common; using GraphQL.AspNet.Interfaces.Schema; /// @@ -26,6 +27,8 @@ public static class SchemaExtensions /// IEnumerable<ISchemaItem>. public static IEnumerable AllSchemaItems(this ISchema schema, bool includeDirectives = false) { + Validation.ThrowIfNull(schema, nameof(schema)); + // schema first yield return schema; diff --git a/src/graphql-aspnet/Schemas/TypeSystem/TypeCollections/ConcreteTypeCollection.cs b/src/graphql-aspnet/Schemas/TypeSystem/TypeCollections/ConcreteTypeCollection.cs index ea2caaf5d..07bf1c62f 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/TypeCollections/ConcreteTypeCollection.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/TypeCollections/ConcreteTypeCollection.cs @@ -12,6 +12,7 @@ namespace GraphQL.AspNet.Schemas.TypeSystem.TypeCollections using System; using System.Collections.Concurrent; using System.Collections.Generic; + using System.Linq; using GraphQL.AspNet.Common; using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Directives; @@ -41,17 +42,25 @@ public ConcreteTypeCollection() /// method will perform a coersion if possible. /// /// The concrete type to search with. - /// The kind of graph type to search for. If not supplied the schema will attempt to automatically - /// resolve the correct kind from the given . + /// An optional kind of graph type to search for. Only used in a tie breaker scenario + /// such as if a concrete type is registered as both an OBJECT and INPUT_OBJECT. /// IGraphType. public IGraphType FindGraphType(Type type, TypeKind? kind = null) { Validation.ThrowIfNull(type, nameof(type)); - type = GraphQLProviders.ScalarProvider.EnsureBuiltInTypeReference(type); - var resolvedKind = GraphValidation.ResolveTypeKind(type, kind); + type = GraphValidation.EliminateNextWrapperFromCoreType(type); + if (_graphTypesByConcreteType.TryGetValue(type, out var typeSet)) { + if (typeSet.Count == 1) + { + var value = typeSet.First().Value; + if (!kind.HasValue || value.Kind.IsLeafKind()) + return value; + } + + var resolvedKind = kind ?? TypeKind.OBJECT; if (typeSet.TryGetValue(resolvedKind, out var graphType)) return graphType; } @@ -90,20 +99,9 @@ public Type FindType(IGraphType graphType) /// passed when adding a . public IGraphType EnsureRelationship(IGraphType graphType, Type concreteType) { - // ensure a type association for scalars to its root type - concreteType = GraphQLProviders.ScalarProvider.EnsureBuiltInTypeReference(concreteType); - if (graphType.Kind == TypeKind.SCALAR) - { - concreteType = concreteType ?? GraphQLProviders.ScalarProvider.RetrieveConcreteType(graphType.Name); - - // if a type was provided make sure it COULD be a scalar type - if (!GraphQLProviders.ScalarProvider.IsScalar(concreteType)) - { - throw new GraphTypeDeclarationException( - $"The scalar '{graphType.Name}' attempted to associate itself to a concrete type of {concreteType.FriendlyName()}. " + - "Scalars cannot be associated with non scalar concrete types."); - } - } + // the registered concrete etype of a scalar must always be the primary declaration + if (graphType is IScalarGraphType scalarType) + concreteType = concreteType ?? scalarType.ObjectType; this.EnsureGraphTypeToConcreteTypeAssociationOrThrow(graphType, concreteType); if (concreteType == null) @@ -153,16 +151,17 @@ public IGraphType EnsureRelationship(IGraphType graphType, Type concreteType) /// true if a graph type exists, false otherwise. public bool Contains(Type type, TypeKind? kind = null) { - type = GraphQLProviders.ScalarProvider.EnsureBuiltInTypeReference(type); + Validation.ThrowIfNull(type, nameof(type)); + if (_graphTypesByConcreteType.TryGetValue(type, out var typeSet)) { - var resolvedKind = kind ?? GraphValidation.ResolveTypeKind(type); - return typeSet.ContainsKey(resolvedKind); - } - else - { - return false; + if (!kind.HasValue) + return true; + + return typeSet.ContainsKey(kind.Value); } + + return false; } /// @@ -175,12 +174,16 @@ private void EnsureGraphTypeToConcreteTypeAssociationOrThrow(IGraphType graphTyp { // scalars must be assigned to their pre-defined and accepted concrete type // instances of scalar graph types must be their pre-defined instance as well - if (graphType.Kind == TypeKind.SCALAR) + if (graphType is IScalarGraphType scalarType) { - if (associatedType == null || GraphQLProviders.ScalarProvider.RetrieveScalarName(associatedType) != graphType.Name) + if (associatedType == null || + (associatedType != scalarType.ObjectType && + !scalarType.OtherKnownTypes.Contains(associatedType))) { throw new GraphTypeDeclarationException( - $"The scalar type '{graphType.Name}' cannot be added and associated to the concrete type '{associatedType?.FriendlyName() ?? "-null-"}' it is not an approved scalar type."); + $"The scalar type '{graphType.Name}' cannot be associated to the concrete type '{associatedType?.FriendlyName() ?? "-null-"}' " + + $"on the target schema. Only explicitly declared concrete types on the scalar declaration are " + + $"allowed to represent the to be used for the schema."); } } diff --git a/src/graphql-aspnet/Schemas/TypeSystem/TypeCollections/SchemaTypeCollection.cs b/src/graphql-aspnet/Schemas/TypeSystem/TypeCollections/SchemaTypeCollection.cs index bd42f8ff8..3585b6600 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/TypeCollections/SchemaTypeCollection.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/TypeCollections/SchemaTypeCollection.cs @@ -95,6 +95,7 @@ public bool EnsureGraphType(IGraphType graphType, Type associatedType = null) // they can now be safely included if (associatedType != null) { + var unregisteredFields = _typeQueue.DequeueFields(associatedType); if (graphType is IExtendableGraphType objType) { @@ -162,7 +163,10 @@ public IGraphType FindGraphType(object data) return null; if (data is Type type) - return this.FindGraphType(type, TypeKind.OBJECT); + { + this.DenySearchForListAndKVP(type); + return _concreteTypes.FindGraphType(type, null); + } if (data is VirtualResolvedObject virtualFieldObject) { @@ -251,10 +255,7 @@ private void DenySearchForListAndKVP(Type concreteType) if (concreteType == null) return; - if (GraphQLProviders.ScalarProvider.IsScalar(concreteType)) - return; - - if (concreteType != typeof(string) && typeof(IEnumerable).IsAssignableFrom(concreteType)) + if (concreteType != typeof(string) && Validation.IsCastable(concreteType, typeof(IEnumerable))) { throw new GraphTypeDeclarationException( $"Schema Type Collection search, graph type mismatch, {concreteType.FriendlyName()}. Collections and KeyValuePair enumerable types " + diff --git a/src/graphql-aspnet/ServerExtensions/MultipartRequests/MultipartRequestServerExtension.cs b/src/graphql-aspnet/ServerExtensions/MultipartRequests/MultipartRequestServerExtension.cs index df3a0d471..02f1b1ed4 100644 --- a/src/graphql-aspnet/ServerExtensions/MultipartRequests/MultipartRequestServerExtension.cs +++ b/src/graphql-aspnet/ServerExtensions/MultipartRequests/MultipartRequestServerExtension.cs @@ -94,11 +94,7 @@ public virtual void Configure(SchemaOptions options) } // register a scalar that represents the file - var isRegisteredScalar = GraphQLProviders.ScalarProvider.IsScalar(typeof(FileUpload)); - if (!isRegisteredScalar) - { - GraphQLProviders.ScalarProvider.RegisterCustomScalar(typeof(FileUploadScalarGraphType)); - } + options.AddGraphType(); // register the config options for the schema var configurationServiceType = typeof(IMultipartRequestConfiguration<>).MakeGenericType(options.SchemaType); diff --git a/src/graphql-aspnet/ServerExtensions/MultipartRequests/Schema/FileUploadScalarGraphType.cs b/src/graphql-aspnet/ServerExtensions/MultipartRequests/Schema/FileUploadScalarGraphType.cs index c40df426c..52079ad0f 100644 --- a/src/graphql-aspnet/ServerExtensions/MultipartRequests/Schema/FileUploadScalarGraphType.cs +++ b/src/graphql-aspnet/ServerExtensions/MultipartRequests/Schema/FileUploadScalarGraphType.cs @@ -10,6 +10,7 @@ namespace GraphQL.AspNet.ServerExtensions.MultipartRequests.Schema { using System; + using System.Diagnostics; using GraphQL.AspNet.Common; using GraphQL.AspNet.Schemas.TypeSystem.Scalars; using GraphQL.AspNet.ServerExtensions.MultipartRequests.Model; @@ -19,6 +20,7 @@ namespace GraphQL.AspNet.ServerExtensions.MultipartRequests.Schema /// requirements of the multi-part request specification: /// . /// + [DebuggerDisplay("SCALAR: {Name}")] public class FileUploadScalarGraphType : ScalarGraphTypeBase { /// diff --git a/src/graphql-aspnet/graphql-aspnet.csproj b/src/graphql-aspnet/graphql-aspnet.csproj index 5260e555c..8683b4e38 100644 --- a/src/graphql-aspnet/graphql-aspnet.csproj +++ b/src/graphql-aspnet/graphql-aspnet.csproj @@ -12,4 +12,8 @@ + + + + \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Configuration/ConfigurationSetupTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Configuration/ConfigurationSetupTests.cs index f367ab0a0..0fb0419fe 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Configuration/ConfigurationSetupTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Configuration/ConfigurationSetupTests.cs @@ -37,8 +37,6 @@ public void AddSubscriptions_RegistrationChecks() using var restorePoint = new GraphQLGlobalSubscriptionRestorePoint(); // ensure the runtime is in a default state (just in case the statics got messed up) - GraphQLProviders.TemplateProvider = new DefaultTypeTemplateProvider(); - GraphQLProviders.GraphTypeMakerProvider = new DefaultGraphTypeMakerProvider(); GraphQLSchemaBuilderExtensions.Clear(); var serviceCollection = new ServiceCollection(); @@ -62,8 +60,6 @@ public void ExplicitDeclarationOfPerFieldAuthorizationFailsServerCreation() using var restorePoint = new GraphQLGlobalSubscriptionRestorePoint(); // ensure the runtime is in a default state (just in case the statics got messed up) - GraphQLProviders.TemplateProvider = new DefaultTypeTemplateProvider(); - GraphQLProviders.GraphTypeMakerProvider = new DefaultGraphTypeMakerProvider(); GraphQLSchemaBuilderExtensions.Clear(); var serviceCollection = new ServiceCollection(); @@ -88,8 +84,6 @@ public void ExplicitDeclarationOfPerRequestAuthorizationAddsServerSuccessfully() using var restorePoint = new GraphQLGlobalSubscriptionRestorePoint(); // ensure the runtime is in a default state (just in case the statics got messed up) - GraphQLProviders.TemplateProvider = new DefaultTypeTemplateProvider(); - GraphQLProviders.GraphTypeMakerProvider = new DefaultGraphTypeMakerProvider(); GraphQLSchemaBuilderExtensions.Clear(); var serviceCollection = new ServiceCollection(); @@ -108,10 +102,6 @@ public void NonExplicitDeclarationResultsInPerRequestAndAddsServerSuccessfully() { // setup the server with a hard declaration of nothing using var restorePoint = new GraphQLGlobalSubscriptionRestorePoint(); - - // ensure the runtime is in a default state (just in case the statics got messed up) - GraphQLProviders.TemplateProvider = new DefaultTypeTemplateProvider(); - GraphQLProviders.GraphTypeMakerProvider = new DefaultGraphTypeMakerProvider(); GraphQLSchemaBuilderExtensions.Clear(); SchemaOptions optionsSaved = null; @@ -134,8 +124,6 @@ public void AddSubscriptionServer_RegistrationChecks() using var restorePoint = new GraphQLGlobalSubscriptionRestorePoint(); // ensure the runtime is in a default state (just in case the statics got messed up) - GraphQLProviders.TemplateProvider = new DefaultTypeTemplateProvider(); - GraphQLProviders.GraphTypeMakerProvider = new DefaultGraphTypeMakerProvider(); GraphQLSchemaBuilderExtensions.Clear(); var serviceCollection = new ServiceCollection(); @@ -160,10 +148,6 @@ private void EnsureSubscriptionServerRegistrations(IServiceProvider sp) // ensure router is registered Assert.IsNotNull(sp.GetService(typeof(ISubscriptionEventRouter))); - - // ensure the template provider for the runtime is swapped - Assert.IsTrue(GraphQLProviders.TemplateProvider is SubscriptionEnabledTypeTemplateProvider); - Assert.IsTrue(GraphQLProviders.GraphTypeMakerProvider is SubscriptionEnabledGraphTypeMakerProvider); } [Test] @@ -172,8 +156,6 @@ public void AddSubscriptionPublishing_RegistrationChecks() using var restorePoint = new GraphQLGlobalSubscriptionRestorePoint(); // ensure the runtime is in a default state (just in case the statics got messed up) - GraphQLProviders.TemplateProvider = new DefaultTypeTemplateProvider(); - GraphQLProviders.GraphTypeMakerProvider = new DefaultGraphTypeMakerProvider(); var serviceCollection = new ServiceCollection(); @@ -208,10 +190,6 @@ private void EnsureSubscriptionPublishingRegistrations(ServiceProvider sp) Assert.IsNotNull(sp.GetService(typeof(ISubscriptionEventPublisher))); Assert.IsNotNull(sp.GetService(typeof(SubscriptionEventPublishingQueue))); Assert.IsNotNull(sp.GetService(typeof(IHostedService)) as SubscriptionPublicationService); - - // ensure the template provider for the runtime is swapped - Assert.IsTrue(GraphQLProviders.TemplateProvider is SubscriptionEnabledTypeTemplateProvider); - Assert.IsTrue(GraphQLProviders.GraphTypeMakerProvider is SubscriptionEnabledGraphTypeMakerProvider); } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/SubscriptionEnabledFieldFieldMakerTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/SubscriptionEnabledFieldFieldMakerTests.cs index b60996cfa..020099555 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/SubscriptionEnabledFieldFieldMakerTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/SubscriptionEnabledFieldFieldMakerTests.cs @@ -18,6 +18,7 @@ namespace GraphQL.AspNet.Tests.Engine using GraphQL.AspNet.Tests.Engine.TestData; using Moq; using NUnit.Framework; + using GraphQL.AspNet.Schemas.Generation; [TestFixture] public class SubscriptionEnabledFieldFieldMakerTests @@ -39,7 +40,8 @@ public void SubscriptionActionField_TransfersDirectives() var schema = new TestServerBuilder().Build().Schema; - var maker = new SubscriptionEnabledGraphFieldMaker(schema); + // var factory = SchemaEnabledGraphTypeFactory(); + var maker = new SubscriptionEnabledGraphFieldMaker(schema, null); var field = maker.CreateField(actionTemplate).Field; diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/GraphQLGlobalSubscriptionRestorePoint.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/GraphQLGlobalSubscriptionRestorePoint.cs index 5948bc2d3..4127f198d 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/GraphQLGlobalSubscriptionRestorePoint.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/GraphQLGlobalSubscriptionRestorePoint.cs @@ -9,6 +9,7 @@ namespace GraphQL.AspNet.Tests { + using System; using GraphQL.AspNet.SubscriptionServer; using GraphQL.AspNet.Tests.Framework; @@ -17,13 +18,12 @@ namespace GraphQL.AspNet.Tests /// that were present just before this object was created. Used in conjunction with NUnit to undo any changes to /// the global static providers in between tests. /// - public class GraphQLGlobalSubscriptionRestorePoint : GraphQLGlobalRestorePoint + public class GraphQLGlobalSubscriptionRestorePoint : IDisposable { private readonly int? _maxSubConnectedClient; private readonly int _maxSubConcurrentReceiver; public GraphQLGlobalSubscriptionRestorePoint() - : base() { _maxSubConnectedClient = GraphQLSubscriptionServerSettings.MaxConnectedClientCount; _maxSubConcurrentReceiver = GraphQLSubscriptionServerSettings.MaxConcurrentSubscriptionReceiverCount; @@ -32,15 +32,10 @@ public GraphQLGlobalSubscriptionRestorePoint() } /// - protected override void Dispose(bool disposing) + public void Dispose() { - base.Dispose(disposing); - - if (disposing) - { - GraphQLSubscriptionServerSettings.MaxConnectedClientCount = _maxSubConnectedClient; - GraphQLSubscriptionServerSettings.MaxConcurrentSubscriptionReceiverCount = _maxSubConcurrentReceiver; - } + GraphQLSubscriptionServerSettings.MaxConnectedClientCount = _maxSubConnectedClient; + GraphQLSubscriptionServerSettings.MaxConcurrentSubscriptionReceiverCount = _maxSubConcurrentReceiver; } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/GraphControllerTemplateTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/GraphControllerTemplateTests.cs index 883a39d0f..279709993 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/GraphControllerTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/GraphControllerTemplateTests.cs @@ -10,8 +10,6 @@ namespace GraphQL.AspNet.Tests.Internal.Templating { using System.Linq; - using GraphQL.AspNet.Engine; - using GraphQL.AspNet.Interfaces.Engine; using GraphQL.AspNet.Internal.TypeTemplates; using GraphQL.AspNet.Tests.Internal.Templating.ControllerTestData; using NUnit.Framework; @@ -19,12 +17,10 @@ namespace GraphQL.AspNet.Tests.Internal.Templating [TestFixture] public class GraphControllerTemplateTests { - public IGraphTypeTemplateProvider SubscriptionTemplateProvider => new SubscriptionEnabledTypeTemplateProvider(); - [Test] public void Parse_SingleSubscriptionRoute_CreatesCorrectActionTemplate() { - var template = this.SubscriptionTemplateProvider.ParseType() as GraphControllerTemplate; + var template = new SubscriptionGraphControllerTemplate(typeof(SimpleSubscriptionController)) as GraphControllerTemplate; Assert.IsNotNull(template); Assert.AreEqual(1, template.FieldTemplates.Count()); diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/GraphSchemaManagerTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/GraphSchemaManagerTests.cs deleted file mode 100644 index 0e07e48df..000000000 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/GraphSchemaManagerTests.cs +++ /dev/null @@ -1,81 +0,0 @@ -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - -namespace GraphQL.AspNet.Tests.Schemas -{ - using System; - using GraphQL.AspNet; - using GraphQL.AspNet.Engine; - using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Schemas; - using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Schemas.SchemaTestData; - using NUnit.Framework; - - [TestFixture] - public class GraphSchemaManagerTests - { - [Test] - public void AddSingleSubscriptionAction_AllDefaults_EnsureFieldStructure() - { - using var restorePoint = new GraphQLGlobalSubscriptionRestorePoint(); - - GraphQLProviders.TemplateProvider = new SubscriptionEnabledTypeTemplateProvider(); - var schema = new GraphSchema() as ISchema; - schema.SetNoAlterationConfiguration(); - schema.Configuration.DeclarationOptions.AllowedOperations.Add(GraphOperationType.Subscription); - - var manager = new GraphSchemaManager(schema); - manager.EnsureGraphType(); - - // query always exists - // subscription root was found via the method parsed - // mutation was not provided - Assert.IsTrue(schema.Operations.ContainsKey(GraphOperationType.Query)); - Assert.IsFalse(schema.Operations.ContainsKey(GraphOperationType.Mutation)); - Assert.IsTrue(schema.Operations.ContainsKey(GraphOperationType.Subscription)); - - // field for the controller exists - var topFieldName = nameof(SimpleMethodController).Replace(Constants.CommonSuffix.CONTROLLER_SUFFIX, string.Empty); - Assert.IsTrue(schema.Operations[GraphOperationType.Subscription].Fields.ContainsKey(topFieldName)); - - // ensure the field on the subscription operation is the right name (i.e. the controller name) - var topField = schema.Operations[GraphOperationType.Subscription][topFieldName]; - Assert.IsNotNull(topField); - - var type = schema.KnownTypes.FindGraphType(topField) as IObjectGraphType; - - var action = GraphQLTemplateHelper.CreateFieldTemplate(nameof(SimpleMethodController.TestActionMethod)); - - // ensure the action was put into the field collection of the controller operation - Assert.IsTrue(type.Fields.ContainsKey(action.Route.Name)); - } - - [Test] - public void AddASubscriptionAction_WithoutUpdatingTheConfiguration_ThrowsDeclarationException() - { - using var restorePoint = new GraphQLGlobalSubscriptionRestorePoint(); - - GraphQLProviders.TemplateProvider = new SubscriptionEnabledTypeTemplateProvider(); - var schema = new GraphSchema() as ISchema; - schema.SetNoAlterationConfiguration(); - - // do not tell the schema to allow the subscription operation type - // schema.SetSubscriptionAllowances(); - - // attempt to add a controller with a subscription - Assert.Throws(() => - { - var manager = new GraphSchemaManager(schema); - manager.EnsureGraphType(); - }); - } - } -} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionPublisherExtensionTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionPublisherExtensionTests.cs index 93b5614f5..379defc85 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionPublisherExtensionTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionPublisherExtensionTests.cs @@ -28,7 +28,6 @@ public void GeneralPropertyCheck() { using var restorePoint = new GraphQLGlobalSubscriptionRestorePoint(); - GraphQLProviders.TemplateProvider = null; var collection = new ServiceCollection(); var primaryOptions = new SchemaOptions(collection); @@ -38,7 +37,6 @@ public void GeneralPropertyCheck() extension.Configure(primaryOptions); Assert.IsTrue(primaryOptions.DeclarationOptions.AllowedOperations.Contains(GraphOperationType.Subscription)); - Assert.IsTrue(GraphQLProviders.TemplateProvider is SubscriptionEnabledTypeTemplateProvider); } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionReceiverExtensionTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionReceiverExtensionTests.cs index c540f659a..2e4eb9bc3 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionReceiverExtensionTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionReceiverExtensionTests.cs @@ -72,7 +72,6 @@ public void ServiceCollection_VerifyDefaultInjectedObjects() using var restorePoint = new GraphQLGlobalSubscriptionRestorePoint(); var serviceCollection = new ServiceCollection(); - GraphQLProviders.TemplateProvider = null; var primaryOptions = new SchemaOptions(serviceCollection); var subscriptionOptions = new SubscriptionServerOptions(); @@ -99,8 +98,6 @@ public void ServiceCollection_VerifyDefaultInjectedObjects() // legacy graphql-ws objects Assert.IsNotNull(primaryOptions.ServiceCollection.SingleOrDefault(x => x.ImplementationType == typeof(GraphqlWsLegacySubscriptionClientProxyFactory))); Assert.IsNotNull(primaryOptions.ServiceCollection.SingleOrDefault(x => x.ImplementationType == typeof(GraphqlWsLegacySubscriptionClientProxyFactoryAlternate))); - - Assert.IsTrue(GraphQLProviders.TemplateProvider is SubscriptionEnabledTypeTemplateProvider); } [Test] @@ -135,7 +132,6 @@ public void GeneralPropertyCheck() using var restorePoint = new GraphQLGlobalSubscriptionRestorePoint(); var serviceCollection = new ServiceCollection(); - GraphQLProviders.TemplateProvider = null; var primaryOptions = new SchemaOptions(serviceCollection); var subscriptionOptions = new SubscriptionServerOptions(); diff --git a/src/unit-tests/graphql-aspnet-testframework/GraphQLGlobalRestorePoint.cs b/src/unit-tests/graphql-aspnet-testframework/GraphQLGlobalRestorePoint.cs deleted file mode 100644 index 864e1545c..000000000 --- a/src/unit-tests/graphql-aspnet-testframework/GraphQLGlobalRestorePoint.cs +++ /dev/null @@ -1,81 +0,0 @@ -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - -namespace GraphQL.AspNet.Tests.Framework -{ - using System; - using GraphQL.AspNet; - using GraphQL.AspNet.Engine; - using GraphQL.AspNet.Interfaces.Configuration; - using GraphQL.AspNet.Interfaces.Engine; - using GraphQL.AspNet.Schemas; - using Microsoft.Extensions.DependencyInjection; - - /// - /// A marker to a point in time that, when disposed, will reset the the global settings to the values - /// that were present just before this object was created. Used in conjunction with NUnit to undo any changes to - /// the global static providers in between tests. - /// - /// - /// If your test suite is configured to execute more than 1 test concurrently within the - /// same app space this could cause unexpected results. - /// - public class GraphQLGlobalRestorePoint : IDisposable - { - private readonly IGraphTypeTemplateProvider _templateProvider; - private readonly IScalarGraphTypeProvider _scalarTypeProvider; - private readonly IGraphTypeMakerProvider _makerProvider; - private readonly ServiceLifetime _controllerServiceLifetime; - - /// - /// Initializes a new instance of the class. - /// - /// if set to true all providers will - /// be immediately reset to their default implementation until this restore point is disposed. - public GraphQLGlobalRestorePoint(bool resetAllProviders = false) - { - _templateProvider = GraphQLProviders.TemplateProvider; - _scalarTypeProvider = GraphQLProviders.ScalarProvider; - _makerProvider = GraphQLProviders.GraphTypeMakerProvider; - - _controllerServiceLifetime = GraphQLServerSettings.ControllerServiceLifeTime; - - if (resetAllProviders) - { - GraphQLProviders.TemplateProvider = new DefaultTypeTemplateProvider(); - GraphQLProviders.ScalarProvider = new DefaultScalarGraphTypeProvider(); - GraphQLProviders.GraphTypeMakerProvider = new DefaultGraphTypeMakerProvider(); - } - } - - /// - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// - public void Dispose() - { - this.Dispose(true); - } - - /// - /// Releases unmanaged and - optionally - managed resources. - /// - /// true to release both managed and unmanaged resources; false to release only unmanaged resources. - protected virtual void Dispose(bool disposing) - { - if (disposing) - { - GraphQLProviders.TemplateProvider = _templateProvider; - GraphQLProviders.ScalarProvider = _scalarTypeProvider; - GraphQLProviders.GraphTypeMakerProvider = _makerProvider; - - GraphQLServerSettings.ControllerServiceLifeTime = _controllerServiceLifetime; - } - } - } -} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-testframework/GraphQLTemplateHelper.cs b/src/unit-tests/graphql-aspnet-testframework/GraphQLTemplateHelper.cs index d00231283..d14a8e0c4 100644 --- a/src/unit-tests/graphql-aspnet-testframework/GraphQLTemplateHelper.cs +++ b/src/unit-tests/graphql-aspnet-testframework/GraphQLTemplateHelper.cs @@ -11,11 +11,17 @@ namespace GraphQL.AspNet.Tests.Framework { using System; using System.Linq; + using System.Runtime.CompilerServices; + using GraphQL.AspNet.Common; using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Directives; using GraphQL.AspNet.Interfaces.Internal; + using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Schemas.Generation.TypeMakers; using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Schemas.TypeSystem.Scalars; using GraphQL.AspNet.Tests.Framework.PipelineContextBuilders; /// @@ -31,8 +37,7 @@ public static class GraphQLTemplateHelper public static IGraphControllerTemplate CreateControllerTemplate() where TController : GraphController { - GraphQLProviders.TemplateProvider.Clear(); - return GraphQLProviders.TemplateProvider.ParseType() as IGraphControllerTemplate; + return CreateGraphTypeTemplate(TypeKind.CONTROLLER) as IGraphControllerTemplate; } /// @@ -62,7 +67,7 @@ public static IGraphFieldTemplate CreateActionMethodTemplate(string /// IGraphTypeFieldTemplate. public static IGraphFieldTemplate CreateFieldTemplate(string fieldOrMethodName) { - var template = CreateGraphTypeTemplate() as IGraphTypeFieldTemplateContainer; + var template = CreateGraphTypeTemplate(TypeKind.OBJECT) as IGraphTypeFieldTemplateContainer; // bit of a hack but it solves a lot of schema configuration differences that // can occur when setting up a test do to references occuring out of process @@ -83,11 +88,51 @@ public static IGraphFieldTemplate CreateFieldTemplate(string fieldOrMetho /// /// The graph type to template. /// The kind. + /// if set to true the template will be parsed and validated before + /// being returned. Exceptions may be thrown if it does not parse correctly. /// IGraphItemTemplate. - public static ISchemaItemTemplate CreateGraphTypeTemplate(TypeKind? kind = null) + public static IGraphTypeTemplate CreateGraphTypeTemplate(TypeKind? kind = null, bool autoParse = true) { - GraphQLProviders.TemplateProvider.CacheTemplates = false; - return GraphQLProviders.TemplateProvider.ParseType(kind); + return CreateGraphTypeTemplate(typeof(TType), kind, autoParse); + } + + /// + /// Generates a schema template for a give type and kind combination. + /// + /// The graph type to template. + /// The kind. + /// if set to true the template will be parsed and validated before + /// being returned. Exceptions may be thrown if it does not parse correctly. + /// IGraphItemTemplate. + public static IGraphTypeTemplate CreateGraphTypeTemplate(Type objectType, TypeKind? kind = null, bool autoParse = true) + { + objectType = GlobalScalars.FindBuiltInScalarType(objectType) ?? objectType; + + IGraphTypeTemplate template; + if (Validation.IsCastable(objectType)) + template = new ScalarGraphTypeTemplate(objectType); + else if (Validation.IsCastable(objectType)) + template = new UnionGraphTypeTemplate(objectType); + else if (objectType.IsEnum) + template = new EnumGraphTypeTemplate(objectType); + else if (objectType.IsInterface) + template = new InterfaceGraphTypeTemplate(objectType); + else if (Validation.IsCastable(objectType)) + template = new GraphDirectiveTemplate(objectType); + else if (Validation.IsCastable(objectType)) + template = new GraphControllerTemplate(objectType); + else if (kind.HasValue && kind.Value == TypeKind.INPUT_OBJECT) + template = new InputObjectGraphTypeTemplate(objectType); + else + template = new ObjectGraphTypeTemplate(objectType); + + if (autoParse) + { + template.Parse(); + template.ValidateOrThrow(); + } + + return template; } /// diff --git a/src/unit-tests/graphql-aspnet-testframework/TestServer.cs b/src/unit-tests/graphql-aspnet-testframework/TestServer.cs index 57e7ed9b8..6ca9167da 100644 --- a/src/unit-tests/graphql-aspnet-testframework/TestServer.cs +++ b/src/unit-tests/graphql-aspnet-testframework/TestServer.cs @@ -38,6 +38,9 @@ namespace GraphQL.AspNet.Tests.Framework using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Interfaces.Security; using GraphQL.AspNet.Interfaces.Web; + using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Schemas.Generation; + using GraphQL.AspNet.Schemas.Generation.TypeMakers; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Tests.Framework.PipelineContextBuilders; using Microsoft.AspNetCore.Http; @@ -177,8 +180,12 @@ public virtual Task CreateQueryPlan(string queryText, strin /// GraphTypeCreationResult. public virtual GraphTypeCreationResult CreateGraphType(Type concreteType, TypeKind kind) { - var maker = GraphQLProviders.GraphTypeMakerProvider.CreateTypeMaker(this.Schema, kind); - return maker.CreateGraphType(concreteType); + var factory = new DefaultGraphQLTypeMakerFactory(); + factory.Initialize(this.Schema); + var maker = factory.CreateTypeMaker(concreteType, kind); + + var template = factory.MakeTemplate(concreteType); + return maker.CreateGraphType(template); } /// @@ -193,7 +200,10 @@ public virtual FieldContextBuilder CreateGraphTypeFieldContextBuilder(actionName); - var fieldMaker = new GraphFieldMaker(this.Schema); + + var factory = new DefaultGraphQLTypeMakerFactory(); + factory.Initialize(this.Schema); + var fieldMaker = new GraphFieldMaker(this.Schema, factory); var fieldResult = fieldMaker.CreateField(template); var builder = new FieldContextBuilder( @@ -314,7 +324,7 @@ public virtual GraphFieldExecutionContext CreateFieldExecutionContext( /// generic will be used if not supplied. /// The type kind to resolve the field as (only necessary for input object types). /// FieldContextBuilder. - public virtual FieldContextBuilder CreateGraphTypeFieldContextBuilder(string fieldName, object sourceData, TypeKind? typeKind = null) + public virtual FieldContextBuilder CreateGraphTypeFieldContextBuilder(string fieldName, object sourceData, TypeKind typeKind) { IGraphType graphType = this.Schema.KnownTypes.FindGraphType(typeof(TType)); @@ -364,7 +374,7 @@ public virtual FieldContextBuilder CreateGraphTypeFieldContextBuilder(str /// Name of the field. /// The type kind to resolve the field as (only necessary for input object types). /// IGraphMethod. - public virtual IGraphFieldResolverMetaData CreateResolverMetadata(string fieldName, TypeKind? typeKind = null) + public virtual IGraphFieldResolverMetaData CreateResolverMetadata(string fieldName, TypeKind typeKind) { var template = GraphQLTemplateHelper.CreateGraphTypeTemplate(typeKind); var fieldContainer = template as IGraphTypeFieldTemplateContainer; diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/ConfigurationSetupTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/ConfigurationSetupTests.cs index 5ae86eeea..d63a6531e 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/ConfigurationSetupTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/ConfigurationSetupTests.cs @@ -34,18 +34,10 @@ namespace GraphQL.AspNet.Tests.Configuration [TestFixture] public class ConfigurationSetupTests { - [SetUp] - public void Setup() - { - GraphQLProviders.TemplateProvider.CacheTemplates = true; - } - [TearDown] public void TearDown() { GraphQLSchemaBuilderExtensions.Clear(); - GraphQLProviders.TemplateProvider.Clear(); - GraphQLProviders.TemplateProvider.CacheTemplates = false; } [Test] @@ -71,8 +63,6 @@ public void AddGraphQL_AddingDefaultSchema_WithOneController_GeneratesAllDefault Assert.IsNotNull(sp.GetService(typeof(IQueryExecutionPlanGenerator)) as DefaultQueryExecutionPlanGenerator); Assert.IsNotNull(sp.GetService(typeof(IQueryResponseWriter)) as DefaultQueryResponseWriter); Assert.IsNotNull(sp.GetService(typeof(IQueryExecutionMetricsFactory)) as DefaultQueryExecutionMetricsFactory); - - GraphQLProviders.TemplateProvider.Clear(); } [Test] @@ -85,25 +75,6 @@ public void AddGraphQL_AttemptingToAddDefautSchemaAsTyped_ThrowsException() { serviceCollection.AddGraphQL(); }); - - GraphQLProviders.TemplateProvider.Clear(); - } - - [Test] - public void UseGraphQL_PerformsPreparseAndSetupRoutines() - { - var serviceCollection = new ServiceCollection(); - serviceCollection.AddGraphQL(options => - { - options.AddType(); - }); - - var sp = serviceCollection.BuildServiceProvider(); - sp.UseGraphQL(); - - // FanController, FanItem, FanSpeed, - // skipDirective, includeDirective, deprecatedDirective, specifiedByDirective - Assert.AreEqual(7, GraphQLProviders.TemplateProvider.Count); } [Test] @@ -118,11 +89,6 @@ public void SchemaBuilder_AddAssembly_AddGraphAssembly() var provider = serviceCollection.BuildServiceProvider(); provider.UseGraphQL(); - // virtualResolvedObject, candleController, candle, waxType, - // customerController, customer, - // skipDirective, includeDirective, deprecatedDirective, specifiedByDirective - Assert.AreEqual(10, GraphQLProviders.TemplateProvider.Count); - var sp = serviceCollection.BuildServiceProvider(); sp.UseGraphQL(); @@ -152,11 +118,6 @@ public void SchemaBuilder_AddSchemaAssembly_AllControllersAddedToType() var provider = serviceCollection.BuildServiceProvider(); provider.UseGraphQL(); - // virtualResolvedObject, candleController, candle, waxType, - // customerController, customer, - // skipDirective, includeDirective, deprecatedDirective, specifiedByDirective - Assert.AreEqual(10, GraphQLProviders.TemplateProvider.Count); - var sp = serviceCollection.BuildServiceProvider(); var schema = sp.GetService(typeof(CandleSchema)) as ISchema; Assert.IsNotNull(schema); @@ -184,11 +145,6 @@ public void SchemaBuilder_AddGraphController_AppearsInSchema() var provider = serviceCollection.BuildServiceProvider(); provider.UseGraphQL(); - // virtualResolvedObject, candleController, candle, - // waxType, - // skipDirective, includeDirective, deprecatedDirective, specifiedByDirective - Assert.AreEqual(8, GraphQLProviders.TemplateProvider.Count); - var sp = serviceCollection.BuildServiceProvider(); var schema = sp.GetService(typeof(GraphSchema)) as ISchema; Assert.IsNotNull(schema); @@ -219,7 +175,6 @@ public void SchemaBuilder_AddGraphDirective_AppearsInSchema() // sample1Directive, // skipDirective, includeDirective, deprecatedDirective, specifiedByDirective - Assert.AreEqual(5, GraphQLProviders.TemplateProvider.Count); var schema = provider.GetService(typeof(GraphSchema)) as GraphSchema; Assert.IsNotNull(schema); @@ -302,8 +257,6 @@ public async Task SchemaBuilder_AddMiddleware_AsTypeRegistration_AppearsInPipeli [Test] public void ChangingGlobalConfig_ChangesHowControllersAreRegistered() { - using var restorePoint = new GraphQLGlobalRestorePoint(); - // make sure the original setting is not what we hope to change it to // otherwise the test is inconclusive if (GraphQLServerSettings.ControllerServiceLifeTime == ServiceLifetime.Singleton) diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/DirectiveApplicatorTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/DirectiveApplicatorTests.cs index 0fa15f78d..2db6aa678 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/DirectiveApplicatorTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/DirectiveApplicatorTests.cs @@ -42,12 +42,12 @@ object[] CreateArgs(ISchemaItem item) .Build() .Schema; - var applicator = new DirectiveBindingConfiguration("testDirective"); + var applicator = new DirectiveBindingSchemaExtension("testDirective"); applicator .WithArguments(CreateArgs) .ToItems(x => x is IGraphField); - ((ISchemaConfigurationExtension)applicator).Configure(schema); + ((ISchemaExtension)applicator).Extend(schema); for (var i = 0; i < matchedSchemaItems.Count; i++) { @@ -79,14 +79,14 @@ object[] CreateArgsOther(ISchemaItem item) .Build() .Schema; - var applicator = new DirectiveBindingConfiguration("testDirective"); + var applicator = new DirectiveBindingSchemaExtension("testDirective"); applicator .WithArguments(CreateArgs) .WithArguments(new object[0]) .WithArguments(CreateArgsOther) .ToItems(x => x is IGraphField); - ((ISchemaConfigurationExtension)applicator).Configure(schema); + ((ISchemaExtension)applicator).Extend(schema); // count would be greater than zero fi and only if the last // supplied function was executed and any fields were found @@ -103,12 +103,12 @@ public void ConstantSuppliedArgumentsAreUsed_ForAllMatchedItems() .Build() .Schema; - var applicator = new DirectiveBindingConfiguration("testDirective"); + var applicator = new DirectiveBindingSchemaExtension("testDirective"); applicator .WithArguments(argSet) .ToItems(x => x is IGraphField); - ((ISchemaConfigurationExtension)applicator).Configure(schema); + ((ISchemaExtension)applicator).Extend(schema); foreach (var item in schema.AllSchemaItems()) { diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/SchemaOptionsCustomLifetimeRegistrationTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/SchemaOptionsCustomLifetimeRegistrationTests.cs index a32549372..f6c76c8ae 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/SchemaOptionsCustomLifetimeRegistrationTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/SchemaOptionsCustomLifetimeRegistrationTests.cs @@ -22,8 +22,6 @@ public class SchemaOptionsCustomLifetimeRegistrationTests [Test] public void DirectiveAddedWithNonDefaultLifeTime_IsRegisteredAsSuch() { - using var restorePoint = new GraphQLGlobalRestorePoint(); - GraphQLServerSettings.ControllerServiceLifeTime = ServiceLifetime.Transient; var collection = new ServiceCollection(); @@ -41,8 +39,6 @@ public void DirectiveAddedWithNonDefaultLifeTime_IsRegisteredAsSuch() [Test] public void ControllerAddedWithNonDefaultLifeTime_IsRegisteredAsSuch() { - using var restorePoint = new GraphQLGlobalRestorePoint(); - GraphQLServerSettings.ControllerServiceLifeTime = ServiceLifetime.Transient; var collection = new ServiceCollection(); diff --git a/src/unit-tests/graphql-aspnet-tests/Controllers/ActionResults/ActionResultTests.cs b/src/unit-tests/graphql-aspnet-tests/Controllers/ActionResults/ActionResultTests.cs index c4f6f0ab3..26308242e 100644 --- a/src/unit-tests/graphql-aspnet-tests/Controllers/ActionResults/ActionResultTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Controllers/ActionResults/ActionResultTests.cs @@ -19,6 +19,8 @@ namespace GraphQL.AspNet.Tests.Controllers.ActionResults using GraphQL.AspNet.Execution.Contexts; using GraphQL.AspNet.Interfaces.Execution; using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Schemas.Generation; + using GraphQL.AspNet.Schemas.Generation.TypeMakers; using GraphQL.AspNet.Tests.Controllers.ActionResults.ActuionResultTestData; using GraphQL.AspNet.Tests.Framework; using Moq; @@ -46,6 +48,7 @@ public async Task BadRequest_WithModelDictionary_RendersMessageOnResponse() var argTemplate = methodTemplate.Arguments[0]; var mockedOwner = new Mock(); + var fieldArg = new GraphArgumentMaker(server.Schema).CreateArgument(mockedOwner.Object, argTemplate).Argument; // name is marked required, will fail diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultScalarTypeProviderTestData/ScalarTestBase.cs b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultScalarTypeProviderTestData/ScalarTestBase.cs index 38625b4f9..c6ac4c6df 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultScalarTypeProviderTestData/ScalarTestBase.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultScalarTypeProviderTestData/ScalarTestBase.cs @@ -38,6 +38,14 @@ protected ScalarTestBase() this.SourceResolver = new Mock().Object; } + public virtual IScalarGraphType Clone(string newName) + { + newName = Validation.ThrowIfNullWhiteSpaceOrReturn(newName, nameof(newName)); + var newInstance = GlobalScalars.CreateScalarInstanceOrThrow(this.GetType()) as ScalarTestBase; + newInstance.Name = newName; + return newInstance; + } + public TypeCollection OtherKnownTypes { get; set; } public ScalarValueType ValueType { get; set; } diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultScalarTypeProviderTests.cs b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultScalarTypeProviderTests.cs deleted file mode 100644 index 3981e9836..000000000 --- a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultScalarTypeProviderTests.cs +++ /dev/null @@ -1,176 +0,0 @@ -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - -namespace GraphQL.AspNet.Tests.Engine -{ - using System; - using System.Collections.Generic; - using GraphQL.AspNet; - using GraphQL.AspNet.Engine; - using GraphQL.AspNet.Execution.Exceptions; - using GraphQL.AspNet.Tests.Engine.DefaultScalarTypeProviderTestData; - using NUnit.Framework; - - [TestFixture] - public class DefaultScalarTypeProviderTests - { - [Test] - public void EachInvocationOfaScalarIsANewInstance() - { - var provider = new DefaultScalarGraphTypeProvider(); - var instances = new List(); - - for (var i = 0; i < 3; i++) - { - var scalar = provider.CreateScalar(typeof(int)); - instances.Add(scalar); - } - - Assert.AreEqual(3, instances.Count); - - Assert.IsFalse(ReferenceEquals(instances[0], instances[1])); - Assert.IsFalse(ReferenceEquals(instances[0], instances[2])); - Assert.IsFalse(ReferenceEquals(instances[1], instances[2])); - } - - [Test] - public void AllRegisteredTypesProduceSameScalar() - { - var provider = new DefaultScalarGraphTypeProvider(); - - var primary = provider.CreateScalar(typeof(int)); - var secondary = provider.CreateScalar(typeof(int?)); - - Assert.IsFalse(ReferenceEquals(primary, secondary)); - Assert.AreEqual(primary.Name, secondary.Name); - } - - [Test] - public void IsLeaf_NullType_IsFalse() - { - var provider = new DefaultScalarGraphTypeProvider(); - - var result = provider.IsLeaf(null); - Assert.IsFalse(result); - } - - [Test] - public void RegisterCustomScalar_ValidScalarIsRegistered() - { - var provider = new DefaultScalarGraphTypeProvider(); - - provider.RegisterCustomScalar(typeof(ScalarFullyValid)); - - var instance = provider.CreateScalar(typeof(ScalarDataType)); - - Assert.IsNotNull(instance); - Assert.AreEqual(typeof(ScalarDataType), instance.ObjectType); - } - - [Test] - public void AllDefaultScalars_CanBeInstantiatedAndSearched() - { - var provider = new DefaultScalarGraphTypeProvider(); - - foreach (var instanceType in provider.ConcreteTypes) - { - var instanceFromConcrete = provider.CreateScalar(instanceType); - Assert.IsNotNull(instanceFromConcrete, $"Could not create scalar from type '{instanceType.Name}'"); - - var instanceFromName = provider.CreateScalar(instanceFromConcrete.Name); - Assert.IsNotNull(instanceFromName, $"Could not create scalar from name '{instanceFromConcrete.Name}'"); - } - } - - [Test] - public void CreateScalar_ForUnRegisteredScalarName_ReturnsNull() - { - var provider = new DefaultScalarGraphTypeProvider(); - var instance = provider.CreateScalar("NotAScalarName"); - - Assert.IsNull(instance); - } - - [Test] - public void CreateScalar_ForUnRegisteredScalarType_ReturnsNull() - { - var provider = new DefaultScalarGraphTypeProvider(); - var instance = provider.CreateScalar(typeof(DefaultScalarTypeProviderTests)); - - Assert.IsNull(instance); - } - - [Test] - public void RetrieveConcreteType_ByScalarName_ReturnsScalar() - { - var provider = new DefaultScalarGraphTypeProvider(); - var type = provider.RetrieveConcreteType(Constants.ScalarNames.INT); - - Assert.AreEqual(typeof(int), type); - } - - [Test] - public void RetrieveConcreteType_ByScalarName_ReturnsNull() - { - var provider = new DefaultScalarGraphTypeProvider(); - var type = provider.RetrieveConcreteType("not a scalar name"); - - Assert.IsNull(type); - } - - [Test] - public void RetrieveScalarName_ByConcreteType_ReturnsnUll() - { - var provider = new DefaultScalarGraphTypeProvider(); - var type = provider.RetrieveScalarName(typeof(DefaultScalarTypeProviderTests)); - - Assert.IsNull(type); - } - - [Test] - public void RetrieveScalarName_ByConcreteType() - { - var provider = new DefaultScalarGraphTypeProvider(); - var name = provider.RetrieveScalarName(typeof(int)); - - Assert.AreEqual(Constants.ScalarNames.INT, name); - } - - [TestCase(null, typeof(ArgumentNullException))] - [TestCase(typeof(ScalarTypeDoesNotImplementScalarInterface), typeof(GraphTypeDeclarationException))] - [TestCase(typeof(ScalarNoDefaultConstructor), typeof(GraphTypeDeclarationException))] - [TestCase(typeof(ScalarInvalidGraphName), typeof(GraphTypeDeclarationException))] - [TestCase(typeof(ScalarNoGraphName), typeof(GraphTypeDeclarationException))] - [TestCase(typeof(ScalarInUseGraphName), typeof(GraphTypeDeclarationException))] - [TestCase(typeof(ScalarNotCorrectTypeKind), typeof(GraphTypeDeclarationException))] - [TestCase(typeof(ScalarNoPrimaryObjectType), typeof(GraphTypeDeclarationException))] - [TestCase(typeof(ScalarNoSourceResolver), typeof(GraphTypeDeclarationException))] - [TestCase(typeof(ScalarUnknownValueType), typeof(GraphTypeDeclarationException))] - [TestCase(typeof(ScalarNullOtherTypeCollection), typeof(GraphTypeDeclarationException))] - [TestCase(typeof(ScalarNullAppliedDirectives), typeof(GraphTypeDeclarationException))] - [TestCase(typeof(ScalarIncorrectAppliedDirectivesParent), typeof(GraphTypeDeclarationException))] - [TestCase(typeof(ScalarImplementationTypeInUse), typeof(GraphTypeDeclarationException))] - [TestCase(typeof(ScalarOtherTypeInUse), typeof(GraphTypeDeclarationException))] - public void RegisterCustomScalar_ExpectedDeclarationException(Type scalarType, Type expectedExceptionType) - { - var provider = new DefaultScalarGraphTypeProvider(); - try - { - provider.RegisterCustomScalar(scalarType); - } - catch (Exception ex) - { - Assert.IsTrue(ex.GetType() == expectedExceptionType, $"Expected exception type not thrown. Tested Type '{scalarType?.Name ?? "-null-"}'"); - return; - } - - Assert.Fail($"Excepted an exception of type '{expectedExceptionType.Name}' to be thrown."); - } - } -} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/CustomController.cs b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/CustomController.cs new file mode 100644 index 000000000..d70cb2252 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/CustomController.cs @@ -0,0 +1,23 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Engine.DefaultSchemaFactoryTestData +{ + using GraphQL.AspNet.Attributes; + using GraphQL.AspNet.Controllers; + + public class CustomController : GraphController + { + [Query] + public int MethodField(int id) + { + return 0; + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/CustomDirective.cs b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/CustomDirective.cs new file mode 100644 index 000000000..ee5011219 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/CustomDirective.cs @@ -0,0 +1,25 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Engine.DefaultSchemaFactoryTestData +{ + using GraphQL.AspNet.Attributes; + using GraphQL.AspNet.Directives; + using GraphQL.AspNet.Interfaces.Controllers; + using GraphQL.AspNet.Schemas.TypeSystem; + + public class CustomDirective : GraphDirective + { + [DirectiveLocations(DirectiveLocation.FIELD)] + public IGraphActionResult Execute(int arg) + { + return this.Ok(); + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/CustomEnum.cs b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/CustomEnum.cs new file mode 100644 index 000000000..3b20c81a8 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/CustomEnum.cs @@ -0,0 +1,17 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Engine.DefaultSchemaFactoryTestData +{ + public enum CustomEnum + { + Value1, + Value2, + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/CustomObjectWithCustomScalarArgument.cs b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/CustomObjectWithCustomScalarArgument.cs new file mode 100644 index 000000000..4f3811fb6 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/CustomObjectWithCustomScalarArgument.cs @@ -0,0 +1,23 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Engine.DefaultSchemaFactoryTestData +{ + using GraphQL.AspNet.Attributes; + using GraphQL.AspNet.Tests.Framework.CommonHelpers; + + public class CustomObjectWithCustomScalarArgument + { + [GraphField] + public int FieldWithScalarArg(TwoPropertyObject obj) + { + return 0; + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/CustomObjectWithCustomScalarField.cs b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/CustomObjectWithCustomScalarField.cs new file mode 100644 index 000000000..258efa429 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/CustomObjectWithCustomScalarField.cs @@ -0,0 +1,23 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Engine.DefaultSchemaFactoryTestData +{ + using GraphQL.AspNet.Attributes; + using GraphQL.AspNet.Tests.Framework.CommonHelpers; + + public class CustomObjectWithCustomScalarField + { + [GraphField] + public TwoPropertyObject FieldWithScalarReturnValue(int arg) + { + return null; + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/CustomObjectWithFieldWithArg.cs b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/CustomObjectWithFieldWithArg.cs new file mode 100644 index 000000000..20d21c68a --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/CustomObjectWithFieldWithArg.cs @@ -0,0 +1,22 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Engine.DefaultSchemaFactoryTestData +{ + using GraphQL.AspNet.Attributes; + + public class CustomObjectWithFieldWithArg + { + [GraphField] + public int MethodWithArg(decimal? arg) + { + return 0; + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/TwoPropertyObjectAsScalar.cs b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/TwoPropertyObjectAsScalar.cs new file mode 100644 index 000000000..c9a31c57e --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/TwoPropertyObjectAsScalar.cs @@ -0,0 +1,34 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Engine.DefaultSchemaFactoryTestData +{ + using System; + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Schemas.TypeSystem.Scalars; + using GraphQL.AspNet.Tests.Framework.CommonHelpers; + + public class TwoPropertyObjectAsScalar : ScalarGraphTypeBase + { + public TwoPropertyObjectAsScalar() + : base(nameof(TwoPropertyObjectAsScalar), typeof(TwoPropertyObject)) + { + this.OtherKnownTypes = TypeCollection.Empty; + } + + public override object Resolve(ReadOnlySpan data) + { + return null; + } + + public override TypeCollection OtherKnownTypes { get; } + + public override ScalarValueType ValueType => ScalarValueType.String; + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTests.cs b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTests.cs new file mode 100644 index 000000000..e893a801b --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTests.cs @@ -0,0 +1,454 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Engine +{ + using System; + using System.Linq; + using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Engine; + using GraphQL.AspNet.Interfaces.Engine; + using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Schemas.Generation; + using GraphQL.AspNet.Schemas.Structural; + using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Tests.Engine.DefaultSchemaFactoryTestData; + using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Framework.Interfaces; + using Microsoft.Extensions.DependencyInjection; + using NUnit.Framework; + + [TestFixture] + public class DefaultSchemaFactoryTests + { + [Test] + public void OneScalarType_GeneratesCorrectly() + { + var collection = new ServiceCollection(); + collection.AddTransient, DefaultGraphQLTypeMakerFactory>(); + + var factory = new DefaultGraphQLSchemaFactory(includeBuiltInDirectives: false); + var options = new SchemaOptions(collection); + options.DeclarationOptions.DisableIntrospection = true; + + var provider = collection.BuildServiceProvider(); + + var scope = provider.CreateScope(); + var config = options.CreateConfiguration(); + + var instance = factory.CreateInstance( + scope, + config, + new SchemaTypeToRegister[] + { + new SchemaTypeToRegister(typeof(int)), + }); + + Assert.IsNotNull(instance); + Assert.AreEqual(3, instance.KnownTypes.Count); + Assert.IsTrue(instance.KnownTypes.Contains(typeof(int))); + Assert.IsTrue(instance.KnownTypes.Contains(typeof(string))); + Assert.IsTrue(instance.Operations.ContainsKey(GraphOperationType.Query)); + + var graphType = instance.KnownTypes.FindGraphType(typeof(int)); + Assert.IsNotNull(graphType); + Assert.IsTrue(graphType is IScalarGraphType); + Assert.AreEqual(typeof(int), ((IScalarGraphType)graphType).ObjectType); + } + + [Test] + public void CustomScalar_AllAssociatedTypesAreRegistered() + { + var collection = new ServiceCollection(); + collection.AddTransient, DefaultGraphQLTypeMakerFactory>(); + + var factory = new DefaultGraphQLSchemaFactory(includeBuiltInDirectives: false); + var options = new SchemaOptions(collection); + options.DeclarationOptions.DisableIntrospection = true; + + var provider = collection.BuildServiceProvider(); + + var scope = provider.CreateScope(); + var config = options.CreateConfiguration(); + + var instance = factory.CreateInstance( + scope, + config, + new SchemaTypeToRegister[] + { + new SchemaTypeToRegister(typeof(TwoPropertyObjectAsScalar)), + }); + + Assert.IsNotNull(instance); + Assert.AreEqual(3, instance.KnownTypes.Count); + Assert.IsNotNull(instance.KnownTypes.SingleOrDefault(x => x.Name == nameof(TwoPropertyObjectAsScalar))); + Assert.IsNotNull(instance.KnownTypes.SingleOrDefault(x => x.Name == Constants.ScalarNames.STRING)); + Assert.IsNotNull(instance.KnownTypes.SingleOrDefault(x => x.Name == Constants.ReservedNames.QUERY_TYPE_NAME)); + + // should find the custom scalar + var customScalar = instance.KnownTypes.FindGraphType(typeof(TwoPropertyObject)) as IScalarGraphType; + Assert.IsNotNull(customScalar); + Assert.AreEqual(typeof(TwoPropertyObject), customScalar.ObjectType); + } + + [Test] + public void OneEnum_AllAssociatedTypesAreRegistered() + { + var collection = new ServiceCollection(); + collection.AddTransient, DefaultGraphQLTypeMakerFactory>(); + + var factory = new DefaultGraphQLSchemaFactory(includeBuiltInDirectives: false); + var options = new SchemaOptions(collection); + options.DeclarationOptions.DisableIntrospection = true; + + var provider = collection.BuildServiceProvider(); + + var scope = provider.CreateScope(); + var config = options.CreateConfiguration(); + + var instance = factory.CreateInstance( + scope, + config, + new SchemaTypeToRegister[] + { + new SchemaTypeToRegister(typeof(CustomEnum)), + }); + + Assert.IsNotNull(instance); + Assert.AreEqual(3, instance.KnownTypes.Count); + Assert.IsNotNull(instance.KnownTypes.SingleOrDefault(x => x.Name == nameof(CustomEnum))); + Assert.IsNotNull(instance.KnownTypes.SingleOrDefault(x => x.Name == Constants.ScalarNames.STRING)); + Assert.IsNotNull(instance.KnownTypes.SingleOrDefault(x => x.Name == Constants.ReservedNames.QUERY_TYPE_NAME)); + + // should find the custom scalar + var customEnum = instance.KnownTypes.FindGraphType(typeof(CustomEnum)) as IEnumGraphType; + Assert.IsNotNull(customEnum); + Assert.AreEqual(typeof(CustomEnum), customEnum.ObjectType); + + Assert.AreEqual(2, customEnum.Values.Count); + Assert.IsNotNull(customEnum.Values.FindByEnumValue(CustomEnum.Value1)); + Assert.IsNotNull(customEnum.Values.FindByEnumValue(CustomEnum.Value2)); + } + + [Test] + public void OneObjectType_NoArgumentsOnFields_GeneratesCorrectly() + { + var collection = new ServiceCollection(); + collection.AddTransient, DefaultGraphQLTypeMakerFactory>(); + + var factory = new DefaultGraphQLSchemaFactory(includeBuiltInDirectives: false); + var options = new SchemaOptions(collection); + options.DeclarationOptions.DisableIntrospection = true; + + var provider = collection.BuildServiceProvider(); + + var scope = provider.CreateScope(); + var config = options.CreateConfiguration(); + + var instance = factory.CreateInstance( + scope, + config, + new SchemaTypeToRegister[] + { + new SchemaTypeToRegister(typeof(TwoPropertyObjectV2)), + }); + + Assert.IsNotNull(instance); + + Assert.AreEqual(5, instance.KnownTypes.Count); + Assert.IsTrue(instance.KnownTypes.Contains(typeof(DateTime))); // field on v2 + Assert.IsTrue(instance.KnownTypes.Contains(typeof(float))); // field on v2 + Assert.IsTrue(instance.KnownTypes.Contains(typeof(TwoPropertyObjectV2))); // the object itself + Assert.IsNotNull(instance.KnownTypes.SingleOrDefault(x => x.Name == Constants.ScalarNames.STRING)); // required for __typename + Assert.IsNotNull(instance.KnownTypes.SingleOrDefault(x => x.Name == Constants.ReservedNames.QUERY_TYPE_NAME)); + + var graphType = instance.KnownTypes.FindGraphType(typeof(TwoPropertyObjectV2)); + Assert.IsNotNull(graphType); + Assert.IsTrue(graphType is IObjectGraphType); + Assert.AreEqual(typeof(TwoPropertyObjectV2), ((IObjectGraphType)graphType).ObjectType); + + // the two declared properties + __typekind + Assert.AreEqual(3, ((IObjectGraphType)graphType).Fields.Count); + } + + [Test] + public void OneInputObjectType_GeneratesCorrectly() + { + var collection = new ServiceCollection(); + collection.AddTransient, DefaultGraphQLTypeMakerFactory>(); + + var factory = new DefaultGraphQLSchemaFactory(includeBuiltInDirectives: false); + var options = new SchemaOptions(collection); + options.DeclarationOptions.DisableIntrospection = true; + + var provider = collection.BuildServiceProvider(); + + var scope = provider.CreateScope(); + var config = options.CreateConfiguration(); + + var instance = factory.CreateInstance( + scope, + config, + new SchemaTypeToRegister[] + { + new SchemaTypeToRegister(typeof(TwoPropertyObjectV2), TypeKind.INPUT_OBJECT), + }); + + Assert.IsNotNull(instance); + + Assert.AreEqual(5, instance.KnownTypes.Count); + Assert.IsTrue(instance.KnownTypes.Contains(typeof(DateTime))); // field on v2 + Assert.IsTrue(instance.KnownTypes.Contains(typeof(float))); // field on v2 + Assert.IsTrue(instance.KnownTypes.Contains(typeof(TwoPropertyObjectV2))); // the object itself + Assert.IsNotNull(instance.KnownTypes.SingleOrDefault(x => x.Name == Constants.ScalarNames.STRING)); // required for __typename + Assert.IsNotNull(instance.KnownTypes.SingleOrDefault(x => x.Name == Constants.ReservedNames.QUERY_TYPE_NAME)); + + var graphType = instance.KnownTypes.FindGraphType(typeof(TwoPropertyObjectV2)); + Assert.IsNotNull(graphType); + Assert.IsTrue(graphType is IInputObjectGraphType); + Assert.AreEqual(typeof(TwoPropertyObjectV2), ((IInputObjectGraphType)graphType).ObjectType); + Assert.AreEqual(2, ((IInputObjectGraphType)graphType).Fields.Count); + } + + [Test] + public void OneInterfaceType_NoArgumentsOnFields_GeneratesCorrectly() + { + var collection = new ServiceCollection(); + collection.AddTransient, DefaultGraphQLTypeMakerFactory>(); + + var factory = new DefaultGraphQLSchemaFactory(includeBuiltInDirectives: false); + var options = new SchemaOptions(collection); + options.DeclarationOptions.DisableIntrospection = true; + + var provider = collection.BuildServiceProvider(); + + var scope = provider.CreateScope(); + var config = options.CreateConfiguration(); + + var instance = factory.CreateInstance( + scope, + config, + new SchemaTypeToRegister[] + { + new SchemaTypeToRegister(typeof(ISinglePropertyObject)), + }); + + Assert.IsNotNull(instance); + + Assert.AreEqual(3, instance.KnownTypes.Count); + Assert.IsTrue(instance.KnownTypes.Contains(typeof(ISinglePropertyObject))); // the object itself + Assert.IsNotNull(instance.KnownTypes.SingleOrDefault(x => x.Name == Constants.ScalarNames.STRING)); + Assert.IsNotNull(instance.KnownTypes.SingleOrDefault(x => x.Name == Constants.ReservedNames.QUERY_TYPE_NAME)); + + var graphType = instance.KnownTypes.FindGraphType(typeof(ISinglePropertyObject)); + Assert.IsNotNull(graphType); + Assert.IsTrue(graphType is IInterfaceGraphType); + Assert.AreEqual(typeof(ISinglePropertyObject), ((IInterfaceGraphType)graphType).ObjectType); + + // the one declared field + __typekind + Assert.AreEqual(2, ((IInterfaceGraphType)graphType).Fields.Count); + } + + [Test] + public void OneObjectType_ArgumentsOnField_GeneratesCorrectly() + { + var collection = new ServiceCollection(); + collection.AddTransient, DefaultGraphQLTypeMakerFactory>(); + + var factory = new DefaultGraphQLSchemaFactory(includeBuiltInDirectives: false); + var options = new SchemaOptions(collection); + options.DeclarationOptions.DisableIntrospection = true; + + var provider = collection.BuildServiceProvider(); + + var scope = provider.CreateScope(); + var config = options.CreateConfiguration(); + + var instance = factory.CreateInstance( + scope, + config, + new SchemaTypeToRegister[] + { + new SchemaTypeToRegister(typeof(CustomObjectWithFieldWithArg)), + }); + + Assert.IsNotNull(instance); + + Assert.AreEqual(5, instance.KnownTypes.Count); + Assert.IsTrue(instance.KnownTypes.Contains(typeof(decimal))); // argument on field + Assert.IsTrue(instance.KnownTypes.Contains(typeof(int))); // return type of field + Assert.IsTrue(instance.KnownTypes.Contains(typeof(CustomObjectWithFieldWithArg))); // the object itself + Assert.IsNotNull(instance.KnownTypes.SingleOrDefault(x => x.Name == Constants.ScalarNames.STRING)); // required for __typename + Assert.IsNotNull(instance.KnownTypes.SingleOrDefault(x => x.Name == Constants.ReservedNames.QUERY_TYPE_NAME)); + + var graphType = instance.KnownTypes.FindGraphType(typeof(CustomObjectWithFieldWithArg)); + Assert.IsNotNull(graphType); + Assert.IsTrue(graphType is IObjectGraphType); + Assert.AreEqual(typeof(CustomObjectWithFieldWithArg), ((IObjectGraphType)graphType).ObjectType); + + // the declared method + __typekind + Assert.AreEqual(2, ((IObjectGraphType)graphType).Fields.Count); + var field = ((IObjectGraphType)graphType).Fields.SingleOrDefault(x => x.Name != Constants.ReservedNames.TYPENAME_FIELD); + + Assert.IsNotNull(field); + Assert.AreEqual(1, field.Arguments.Count); + Assert.AreEqual(typeof(decimal), field.Arguments[0].ObjectType); + Assert.AreEqual("arg", field.Arguments[0].Name); + } + + [Test] + public void OneDirective_GeneratesCorrectly() + { + var collection = new ServiceCollection(); + collection.AddTransient, DefaultGraphQLTypeMakerFactory>(); + + var factory = new DefaultGraphQLSchemaFactory(includeBuiltInDirectives: false); + var options = new SchemaOptions(collection); + options.DeclarationOptions.DisableIntrospection = true; + + var provider = collection.BuildServiceProvider(); + + var scope = provider.CreateScope(); + var config = options.CreateConfiguration(); + + var instance = factory.CreateInstance( + scope, + config, + new SchemaTypeToRegister[] + { + new SchemaTypeToRegister(typeof(CustomDirective)), + }); + + Assert.IsNotNull(instance); + + Assert.AreEqual(4, instance.KnownTypes.Count); + Assert.IsTrue(instance.KnownTypes.Contains(typeof(int))); // argument on directive + Assert.IsTrue(instance.KnownTypes.Contains(typeof(CustomDirective))); // the directive itself + Assert.IsNotNull(instance.KnownTypes.SingleOrDefault(x => x.Name == Constants.ScalarNames.STRING)); // required for __typename + Assert.IsNotNull(instance.KnownTypes.SingleOrDefault(x => x.Name == Constants.ReservedNames.QUERY_TYPE_NAME)); + + var graphType = instance.KnownTypes.FindGraphType(typeof(CustomDirective)); + Assert.IsNotNull(graphType); + Assert.IsTrue(graphType is IDirective); + Assert.AreEqual(typeof(CustomDirective), ((IDirective)graphType).ObjectType); + + // the declared method + __typekind + Assert.AreEqual(1, ((IDirective)graphType).Arguments.Count); + Assert.AreEqual(typeof(int), ((IDirective)graphType).Arguments[0].ObjectType); + } + + [Test] + public void OneController_GeneratesCorrectly() + { + var collection = new ServiceCollection(); + collection.AddTransient, DefaultGraphQLTypeMakerFactory>(); + + var factory = new DefaultGraphQLSchemaFactory(includeBuiltInDirectives: false); + var options = new SchemaOptions(collection); + options.DeclarationOptions.DisableIntrospection = true; + + var provider = collection.BuildServiceProvider(); + + var scope = provider.CreateScope(); + var config = options.CreateConfiguration(); + + var instance = factory.CreateInstance( + scope, + config, + new SchemaTypeToRegister[] + { + new SchemaTypeToRegister(typeof(CustomController)), + }); + + Assert.IsNotNull(instance); + + Assert.AreEqual(5, instance.KnownTypes.Count); + Assert.IsTrue(instance.KnownTypes.Contains(typeof(VirtualResolvedObject))); // intermediary resolved value on the controller + Assert.IsTrue(instance.KnownTypes.Contains(typeof(int))); // arg of controller field + Assert.IsNotNull(instance.KnownTypes.FindGraphType("Query_Custom")); // intermediate type for the controller + Assert.IsNotNull(instance.KnownTypes.SingleOrDefault(x => x.Name == Constants.ScalarNames.STRING)); // required for __typename + Assert.IsNotNull(instance.KnownTypes.SingleOrDefault(x => x.Name == Constants.ReservedNames.QUERY_TYPE_NAME)); + } + + [Test] + public void ClassArgumentToAField_ThatIsRegisteredAsAScalar_IsNamedProperly() + { + var collection = new ServiceCollection(); + collection.AddTransient, DefaultGraphQLTypeMakerFactory>(); + + var factory = new DefaultGraphQLSchemaFactory(includeBuiltInDirectives: false); + var options = new SchemaOptions(collection); + options.DeclarationOptions.DisableIntrospection = true; + + var provider = collection.BuildServiceProvider(); + + var scope = provider.CreateScope(); + var config = options.CreateConfiguration(); + + var instance = factory.CreateInstance( + scope, + config, + new SchemaTypeToRegister[] + { + new SchemaTypeToRegister(typeof(TwoPropertyObjectAsScalar)), + new SchemaTypeToRegister(typeof(CustomObjectWithCustomScalarArgument)), + }); + + Assert.IsNotNull(instance); + + var graphType = instance.KnownTypes.FindGraphType(typeof(CustomObjectWithCustomScalarArgument)) as IObjectGraphType; + var field = graphType.Fields.SingleOrDefault(x => string.Compare(x.Name, nameof(CustomObjectWithCustomScalarArgument.FieldWithScalarArg), true) == 0); + Assert.IsNotNull(field); + + var arg = field.Arguments[0]; + + Assert.AreEqual("obj", arg.Name); + + // ensure the type expression points to the scalar name + // not the name as if it was an input object + Assert.AreEqual(nameof(TwoPropertyObjectAsScalar), arg.TypeExpression.TypeName); + } + + [Test] + public void ReturnValueOfAField_ThatIsRegisteredAsAScalar_IsNamedProperly() + { + var collection = new ServiceCollection(); + collection.AddTransient, DefaultGraphQLTypeMakerFactory>(); + + var factory = new DefaultGraphQLSchemaFactory(includeBuiltInDirectives: false); + var options = new SchemaOptions(collection); + options.DeclarationOptions.DisableIntrospection = true; + + var provider = collection.BuildServiceProvider(); + + var scope = provider.CreateScope(); + var config = options.CreateConfiguration(); + + var instance = factory.CreateInstance( + scope, + config, + new SchemaTypeToRegister[] + { + new SchemaTypeToRegister(typeof(TwoPropertyObjectAsScalar)), + new SchemaTypeToRegister(typeof(CustomObjectWithCustomScalarField)), + }); + + Assert.IsNotNull(instance); + + var graphType = instance.KnownTypes.FindGraphType(typeof(CustomObjectWithCustomScalarField)) as IObjectGraphType; + var field = graphType.Fields.SingleOrDefault(x => string.Compare(x.Name, nameof(CustomObjectWithCustomScalarField.FieldWithScalarReturnValue), true) == 0); + Assert.IsNotNull(field); + + // ensure the type expression points to the scalar name + // not the name as if it was an input object + Assert.AreEqual(nameof(TwoPropertyObjectAsScalar), field.TypeExpression.TypeName); + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/DirectiveTypeMakerTests.cs b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/DirectiveTypeMakerTests.cs index a12e686aa..d5d0da9f4 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/DirectiveTypeMakerTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/DirectiveTypeMakerTests.cs @@ -12,6 +12,9 @@ namespace GraphQL.AspNet.Tests.Engine.TypeMakers using GraphQL.AspNet.Engine; using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Internal.Resolvers; + using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Schemas.Generation; + using GraphQL.AspNet.Schemas.Generation.TypeMakers; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Tests.Engine.TypeMakers.TestData; using GraphQL.AspNet.Tests.Framework; @@ -26,10 +29,14 @@ public void Directive_BasicPropertyCheck() { var builder = new TestServerBuilder(); var server = builder.Build(); - var typeMaker = new DefaultGraphTypeMakerProvider() - .CreateTypeMaker(server.Schema, TypeKind.DIRECTIVE); - var directive = typeMaker.CreateGraphType(typeof(MultiMethodDirective)).GraphType as IDirective; + var factory = new DefaultGraphQLTypeMakerFactory(); + factory.Initialize(server.Schema); + + var template = factory.MakeTemplate(typeof(MultiMethodDirective), TypeKind.DIRECTIVE); + var typeMaker = new DirectiveMaker(server.Schema.Configuration, factory.CreateArgumentMaker()); + + var directive = typeMaker.CreateGraphType(template).GraphType as IDirective; Assert.AreEqual("multiMethod", directive.Name); Assert.AreEqual("A Multi Method Directive", directive.Description); @@ -57,10 +64,14 @@ public void Directive_RepeatableAttributeIsSetWhenPresent() { var builder = new TestServerBuilder(); var server = builder.Build(); - var typeMaker = new DefaultGraphTypeMakerProvider() - .CreateTypeMaker(server.Schema, TypeKind.DIRECTIVE); - var directive = typeMaker.CreateGraphType(typeof(RepeatableDirective)).GraphType as IDirective; + var factory = new DefaultGraphQLTypeMakerFactory(); + factory.Initialize(server.Schema); + + var template = factory.MakeTemplate(typeof(RepeatableDirective), TypeKind.DIRECTIVE); + var typeMaker = new DirectiveMaker(server.Schema.Configuration, factory.CreateArgumentMaker()); + + var directive = typeMaker.CreateGraphType(template).GraphType as IDirective; Assert.IsTrue((bool)directive.IsRepeatable); Assert.AreEqual("repeatable", directive.Name); diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/EnumGraphTypeMakerTests.cs b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/EnumGraphTypeMakerTests.cs index ce45e0726..038c3b902 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/EnumGraphTypeMakerTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/EnumGraphTypeMakerTests.cs @@ -14,8 +14,10 @@ namespace GraphQL.AspNet.Tests.Engine.TypeMakers using GraphQL.AspNet.Configuration.Formatting; using GraphQL.AspNet.Engine.TypeMakers; using GraphQL.AspNet.Execution.Exceptions; + using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Schemas.Generation.TypeMakers; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Tests.Engine.TypeMakers.TestData; using GraphQL.AspNet.Tests.Framework; @@ -34,9 +36,10 @@ public void Parse_EnumWithUndeclaredValues_WhenConfigRequiresDeclaration_DoesntI .Build() .Schema; - var maker = new EnumGraphTypeMaker(schema); + var maker = new EnumGraphTypeMaker(schema.Configuration); + var template = GraphQLTemplateHelper.CreateEnumTemplate(); - var graphType = maker.CreateGraphType(typeof(EnumWithUndeclaredValues)).GraphType as IEnumGraphType; + var graphType = maker.CreateGraphType(template).GraphType as IEnumGraphType; Assert.AreEqual(2, graphType.Values.Count); Assert.IsTrue((bool)graphType.Values.ContainsKey("DECLAREDVALUE1")); Assert.IsTrue((bool)graphType.Values.ContainsKey("VALUE_AWESOME")); @@ -52,8 +55,9 @@ public void Parse_EnumWithUndeclaredValues_WhenConfigDoesNotRequireDeclaration_D .Build() .Schema; - var maker = new EnumGraphTypeMaker(schema); - var graphType = maker.CreateGraphType(typeof(EnumWithUndeclaredValues)).GraphType as IEnumGraphType; + var maker = new EnumGraphTypeMaker(schema.Configuration); + var template = GraphQLTemplateHelper.CreateEnumTemplate(); + var graphType = maker.CreateGraphType(template).GraphType as IEnumGraphType; Assert.AreEqual(3, graphType.Values.Count); Assert.IsTrue((bool)graphType.Values.ContainsKey("DECLAREDVALUE1")); @@ -69,8 +73,10 @@ public void Parse_EnumWithCustomGraphTypeName_YieldsName_InGraphType() { var schema = new GraphSchema(); - var maker = new EnumGraphTypeMaker(schema); - var graphType = maker.CreateGraphType(typeof(EnumWithGraphName)).GraphType as IEnumGraphType; + var maker = new EnumGraphTypeMaker(schema.Configuration); + var template = GraphQLTemplateHelper.CreateEnumTemplate(); + + var graphType = maker.CreateGraphType(template).GraphType as IEnumGraphType; Assert.AreEqual("ValidGraphName", graphType.Name); } @@ -88,8 +94,8 @@ public void CreateGraphType_ParsesAsExpected() var template = GraphQLTemplateHelper.CreateEnumTemplate(); - var maker = new EnumGraphTypeMaker(schema); - var graphType = maker.CreateGraphType(typeof(EnumWithDescriptionOnValues)).GraphType as IEnumGraphType; + var maker = new EnumGraphTypeMaker(schema.Configuration); + var graphType = maker.CreateGraphType(template).GraphType as IEnumGraphType; Assert.IsNotNull(graphType); Assert.AreEqual(template.Name, graphType.Name); @@ -103,8 +109,10 @@ public void AppliedDirectives_TransferFromTemplate() { var schema = new GraphSchema(); - var maker = new EnumGraphTypeMaker(schema); - var graphType = maker.CreateGraphType(typeof(EnumWithDirective)).GraphType as IEnumGraphType; + var template = GraphQLTemplateHelper.CreateEnumTemplate(); + var maker = new EnumGraphTypeMaker(schema.Configuration); + + var graphType = maker.CreateGraphType(template).GraphType as IEnumGraphType; Assert.AreEqual(graphType, graphType.AppliedDirectives.Parent); @@ -119,8 +127,10 @@ public void DirectivesAreTransferedToGraphType() { var schema = new GraphSchema(); - var maker = new EnumGraphTypeMaker(schema); - var graphType = maker.CreateGraphType(typeof(EnumValueWithDirective)).GraphType as IEnumGraphType; + var maker = new EnumGraphTypeMaker(schema.Configuration); + var template = GraphQLTemplateHelper.CreateEnumTemplate(); + + var graphType = maker.CreateGraphType(template).GraphType as IEnumGraphType; Assert.AreEqual(0, graphType.AppliedDirectives.Count); @@ -144,9 +154,10 @@ public void EnumValueIsKeyword_ButFormattingDoesNotMatchKeyword_WorksAsExpected( { var schema = new GraphSchema(); - var maker = new EnumGraphTypeMaker(schema); + var maker = new EnumGraphTypeMaker(schema.Configuration); + var template = GraphQLTemplateHelper.CreateGraphTypeTemplate(enumType, TypeKind.ENUM) as IGraphTypeTemplate; - var graphType = maker.CreateGraphType(enumType).GraphType as IEnumGraphType; + var graphType = maker.CreateGraphType(template).GraphType as IEnumGraphType; var value1 = graphType.Values[enumValue]; Assert.IsNotNull(value1); @@ -164,11 +175,12 @@ public void EnumValueIsKeyword_AndFormattingMatchesKeyword_ThrowsException(Type .Build() .Schema; - var maker = new EnumGraphTypeMaker(schema); + var maker = new EnumGraphTypeMaker(schema.Configuration); + var template = GraphQLTemplateHelper.CreateGraphTypeTemplate(enumType, TypeKind.ENUM) as IGraphTypeTemplate; try { - var graphType = maker.CreateGraphType(enumType).GraphType as IEnumGraphType; + var graphType = maker.CreateGraphType(template).GraphType as IEnumGraphType; } catch (GraphTypeDeclarationException) { diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/FieldMaker_InputFieldTests.cs b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/FieldMaker_InputFieldTests.cs index d57baf4a1..87e3ac484 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/FieldMaker_InputFieldTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/FieldMaker_InputFieldTests.cs @@ -11,6 +11,9 @@ namespace GraphQL.AspNet.Tests.Engine.TypeMakers { using System.Linq; using GraphQL.AspNet.Engine.TypeMakers; + using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Schemas.Generation; + using GraphQL.AspNet.Schemas.Generation.TypeMakers; using GraphQL.AspNet.Tests.Engine.TypeMakers.TestData; using GraphQL.AspNet.Tests.Framework; using GraphQL.AspNet.Tests.Framework.CommonHelpers; @@ -29,7 +32,10 @@ public void Parse_NotRequiredValueTypePropertyCheck() .Values .Single(x => x.Name == nameof(InputTestObject.NotRequiredValueTypeField)); - var graphField = new GraphFieldMaker(server.Schema).CreateField(fieldTemplate).Field; + var factory = new DefaultGraphQLTypeMakerFactory(); + factory.Initialize(server.Schema); + + var graphField = new GraphFieldMaker(server.Schema, factory).CreateField(fieldTemplate).Field; Assert.AreEqual("notRequiredValueTypeField", graphField.Name); Assert.IsFalse((bool)graphField.IsRequired); @@ -56,7 +62,10 @@ public void Parse_RequiredValueTypePropertyCheck() .Values .Single(x => x.Name == nameof(InputTestObject.RequiredValueTypeField)); - var graphField = new GraphFieldMaker(server.Schema).CreateField(fieldTemplate).Field; + var factory = new DefaultGraphQLTypeMakerFactory(); + factory.Initialize(server.Schema); + + var graphField = new GraphFieldMaker(server.Schema, factory).CreateField(fieldTemplate).Field; Assert.AreEqual("requiredValueTypeField", graphField.Name); Assert.IsTrue((bool)graphField.IsRequired); @@ -80,7 +89,10 @@ public void Parse_NotRequiredReferenceTypePropertyCheck() .Values .Single(x => x.Name == nameof(InputTestObject.NotRequiredReferenceTypeField)); - var graphField = new GraphFieldMaker(server.Schema).CreateField(fieldTemplate).Field; + var factory = new DefaultGraphQLTypeMakerFactory(); + factory.Initialize(server.Schema); + + var graphField = new GraphFieldMaker(server.Schema, factory).CreateField(fieldTemplate).Field; Assert.AreEqual("notRequiredReferenceTypeField", graphField.Name); Assert.IsFalse((bool)graphField.IsRequired); @@ -106,7 +118,10 @@ public void Parse_RequiredReferenceTypePropertyCheck() .Values .Single(x => x.Name == nameof(InputTestObject.RequiredReferenceTypeField)); - var graphField = new GraphFieldMaker(server.Schema).CreateField(fieldTemplate).Field; + var factory = new DefaultGraphQLTypeMakerFactory(); + factory.Initialize(server.Schema); + + var graphField = new GraphFieldMaker(server.Schema, factory).CreateField(fieldTemplate).Field; Assert.AreEqual("requiredReferenceTypeField", graphField.Name); @@ -134,7 +149,10 @@ public void Parse_RequiredNonNullableReferenceTypePropertyCheck() .Values .Single(x => x.Name == nameof(InputTestObject.RequiredReferenceExplicitNonNullTypeField)); - var graphField = new GraphFieldMaker(server.Schema).CreateField(fieldTemplate).Field; + var factory = new DefaultGraphQLTypeMakerFactory(); + factory.Initialize(server.Schema); + + var graphField = new GraphFieldMaker(server.Schema, factory).CreateField(fieldTemplate).Field; Assert.AreEqual("requiredReferenceExplicitNonNullTypeField", graphField.Name); Assert.IsTrue((bool)graphField.IsRequired); @@ -160,7 +178,10 @@ public void Parse_RequiredGraphIdPropertyCheck() .Values .Single(x => x.Name == nameof(InputTestObject.GraphIdRequired)); - var graphField = new GraphFieldMaker(server.Schema).CreateField(fieldTemplate).Field; + var factory = new DefaultGraphQLTypeMakerFactory(); + factory.Initialize(server.Schema); + + var graphField = new GraphFieldMaker(server.Schema, factory).CreateField(fieldTemplate).Field; Assert.AreEqual("graphIdRequired", graphField.Name); Assert.IsTrue((bool)graphField.IsRequired); @@ -185,7 +206,10 @@ public void Parse_NotRequiredGraphIdPropertyCheck() .Values .Single(x => x.Name == nameof(InputTestObject.GraphIdNotRequired)); - var graphField = new GraphFieldMaker(server.Schema).CreateField(fieldTemplate).Field; + var factory = new DefaultGraphQLTypeMakerFactory(); + factory.Initialize(server.Schema); + + var graphField = new GraphFieldMaker(server.Schema, factory).CreateField(fieldTemplate).Field; Assert.AreEqual("graphIdNotRequired", graphField.Name); Assert.IsFalse((bool)graphField.IsRequired); @@ -209,7 +233,10 @@ public void Parse_NotRequiredNullableGraphIdPropertyCheck() .Values .Single(x => x.Name == nameof(InputTestObject.GraphIdNullable)); - var graphField = new GraphFieldMaker(server.Schema).CreateField(fieldTemplate).Field; + var factory = new DefaultGraphQLTypeMakerFactory(); + factory.Initialize(server.Schema); + + var graphField = new GraphFieldMaker(server.Schema, factory).CreateField(fieldTemplate).Field; Assert.AreEqual("graphIdNullable", graphField.Name); Assert.IsFalse((bool)graphField.IsRequired); diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/FieldMaker_StandardFieldTests.cs b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/FieldMaker_StandardFieldTests.cs index a997abb72..f9e8c0a4f 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/FieldMaker_StandardFieldTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/FieldMaker_StandardFieldTests.cs @@ -12,6 +12,9 @@ namespace GraphQL.AspNet.Tests.Engine.TypeMakers using GraphQL.AspNet.Engine.TypeMakers; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Schemas.Generation; + using GraphQL.AspNet.Schemas.Generation.TypeMakers; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Security; @@ -60,7 +63,10 @@ public void Parse_PolicyOnController_IsInheritedByField() Assert.AreEqual(1, template.SecurityPolicies.Count()); Assert.AreEqual(0, actionMethod.SecurityPolicies.Count()); - var graphField = new GraphFieldMaker(server.Schema).CreateField(actionMethod).Field; + var factory = new DefaultGraphQLTypeMakerFactory(); + factory.Initialize(server.Schema); + + var graphField = new GraphFieldMaker(server.Schema, factory).CreateField(actionMethod).Field; Assert.AreEqual(1, Enumerable.Count(graphField.SecurityGroups)); var group = Enumerable.First(graphField.SecurityGroups); @@ -80,7 +86,10 @@ public void Parse_PolicyOnController_AndOnMethod_IsInheritedByField_InCorrectOrd Assert.AreEqual(1, template.SecurityPolicies.Count()); Assert.AreEqual(1, actionMethod.SecurityPolicies.Count()); - var graphField = new GraphFieldMaker(server.Schema).CreateField(actionMethod).Field; + var factory = new DefaultGraphQLTypeMakerFactory(); + factory.Initialize(server.Schema); + + var graphField = new GraphFieldMaker(server.Schema, factory).CreateField(actionMethod).Field; Assert.AreEqual(2, Enumerable.Count(graphField.SecurityGroups)); @@ -107,7 +116,10 @@ public void Parse_MethodWithNullableEnum_ParsesCorrectly() Assert.AreEqual(typeof(NullableEnumController.LengthType), arg.ObjectType); Assert.AreEqual(NullableEnumController.LengthType.Yards, arg.DefaultValue); - var graphField = new GraphFieldMaker(server.Schema).CreateField(field).Field; + var factory = new DefaultGraphQLTypeMakerFactory(); + factory.Initialize(server.Schema); + + var graphField = new GraphFieldMaker(server.Schema, factory).CreateField(field).Field; Assert.IsNotNull(graphField); var graphArg = Enumerable.FirstOrDefault(graphField.Arguments); diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/GraphTypeMakerFactoryTests.cs b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/GraphTypeMakerFactoryTests.cs deleted file mode 100644 index 86c9a8789..000000000 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/GraphTypeMakerFactoryTests.cs +++ /dev/null @@ -1,37 +0,0 @@ -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - -namespace GraphQL.AspNet.Tests.Engine.TypeMakers -{ - using GraphQL.AspNet.Engine; - using GraphQL.AspNet.Schemas; - using GraphQL.AspNet.Schemas.TypeSystem; - using NUnit.Framework; - - [TestFixture] - public class GraphTypeMakerFactoryTests : GraphTypeMakerTestBase - { - [Test] - public void DefaultFactory_NoSchema_YieldsNoMaker() - { - var factory = new DefaultGraphTypeMakerProvider(); - var instance = factory.CreateTypeMaker(null, TypeKind.OBJECT); - Assert.IsNull(instance); - } - - [Test] - public void DefaultFactory_UnknownTypeKind_YieldsNoMaker() - { - var schema = new GraphSchema(); - var factory = new DefaultGraphTypeMakerProvider(); - var instance = factory.CreateTypeMaker(schema, TypeKind.LIST); - Assert.IsNull(instance); - } - } -} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/GraphTypeMakerTestBase.cs b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/GraphTypeMakerTestBase.cs index 67df5988c..5889d4bbd 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/GraphTypeMakerTestBase.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/GraphTypeMakerTestBase.cs @@ -17,6 +17,8 @@ namespace GraphQL.AspNet.Tests.Engine.TypeMakers using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Tests.Framework; + using GraphQL.AspNet.Schemas.Generation; + using GraphQL.AspNet.Schemas; public abstract class GraphTypeMakerTestBase { @@ -34,16 +36,26 @@ protected GraphTypeCreationResult MakeGraphType( }); } - var typeMaker = new DefaultGraphTypeMakerProvider(); var testServer = builder.Build(); - var maker = typeMaker.CreateTypeMaker(testServer.Schema, kind); - return maker.CreateGraphType(type); + + var factory = new DefaultGraphQLTypeMakerFactory(); + factory.Initialize(testServer.Schema); + + var template = factory.MakeTemplate(type, kind); + var maker = factory.CreateTypeMaker(type, kind); + + return maker.CreateGraphType(template); } protected IGraphField MakeGraphField(IGraphFieldTemplate fieldTemplate) { var testServer = new TestServerBuilder().Build(); - var maker = new GraphFieldMaker(testServer.Schema); + + var factory = new DefaultGraphQLTypeMakerFactory(); + factory.Initialize(testServer.Schema); + + var maker = factory.CreateFieldMaker(); + return maker.CreateField(fieldTemplate).Field; } } diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/InputObjectGraphTypeMakerTests.cs b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/InputObjectGraphTypeMakerTests.cs index 41bd17b25..ee2aab5a8 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/InputObjectGraphTypeMakerTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/InputObjectGraphTypeMakerTests.cs @@ -40,8 +40,8 @@ public void Parse_FieldAndDependencies_SetCorrectly() // string, OneMarkedProperty Assert.AreEqual(2, Enumerable.Count(typeResult.DependentTypes)); - Assert.IsTrue(Enumerable.Any(typeResult.DependentTypes, x => x.Type == typeof(OneMarkedProperty) && x.ExpectedKind == TypeKind.INPUT_OBJECT)); - Assert.IsTrue(Enumerable.Any(typeResult.DependentTypes, x => x.Type == typeof(string) && x.ExpectedKind == TypeKind.SCALAR)); + Assert.IsTrue(Enumerable.Any(typeResult.DependentTypes, x => x.Type == typeof(OneMarkedProperty))); + Assert.IsTrue(Enumerable.Any(typeResult.DependentTypes, x => x.Type == typeof(string))); } [Test] diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/InterfaceTypeMakerTests.cs b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/InterfaceTypeMakerTests.cs index 0e674e199..ed76fb8eb 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/InterfaceTypeMakerTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/InterfaceTypeMakerTests.cs @@ -12,6 +12,9 @@ namespace GraphQL.AspNet.Tests.Engine.TypeMakers using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Engine; using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Schemas.Generation; + using GraphQL.AspNet.Schemas.Generation.TypeMakers; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Tests.Engine.TypeMakers.TestData; using GraphQL.AspNet.Tests.Framework; @@ -25,10 +28,13 @@ public void CreateGraphType_PropertyCheck() { var server = new TestServerBuilder().Build(); var template = GraphQLTemplateHelper.CreateInterfaceTemplate(); - var typeMaker = new DefaultGraphTypeMakerProvider(); - var graphType = typeMaker.CreateTypeMaker(server.Schema, TypeKind.INTERFACE) - .CreateGraphType(typeof(ISimpleInterface)).GraphType as IInterfaceGraphType; + var factory = new DefaultGraphQLTypeMakerFactory(); + factory.Initialize(server.Schema); + + var typeMaker = new InterfaceGraphTypeMaker(server.Schema.Configuration, factory.CreateFieldMaker()); + + var graphType = typeMaker.CreateGraphType(GraphQLTemplateHelper.CreateGraphTypeTemplate(typeof(ISimpleInterface), TypeKind.INTERFACE)).GraphType as IInterfaceGraphType; Assert.IsNotNull(graphType); Assert.AreEqual(template.Name, graphType.Name); diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/ObjectGraphTypeMakerTests.cs b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/ObjectGraphTypeMakerTests.cs index f63240138..e002a084b 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/ObjectGraphTypeMakerTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/ObjectGraphTypeMakerTests.cs @@ -14,6 +14,7 @@ namespace GraphQL.AspNet.Tests.Engine.TypeMakers using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Schemas.Generation; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Tests.Engine.TypeMakers.TestData; using GraphQL.AspNet.Tests.Framework; @@ -40,13 +41,16 @@ public void Object_CreateGraphType_WithSelfReferencingObject_ParsesAsExpected() } [Test] - public void Interface_CreateGraphType_ParsesCorrectly() + public void Object_CreateGraphType_ParsesCorrectly() { var server = new TestServerBuilder(TestOptions.UseCodeDeclaredNames).Build(); - var template = GraphQLTemplateHelper.CreateGraphTypeTemplate(); - var typeMaker = new DefaultGraphTypeMakerProvider(); + var template = GraphQLTemplateHelper.CreateGraphTypeTemplate(TypeKind.OBJECT); + var factory = new DefaultGraphQLTypeMakerFactory(); + factory.Initialize(server.Schema); - var objectGraphType = typeMaker.CreateTypeMaker(server.Schema, TypeKind.OBJECT).CreateGraphType(typeof(TypeCreationItem)).GraphType as IObjectGraphType; + var objectGraphType = factory + .CreateTypeMaker(typeof(TypeCreationItem)) + .CreateGraphType(template).GraphType as IObjectGraphType; Assert.IsNotNull(objectGraphType); Assert.AreEqual(nameof(TypeCreationItem), objectGraphType.Name); diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/ScalarGraphTypeMakerTests.cs b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/ScalarGraphTypeMakerTests.cs index da614264a..16081c822 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/ScalarGraphTypeMakerTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/ScalarGraphTypeMakerTests.cs @@ -8,7 +8,13 @@ // ************************************************************* namespace GraphQL.AspNet.Tests.Engine.TypeMakers { + using System; + using GraphQL.AspNet.Configuration.Formatting; using GraphQL.AspNet.Engine.TypeMakers; + using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Schemas.Generation.TypeMakers; + using GraphQL.AspNet.Tests.Framework; using NUnit.Framework; [TestFixture] @@ -17,9 +23,10 @@ public class ScalarGraphTypeMakerTests [Test] public void RegisteredScalarIsReturned() { - var maker = new ScalarGraphTypeMaker(); + var schema = new GraphSchema(); + var maker = new ScalarGraphTypeMaker(schema.Configuration); - var result = maker.CreateGraphType(typeof(int)); + var result = maker.CreateGraphType(GraphQLTemplateHelper.CreateGraphTypeTemplate(typeof(int))); Assert.IsNotNull(result?.GraphType); Assert.AreEqual(typeof(int), result.ConcreteType); } @@ -27,10 +34,55 @@ public void RegisteredScalarIsReturned() [Test] public void NullType_ReturnsNullResult() { - var maker = new ScalarGraphTypeMaker(); + var schema = new GraphSchema(); + var maker = new ScalarGraphTypeMaker(schema.Configuration); var result = maker.CreateGraphType(null); Assert.IsNull(result); } + + // fixed name scalars will never be renamed + [TestCase(typeof(int), GraphNameFormatStrategy.UpperCase, "Int")] + [TestCase(typeof(int), GraphNameFormatStrategy.LowerCase, "Int")] + [TestCase(typeof(int), GraphNameFormatStrategy.ProperCase, "Int")] + [TestCase(typeof(float), GraphNameFormatStrategy.UpperCase, "Float")] + [TestCase(typeof(float), GraphNameFormatStrategy.LowerCase, "Float")] + [TestCase(typeof(float), GraphNameFormatStrategy.ProperCase, "Float")] + [TestCase(typeof(string), GraphNameFormatStrategy.UpperCase, "String")] + [TestCase(typeof(string), GraphNameFormatStrategy.LowerCase, "String")] + [TestCase(typeof(string), GraphNameFormatStrategy.ProperCase, "String")] + [TestCase(typeof(bool), GraphNameFormatStrategy.UpperCase, "Boolean")] + [TestCase(typeof(bool), GraphNameFormatStrategy.LowerCase, "Boolean")] + [TestCase(typeof(bool), GraphNameFormatStrategy.ProperCase, "Boolean")] + [TestCase(typeof(GraphId), GraphNameFormatStrategy.UpperCase, "ID")] + [TestCase(typeof(GraphId), GraphNameFormatStrategy.LowerCase, "ID")] + [TestCase(typeof(GraphId), GraphNameFormatStrategy.ProperCase, "ID")] + + // non-fixed scalars will rename themselves + [TestCase(typeof(decimal), GraphNameFormatStrategy.UpperCase, "DECIMAL")] + [TestCase(typeof(decimal), GraphNameFormatStrategy.LowerCase, "decimal")] + [TestCase(typeof(decimal), GraphNameFormatStrategy.ProperCase, "Decimal")] + [TestCase(typeof(Uri), GraphNameFormatStrategy.UpperCase, "URI")] + [TestCase(typeof(Uri), GraphNameFormatStrategy.LowerCase, "uri")] + [TestCase(typeof(Uri), GraphNameFormatStrategy.ProperCase, "Uri")] + public void BuiltInScalar_ObeysNamingRulesOfConfig(Type builtInScalarType, GraphNameFormatStrategy strategy, string expectedName) + { + var server = new TestServerBuilder() + .AddGraphQL(o => + { + o.DeclarationOptions.GraphNamingFormatter + = new GraphNameFormatter(strategy); + }) + .Build(); + + var maker = new ScalarGraphTypeMaker(server.Schema.Configuration); + + var template = new ScalarGraphTypeTemplate(builtInScalarType); + template.Parse(); + template.ValidateOrThrow(); + + var result = maker.CreateGraphType(template); + Assert.AreEqual(expectedName, result.GraphType.Name); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/UnionTypeMakerTests.cs b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/UnionTypeMakerTests.cs index 0f7603629..8f36ed1b2 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/UnionTypeMakerTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/UnionTypeMakerTests.cs @@ -14,6 +14,7 @@ namespace GraphQL.AspNet.Tests.Engine.TypeMakers using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Schemas.Generation.TypeMakers; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Tests.Engine.TypeMakers.TestData; using GraphQL.AspNet.Tests.Framework; @@ -29,7 +30,7 @@ public void ActionTemplate_CreateUnionType_PropertyCheck() schema.SetNoAlterationConfiguration(); var action = GraphQLTemplateHelper.CreateActionMethodTemplate(nameof(UnionTestController.TwoTypeUnion)); - var unionResult = new UnionGraphTypeMaker(schema).CreateUnionFromProxy(action.UnionProxy); + var unionResult = new UnionGraphTypeMaker(schema.Configuration).CreateUnionFromProxy(action.UnionProxy); var union = unionResult.GraphType as IUnionGraphType; Assert.IsNotNull(union); @@ -52,7 +53,7 @@ public void UnionProxyWithDirectives_DirectivesAreApplied() var schema = new GraphSchema(); schema.SetNoAlterationConfiguration(); - var maker = new UnionGraphTypeMaker(schema); + var maker = new UnionGraphTypeMaker(schema.Configuration); var unionResult = maker.CreateUnionFromProxy(new UnionProxyWithDirective()); var unionType = unionResult.GraphType as IUnionGraphType; @@ -71,7 +72,7 @@ public void UnionProxyWithDirectives_InvalidDirectiveType_ThrowsException() { var schema = new GraphSchema(); schema.SetNoAlterationConfiguration(); - var maker = new UnionGraphTypeMaker(schema); + var maker = new UnionGraphTypeMaker(schema.Configuration); Assert.Throws(() => { @@ -84,7 +85,7 @@ public void NullProxy_YieldsNullGraphType() { var schema = new GraphSchema(); schema.SetNoAlterationConfiguration(); - var maker = new UnionGraphTypeMaker(schema); + var maker = new UnionGraphTypeMaker(schema.Configuration); var unionType = maker.CreateUnionFromProxy(null); Assert.IsNull(unionType); diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/DirectiveProcessorTypeSystemTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/DirectiveProcessorTypeSystemTests.cs index 1b977af56..de3660fcc 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/DirectiveProcessorTypeSystemTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/DirectiveProcessorTypeSystemTests.cs @@ -10,16 +10,21 @@ namespace GraphQL.AspNet.Tests.Execution { using System; using System.Collections.Generic; + using System.Linq; using System.Threading; using System.Threading.Tasks; + using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Configuration.Exceptions; using GraphQL.AspNet.Directives; + using GraphQL.AspNet.Engine; using GraphQL.AspNet.Execution; using GraphQL.AspNet.Execution.Contexts; using GraphQL.AspNet.Execution.Exceptions; + using GraphQL.AspNet.Interfaces.Engine; using GraphQL.AspNet.Interfaces.Middleware; using GraphQL.AspNet.Middleware; using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Schemas.Generation; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Tests.Execution.TestData.GraphSchemaProcessorTestData; using Microsoft.Extensions.DependencyInjection; @@ -41,6 +46,8 @@ public class DirectiveProcessorTypeSystemTests public DirectiveProcessorTypeSystemTests() { _serviceCollection = new ServiceCollection(); + _serviceCollection.AddTransient, DefaultGraphQLTypeMakerFactory>(); + _itemsExecuted = new List(); _typesToAdd = new List(); } @@ -50,10 +57,15 @@ private void BuildInstance( GraphMiddlewareInvocationDelegate delegateToExecute = null) { // build the schema - _schemaInstance = new GraphSchema(); - var manager = new GraphSchemaManager(_schemaInstance); - foreach (var type in _typesToAdd) - manager.EnsureGraphType(type); + var options = new SchemaOptions(_serviceCollection); + + var schemaFactory = new DefaultGraphQLSchemaFactory( + processTypeSystemDirectives: false); + + _schemaInstance = schemaFactory.CreateInstance( + _serviceCollection.BuildServiceProvider().CreateScope(), + options.CreateConfiguration(), + _typesToAdd.Select(x => new SchemaTypeToRegister(x))); // build hte directive pipeline instance if (buildRequiredDirectivePipeline) @@ -291,7 +303,7 @@ public void UncaughtExceptionDuringPipelineExecution_IsCaughtAndPackagedByProces Assert.AreEqual(thrownException, ex.InnerException); Assert.IsNull(ex.InnerException.InnerException); } - catch + catch(Exception ex) { Assert.Fail("Unexpected exception was thrown"); } diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionRuntimeFieldTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionRuntimeFieldTests.cs index b8d8f08ad..362d5d13e 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionRuntimeFieldTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionRuntimeFieldTests.cs @@ -316,6 +316,9 @@ public async Task BasicMappedQuery_WithExplicitlyDeclaredInjectedService_Returni [Test] public async Task BasicMappedQuery_WithImplicitlyDeclaredInjectedService_ReturningValueResult_ResolvesCorrectly() { + Assert.Inconclusive("Need to finish this test"); + return; + var serverBuilder = new TestServerBuilder(); serverBuilder.AddTransient(); @@ -348,6 +351,9 @@ public async Task BasicMappedQuery_WithImplicitlyDeclaredInjectedService_Returni [Test] public async Task BasicMappedQuery_WithImplicitlyDeclaredInjectedService_ReturningActionResult_ResolvesCorrectly() { + Assert.Inconclusive("Need to finish this test"); + return; + var serverBuilder = new TestServerBuilder(); serverBuilder.AddTransient(); diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/IntrospectionTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/IntrospectionTests.cs index 5b2345272..7703127ea 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/IntrospectionTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/IntrospectionTests.cs @@ -1345,13 +1345,10 @@ public async Task SpecifiedByLateBound_WithAtSymbol_PopulateSpecifiedByURL() [Test] public async Task SpecifiedByEarlyBound_PopulateSpecifiedByURL() { - using var restorePoint = new GraphQLGlobalRestorePoint(); - - GraphQLProviders.ScalarProvider = new DefaultScalarGraphTypeProvider(); - GraphQLProviders.ScalarProvider.RegisterCustomScalar(typeof(CustomSpecifiedScalar)); var serverBuilder = new TestServerBuilder(); var server = serverBuilder.AddGraphQL(o => { + o.AddGraphType(); o.AddGraphType(); }) .Build(); diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TypeSystemDirectiveDiscoveryTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TypeSystemDirectiveDiscoveryTests.cs index 9826557f2..64a080766 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TypeSystemDirectiveDiscoveryTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TypeSystemDirectiveDiscoveryTests.cs @@ -123,13 +123,10 @@ public void UnionDirective_DeclaredByType_WhenNotExplicitlyIncluded_IsLocatedAnd [Test] public void ScalarDirective_DeclaredByType_WhenNotExplicitlyIncluded_IsLocatedAndIncluded() { - using var restorePoint = new GraphQLGlobalRestorePoint(); - - GraphQLProviders.ScalarProvider.RegisterCustomScalar(typeof(MarkedScalarByAttribute)); - // the object has a property that returns the custom scalar // forcing the enclusion of the scalar and thus the directive on said scalar var server = new TestServerBuilder(TestOptions.UseCodeDeclaredNames) + .AddType() .AddType() .Build(); diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/InputResolverGeneratorTests.cs b/src/unit-tests/graphql-aspnet-tests/Internal/InputResolverGeneratorTests.cs index c071385a6..15a4bc90c 100644 --- a/src/unit-tests/graphql-aspnet-tests/Internal/InputResolverGeneratorTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Internal/InputResolverGeneratorTests.cs @@ -47,12 +47,9 @@ private enum TestEnum private ISchema CreateSchema() { var builder = new TestServerBuilder(); - var defaultScalars = new DefaultScalarGraphTypeProvider(); - foreach (var scalarConcreteType in defaultScalars.ConcreteTypes) - { + foreach (var scalarConcreteType in GlobalScalars.ScalarInstanceTypes) builder.AddType(scalarConcreteType); - } builder.AddType(typeof(TestEnum)); builder.AddType(typeof(Telephone), TypeKind.INPUT_OBJECT); diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/ObjectMethodResolverTests.cs b/src/unit-tests/graphql-aspnet-tests/Internal/ObjectMethodResolverTests.cs index b3a1c0b10..2ec88ea96 100644 --- a/src/unit-tests/graphql-aspnet-tests/Internal/ObjectMethodResolverTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Internal/ObjectMethodResolverTests.cs @@ -12,6 +12,7 @@ namespace GraphQL.AspNet.Tests.Internal using System; using System.Threading.Tasks; using GraphQL.AspNet.Internal.Resolvers; + using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Tests.Framework; using GraphQL.AspNet.Tests.Framework.CommonHelpers; using GraphQL.AspNet.Tests.Internal.ValueResolversTestData; @@ -29,7 +30,8 @@ public async Task NullSourceData_FailsRequest() var builder = server.CreateGraphTypeFieldContextBuilder( nameof(ResolverObject.MethodRetrieveData), - null); + null, + TypeKind.OBJECT); var resolver = new ObjectMethodGraphFieldResolver(builder.ResolverMetaData.Object); @@ -50,7 +52,8 @@ public async Task SourceDataIsNotOfTheTemplate_FailsRequest() var builder = server.CreateGraphTypeFieldContextBuilder( nameof(ResolverObject.MethodRetrieveData), - new object()); + new object(), + TypeKind.OBJECT); // source data is not of the type the resolver is for builder.AddSourceData(new TwoPropertyObject()); @@ -72,7 +75,8 @@ public async Task MethodThrowsException_FailsRequest() var builder = server.CreateGraphTypeFieldContextBuilder( nameof(ResolverObject.MethodThrowException), - new object()); + new object(), + TypeKind.OBJECT); // source data is not of the type the resolver is for builder.AddSourceData(new ResolverObject()); @@ -96,7 +100,8 @@ public async Task KnownExecutionError_FailsRequest() var builder = server.CreateGraphTypeFieldContextBuilder( nameof(ResolverObject.MethodWithArgument), - new object()); + new object(), + TypeKind.OBJECT); // the method declares one input argument which is not provided on this request // resulting in a GraphExecutionException which @@ -123,7 +128,8 @@ public async Task AsyncMethod_NullSourceData_FailsRequest() var builder = server.CreateGraphTypeFieldContextBuilder( nameof(ResolverObject.MethodRetrieveDataAsync), - null); + null, + TypeKind.OBJECT); var resolver = new ObjectMethodGraphFieldResolver(builder.ResolverMetaData.Object); @@ -144,7 +150,8 @@ public async Task AsyncMethod_SourceDataIsNotOfTheTemplate_FailsRequest() var builder = server.CreateGraphTypeFieldContextBuilder( nameof(ResolverObject.MethodRetrieveDataAsync), - new object()); + new object(), + TypeKind.OBJECT); // source data is not of the type the resolver is for builder.AddSourceData(new TwoPropertyObject()); @@ -166,7 +173,8 @@ public async Task AsyncMethod_MethodThrowsException_FailsRequest() var builder = server.CreateGraphTypeFieldContextBuilder( nameof(ResolverObject.MethodThrowExceptionAsync), - new object()); + new object(), + TypeKind.OBJECT); // source data is not of the type the resolver is for builder.AddSourceData(new ResolverObject()); @@ -190,7 +198,8 @@ public async Task AsyncMethod_KnownExecutionError_FailsRequest() var builder = server.CreateGraphTypeFieldContextBuilder( nameof(ResolverObject.MethodWithArgumentAsync), - new object()); + new object(), + TypeKind.OBJECT); // the method declares one input argument which is not provided on this request // resulting in a GraphExecutionException which diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/ObjectPropertyResolverTests.cs b/src/unit-tests/graphql-aspnet-tests/Internal/ObjectPropertyResolverTests.cs index e8c73f5c1..53e06c7c1 100644 --- a/src/unit-tests/graphql-aspnet-tests/Internal/ObjectPropertyResolverTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Internal/ObjectPropertyResolverTests.cs @@ -13,6 +13,7 @@ namespace GraphQL.AspNet.Tests.Internal using System.Threading.Tasks; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Internal.Resolvers; + using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Tests.Common.Extensions.DiExtensionTestData; using GraphQL.AspNet.Tests.Framework; using GraphQL.AspNet.Tests.Framework.CommonHelpers; @@ -32,7 +33,8 @@ public async Task NullSourceData_FailsRequest() var fieldContextBuilder = server.CreateGraphTypeFieldContextBuilder( nameof(ResolverObject.Address1), - null); + null, + TypeKind.OBJECT); fieldContextBuilder.AddSourceData(null); var resolutionContext = fieldContextBuilder.CreateResolutionContext(); @@ -55,7 +57,8 @@ public async Task TemplateIsInterface_SourceDataDoesImplementInterface_RendersCo var fieldContextBuilder = server.CreateGraphTypeFieldContextBuilder( nameof(ResolverObject.Address1), - null); + null, + TypeKind.OBJECT); var item = new ResolverObject(); item.Address1 = "15th Street"; @@ -85,7 +88,8 @@ public async Task TemplateIsInterface_SourceDataDoesNotImplementInterface_FailsR var fieldContextBuilder = server.CreateGraphTypeFieldContextBuilder( nameof(ResolverObject.Address1), - null); + null, + TypeKind.OBJECT); fieldContextBuilder.AddSourceData(new TwoPropertyObject()); @@ -115,7 +119,8 @@ public async Task SourceDataIsNotOfTheTemplate_FailsRequest() // resolving structA, but supplying structB as source var fieldContextBuilder = server.CreateGraphTypeFieldContextBuilder( nameof(ResolverStructA.Prop1), - new ResolverStructB("struct")); + new ResolverStructB("struct"), + TypeKind.OBJECT); // source data is not of the type the resolver is for var resolver = new ObjectPropertyGraphFieldResolver(fieldContextBuilder.ResolverMetaData.Object); @@ -136,7 +141,8 @@ public async Task PropertyThrowsException_FailsRequest() var fieldContextBuilder = server.CreateGraphTypeFieldContextBuilder( nameof(ResolverObject.PropertyThrowException), - new ResolverObject()); + new ResolverObject(), + TypeKind.OBJECT); // source data is not of the type the resolver is for fieldContextBuilder.AddSourceData(new ResolverObject()); @@ -160,7 +166,8 @@ public async Task AsyncProperty_ValidSourceData_ReturnsData() var fieldContextBuilder = server.CreateGraphTypeFieldContextBuilder( nameof(ResolverObject.Address1Async), - new ResolverObject()); + new ResolverObject(), + TypeKind.OBJECT); var resolutionContext = fieldContextBuilder.CreateResolutionContext(); @@ -181,7 +188,8 @@ public async Task AsyncProperty_ThrowsException_FailsRequest() var fieldContextBuilder = server.CreateGraphTypeFieldContextBuilder( nameof(ResolverObject.AsyncPropException), - new ResolverObject()); + new ResolverObject(), + TypeKind.OBJECT); // source data is not of the type the resolver is for fieldContextBuilder.AddSourceData(new ResolverObject()); diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ArgumentTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ArgumentTemplateTests.cs index 46d2b99d8..175d3c84e 100644 --- a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ArgumentTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ArgumentTemplateTests.cs @@ -186,7 +186,7 @@ public void ArrayOfObjects_ThrowsException() { var template = this.ExtractParameterTemplate("arrayOfObjects", out var paramInfo); Assert.AreEqual(typeof(Person[]), template.Parameter.ParameterType); - Assert.AreEqual("[Input_Person]", template.TypeExpression.ToString()); + Assert.AreEqual("[Type]", template.TypeExpression.ToString()); Assert.AreEqual(null, template.DefaultValue); } @@ -195,7 +195,7 @@ public void ArrayOfEnumerableOfObject_ThrowsException() { var template = this.ExtractParameterTemplate("arrayOfEnumerableOfObject", out var paramInfo); Assert.AreEqual(typeof(IEnumerable[]), template.Parameter.ParameterType); - Assert.AreEqual("[[Input_Person]]", template.TypeExpression.ToString()); + Assert.AreEqual("[[Type]]", template.TypeExpression.ToString()); Assert.AreEqual(null, template.DefaultValue); } @@ -204,7 +204,7 @@ public void EnumerableArrayOfObjects_ThrowsException() { var template = this.ExtractParameterTemplate("enumerableOfArrayOfObjects", out var paramInfo); Assert.AreEqual(typeof(IEnumerable), template.Parameter.ParameterType); - Assert.AreEqual("[[Input_Person]]", template.TypeExpression.ToString()); + Assert.AreEqual("[[Type]]", template.TypeExpression.ToString()); Assert.AreEqual(null, template.DefaultValue); } @@ -213,7 +213,7 @@ public void EnumerableArrayOfArrryOfObjects_ParsesTypeExpression() { var template = this.ExtractParameterTemplate("arrayOfEnumerableOfArrayOfObjects", out var paramInfo); Assert.AreEqual(typeof(IEnumerable[]), template.Parameter.ParameterType); - Assert.AreEqual("[[[Input_Person]]]", template.TypeExpression.ToString()); + Assert.AreEqual("[[[Type]]]", template.TypeExpression.ToString()); Assert.AreEqual(null, template.DefaultValue); } @@ -222,7 +222,7 @@ public void StupidDeepArray_ParsesCorrectTypeExpression() { var template = this.ExtractParameterTemplate("deepArray", out var paramInfo); Assert.AreEqual(typeof(Person[][][][][][][][][][][][][][][][][][][]), template.Parameter.ParameterType); - Assert.AreEqual("[[[[[[[[[[[[[[[[[[[Input_Person]]]]]]]]]]]]]]]]]]]", template.TypeExpression.ToString()); + Assert.AreEqual("[[[[[[[[[[[[[[[[[[[Type]]]]]]]]]]]]]]]]]]]", template.TypeExpression.ToString()); Assert.AreEqual(null, template.DefaultValue); } @@ -243,7 +243,7 @@ public void CompatiableDeclaredTypeExpression_IsAllowed() // actual type expression "Int" // declared as Int! var template = this.ExtractParameterTemplate("compatiableTypeExpressionSingle", out var paramInfo); - Assert.AreEqual("Int!", template.TypeExpression.ToString()); + Assert.AreEqual("Type!", template.TypeExpression.ToString()); } [Test] @@ -252,7 +252,7 @@ public void CompatiableDeclaredTypeExpressionOnList_IsAllowed() // actual type expression [Int] // declared as [Int!]! var template = this.ExtractParameterTemplate("compatiableTypeExpressionList", out var paramInfo); - Assert.AreEqual("[Int!]!", template.TypeExpression.ToString()); + Assert.AreEqual("[Type!]!", template.TypeExpression.ToString()); } [Test] diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ControllerTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ControllerTemplateTests.cs index 8f63a30d5..2dbb3d5ee 100644 --- a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ControllerTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ControllerTemplateTests.cs @@ -65,7 +65,7 @@ public void Parse_OverloadedMethodsOnDifferentRoots_ParsesCorrectly() public void Parse_ReturnArrayOnAction_ParsesCorrectly() { var expectedTypeExpression = new GraphTypeExpression( - "String", + "Type", MetaGraphTypes.IsList); var template = new GraphControllerTemplate(typeof(ArrayReturnController)); @@ -80,10 +80,10 @@ public void Parse_ReturnArrayOnAction_ParsesCorrectly() } [Test] - public void Parse_ArrayOnInputParameter_ThrowsException() + public void Parse_ArrayOnInputParameter_ParsesCorrectly() { var expectedTypeExpression = new GraphTypeExpression( - "Input_" + typeof(TwoPropertyObject).FriendlyName(), + "Type", MetaGraphTypes.IsList); var template = new GraphControllerTemplate(typeof(ArrayInputParamController)); diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/DefaultUnionTemplateProviderTests.cs b/src/unit-tests/graphql-aspnet-tests/Internal/Templating/DefaultUnionTemplateProviderTests.cs deleted file mode 100644 index 87f9473b0..000000000 --- a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/DefaultUnionTemplateProviderTests.cs +++ /dev/null @@ -1,69 +0,0 @@ -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - -namespace GraphQL.AspNet.Tests.Internal.Templating -{ - using System; - using System.Collections.Generic; - using GraphQL.AspNet.Engine; - using GraphQL.AspNet.Execution.Exceptions; - using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Schemas.TypeSystem; - using NUnit.Framework; - - [TestFixture] - public class DefaultUnionTemplateProviderTests - { - public class FakeProxy : IGraphUnionProxy - { - public string Name - { - get => throw new NotImplementedException(); - set => throw new NotImplementedException(); - } - - public string Description - { - get => throw new NotImplementedException(); - set => throw new NotImplementedException(); - } - - public HashSet Types => throw new NotImplementedException(); - - public bool Publish - { - get => throw new NotImplementedException(); - set => throw new NotImplementedException(); - } - - public Type MapType(Type runtimeObjectType) => throw new NotImplementedException(); - } - - [Test] - public void ParseAKnownScalar_ThrowsException() - { - var templateProvider = new DefaultTypeTemplateProvider(); - Assert.Throws(() => - { - var template = templateProvider.ParseType(typeof(int), TypeKind.SCALAR); - }); - } - - [Test] - public void ParseAUnionProxy_ThrowsException() - { - var templateProvider = new DefaultTypeTemplateProvider(); - - Assert.Throws(() => - { - var template = templateProvider.ParseType(typeof(FakeProxy), TypeKind.UNION); - }); - } - } -} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/GraphTypeNamesTests.cs b/src/unit-tests/graphql-aspnet-tests/Internal/Templating/GraphTypeNamesTests.cs index 0e3ffe056..10beeaa29 100644 --- a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/GraphTypeNamesTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Internal/Templating/GraphTypeNamesTests.cs @@ -17,6 +17,7 @@ namespace GraphQL.AspNet.Tests.Internal.Templating using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Internal; using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Schemas.TypeSystem.Scalars; using GraphQL.AspNet.Tests.Internal.Templating.GraphTypeNameTestData; using NUnit.Framework; @@ -62,22 +63,16 @@ public void Item_WithAttribute_ReturnsAttributeDefinedName() } [Test] - public void Item_ScalarParsesToScalarName_Always() + public void ScalarNames_AreUnique() { - foreach (var scalarType in GraphQLProviders.ScalarProvider.ScalarInstanceTypes) + var nameSet = new HashSet(); + foreach (var scalarType in GlobalScalars.ScalarInstanceTypes) { var scalar = InstanceFactory.CreateInstance(scalarType) as IScalarGraphType; - var nameSet = new HashSet(); - var concreteType = GraphQLProviders.ScalarProvider.RetrieveConcreteType(scalar.Name); - foreach (var typeKind in Enum.GetValues(typeof(TypeKind)).Cast()) - { - var name = GraphTypeNames.ParseName(concreteType, typeKind); - if (!nameSet.Contains(name)) - nameSet.Add(name); - - Assert.AreEqual(1, nameSet.Count); - } + nameSet.Add(scalar.Name.ToLowerInvariant()); } + + Assert.AreEqual(GlobalScalars.ScalarInstanceTypes.Count(), nameSet.Count); } [Test] diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/MethodGraphFieldTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Internal/Templating/MethodGraphFieldTemplateTests.cs index 978c1b7f9..108a2af99 100644 --- a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/MethodGraphFieldTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Internal/Templating/MethodGraphFieldTemplateTests.cs @@ -159,7 +159,7 @@ public void ArrayFromMethod_YieldsTemplate() obj.Setup(x => x.InternalFullName).Returns("Item0"); var expectedTypeExpression = new GraphTypeExpression( - typeof(TwoPropertyObject).FriendlyName(), + "Type", MetaGraphTypes.IsList); var parent = obj.Object; diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectGraphTypeTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectGraphTypeTemplateTests.cs index cef64bcb3..de2ced3f2 100644 --- a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectGraphTypeTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectGraphTypeTemplateTests.cs @@ -296,7 +296,7 @@ public void Parse_ArrayProperty_ExtractsListOfCoreType() Assert.AreEqual(1, template.FieldTemplates.Count); var expectedTypeExpression = new GraphTypeExpression( - typeof(TwoPropertyObject).FriendlyName(), + "Type", MetaGraphTypes.IsList); Assert.AreEqual(1, template.FieldTemplates.Count()); @@ -343,36 +343,6 @@ public void Parse_InheritedProperties_AreValidFields() Assert.AreEqual("Property2", fieldTemplate2.Name); } - [Test] - public void Parse_WhenStructAKnownScalar_ThrowsException() - { - using var point = new GraphQLGlobalRestorePoint(); - - GraphQLProviders.ScalarProvider.RegisterCustomScalar(typeof(SimpleScalarStructGraphType)); - - Assert.Throws(() => - { - var template = new ObjectGraphTypeTemplate(typeof(SimpleScalarStructGraphType)); - template.Parse(); - template.ValidateOrThrow(); - }); - } - - [Test] - public void Parse_WhenObjectIsAKnownScalar_ThrowsException() - { - using var point = new GraphQLGlobalRestorePoint(); - - GraphQLProviders.ScalarProvider.RegisterCustomScalar(typeof(SimpleScalarObjectGraphType)); - - Assert.Throws(() => - { - var template = new ObjectGraphTypeTemplate(typeof(SimpleScalarObjectGraphType)); - template.Parse(); - template.ValidateOrThrow(); - }); - } - [Test] public void Parse_AssignedDirective_IsTemplatized() { diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/PropertyGraphFieldTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Internal/Templating/PropertyGraphFieldTemplateTests.cs index c3c93c3df..95a2f2c78 100644 --- a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/PropertyGraphFieldTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Internal/Templating/PropertyGraphFieldTemplateTests.cs @@ -172,7 +172,7 @@ public void Parse_BasicObject_PropertyReturnsArray_YieldsTemplate() obj.Setup(x => x.InternalFullName).Returns("Item0"); var expectedTypeExpression = new GraphTypeExpression( - typeof(TwoPropertyObject).FriendlyName(), + "Type", MetaGraphTypes.IsList); var parent = obj.Object; @@ -194,7 +194,7 @@ public void Parse_BasicObject_PropertyReturnsArrayOfKeyValuePair_YieldsTemplate( obj.Setup(x => x.InternalFullName).Returns("Item0"); var expectedTypeExpression = new GraphTypeExpression( - typeof(KeyValuePair).FriendlyGraphTypeName(), + "Type", // expression is expected to be unnamed at the template level MetaGraphTypes.IsList, MetaGraphTypes.IsNotNull); // structs can't be null diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/DefaultTypeTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/DefaultTypeTests.cs index 98a47fdff..3b71311e0 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/DefaultTypeTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/DefaultTypeTests.cs @@ -12,13 +12,14 @@ namespace GraphQL.AspNet.Tests.Schemas using System.Linq; using System.Reflection; using GraphQL.AspNet.Engine; + using GraphQL.AspNet.Schemas.TypeSystem.Scalars; using NUnit.Framework; [TestFixture] public class DefaultTypeTests { [Test] - public void Scalars_EnsureAllScalarNamesHaveAnAssociatedType() + public void Scalars_EnsureAllGlobalScalarNamesHaveAnAssociatedType() { var fields = typeof(Constants.ScalarNames) .GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy) @@ -27,8 +28,8 @@ public void Scalars_EnsureAllScalarNamesHaveAnAssociatedType() foreach (FieldInfo fi in fields) { Assert.IsTrue( - GraphQLProviders.ScalarProvider.IsScalar(fi.GetRawConstantValue()?.ToString()), - $"The scalar name '{fi.GetRawConstantValue()}' does not exist in the {{{nameof(DefaultScalarGraphTypeProvider)}}} collection."); + GlobalScalars.IsBuiltInScalar(fi.GetRawConstantValue()?.ToString()), + $"The scalar name '{fi.GetRawConstantValue()}' does not exist in the {{{nameof(GlobalScalars)}}} collection."); } } } diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GraphFieldCloningTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GraphFieldCloningTests.cs index 480b14460..39e61a7ec 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/GraphFieldCloningTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GraphFieldCloningTests.cs @@ -85,7 +85,6 @@ public void MethodField_PropertyCheck() Assert.AreEqual(field.Publish, clonedField.Publish); Assert.AreEqual("[type]/BobType/field1", clonedField.Route.Path); Assert.AreEqual(field.Mode, clonedField.Mode); - Assert.AreEqual(field.IsLeaf, clonedField.IsLeaf); Assert.AreEqual(field.IsDeprecated, clonedField.IsDeprecated); Assert.AreEqual(field.DeprecationReason, clonedField.DeprecationReason); Assert.AreEqual(field.Complexity, clonedField.Complexity); @@ -168,7 +167,6 @@ public void PropertyField_PropertyCheck() Assert.AreEqual(field.Publish, clonedField.Publish); Assert.AreEqual("[type]/BobType/field1", clonedField.Route.Path); Assert.AreEqual(field.Mode, clonedField.Mode); - Assert.AreEqual(field.IsLeaf, clonedField.IsLeaf); Assert.AreEqual(field.IsDeprecated, clonedField.IsDeprecated); Assert.AreEqual(field.DeprecationReason, clonedField.DeprecationReason); Assert.AreEqual(field.Complexity, clonedField.Complexity); diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GraphSchemaManagerTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GraphSchemaManagerTests.cs deleted file mode 100644 index b047d91f0..000000000 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/GraphSchemaManagerTests.cs +++ /dev/null @@ -1,849 +0,0 @@ -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - -namespace GraphQL.AspNet.Tests.Schemas -{ - using System; - using System.Collections.Generic; - using System.Linq; - using GraphQL.AspNet.Common.Extensions; - using GraphQL.AspNet.Execution.Exceptions; - using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal.Resolvers; - using GraphQL.AspNet.Schemas; - using GraphQL.AspNet.Schemas.Structural; - using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Tests.CommonHelpers; - using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; - using GraphQL.AspNet.Tests.Schemas.SchemaTestData; - using NUnit.Framework; - - [TestFixture] - public class GraphSchemaManagerTests - { - public enum RandomEnum - { - Value0, - Value1, - Value2, - } - - [Test] - public void RebuildIntrospectionData_AllDefaultFieldsAdded() - { - var schema = new GraphSchema() as ISchema; - var manager = new GraphSchemaManager(schema); - manager.RebuildIntrospectionData(); - - Assert.AreEqual(2, schema.KnownTypes.Count(x => x.Kind == TypeKind.SCALAR)); - Assert.IsNotNull(schema.KnownTypes.FindGraphType(Constants.ScalarNames.STRING)); - Assert.IsNotNull(schema.KnownTypes.FindGraphType(Constants.ScalarNames.BOOLEAN)); - - Assert.AreEqual(2, schema.KnownTypes.Count(x => x.Kind == TypeKind.ENUM)); - Assert.IsTrue(schema.KnownTypes.Contains(typeof(DirectiveLocation), TypeKind.ENUM)); - Assert.IsTrue(schema.KnownTypes.Contains(typeof(TypeKind), TypeKind.ENUM)); - - Assert.AreEqual(7, schema.KnownTypes.Count(x => x.Kind == TypeKind.OBJECT)); - Assert.IsTrue(schema.KnownTypes.Contains(Constants.ReservedNames.QUERY_TYPE_NAME)); - Assert.IsTrue(schema.KnownTypes.Contains(Constants.ReservedNames.DIRECTIVE_TYPE)); - Assert.IsTrue(schema.KnownTypes.Contains(Constants.ReservedNames.ENUM_VALUE_TYPE)); - Assert.IsTrue(schema.KnownTypes.Contains(Constants.ReservedNames.FIELD_TYPE)); - Assert.IsTrue(schema.KnownTypes.Contains(Constants.ReservedNames.INPUT_VALUE_TYPE)); - Assert.IsTrue(schema.KnownTypes.Contains(Constants.ReservedNames.SCHEMA_TYPE)); - Assert.IsTrue(schema.KnownTypes.Contains(Constants.ReservedNames.TYPE_TYPE)); - } - - [Test] - public void AddSingleQueryAction_AllDefaults_EnsureFieldStructure() - { - var schema = new GraphSchema() as ISchema; - schema.SetNoAlterationConfiguration(); - var manager = new GraphSchemaManager(schema); - manager.EnsureGraphType(); - - var action = GraphQLTemplateHelper.CreateFieldTemplate(nameof(SimpleMethodController.TestActionMethod)); - - // query root exists, mutation does not (nothing was added to it) - Assert.IsTrue(schema.Operations.ContainsKey(GraphOperationType.Query)); - Assert.IsFalse(schema.Operations.ContainsKey(GraphOperationType.Mutation)); - - // field for the controller exists - var topFieldName = nameof(SimpleMethodController).Replace(Constants.CommonSuffix.CONTROLLER_SUFFIX, string.Empty); - Assert.IsTrue(schema.Operations[GraphOperationType.Query].Fields.ContainsKey(topFieldName)); - - // ensure the field on the query is the right name (or throw) - var topField = schema.Operations[GraphOperationType.Query][topFieldName]; - Assert.IsNotNull(topField); - - var type = schema.KnownTypes.FindGraphType(topField) as IObjectGraphType; - - // ensure the action was put into the field collection of the controller operation - Assert.IsTrue(type.Fields.ContainsKey(action.Route.Name)); - } - - [Test] - public void AddSingleQueryAction_NestedRouting_EnsureFieldStructure() - { - var schema = new GraphSchema() as ISchema; - var manager = new GraphSchemaManager(schema); - manager.EnsureGraphType(); - - // query root exists, mutation does not (nothing was added to it) - Assert.IsTrue(schema.Operations.ContainsKey(GraphOperationType.Query)); - Assert.IsFalse(schema.Operations.ContainsKey(GraphOperationType.Mutation)); - - // field for the controller exists - var fieldName = "path0"; - Assert.IsTrue(schema.Operations[GraphOperationType.Query].Fields.ContainsKey(fieldName)); - - var topField = schema.Operations[GraphOperationType.Query][fieldName]; - var type = schema.KnownTypes.FindGraphType(topField) as IObjectGraphType; - Assert.IsNotNull(type); - Assert.AreEqual(2, type.Fields.Count); // declared field + __typename - - // field contains 1 field for first path segment - Assert.IsTrue(type.Fields.ContainsKey("path1")); - var firstField = type["path1"] as VirtualGraphField; - var firstFieldType = schema.KnownTypes.FindGraphType(firstField) as IObjectGraphType; - - Assert.IsNotNull(firstFieldType); - Assert.AreEqual(2, firstFieldType.Fields.Count); // declared field + __typename - Assert.IsTrue(firstFieldType.Fields.ContainsKey("path2")); - - var actionField = firstFieldType.Fields["path2"]; - Assert.IsNotNull(actionField); - Assert.IsNotNull(actionField.Resolver as GraphControllerActionResolver); - } - - [Test] - public void AddSingleQueryAction_AllDefaults_EnsureTypeStructure() - { - var schema = new GraphSchema() as ISchema; - var manager = new GraphSchemaManager(schema); - manager.EnsureGraphType(); - - // scalars for arguments on the method exists - Assert.IsNotNull(schema.KnownTypes.FindGraphType(Constants.ScalarNames.STRING)); - Assert.IsNotNull(schema.KnownTypes.FindGraphType(Constants.ScalarNames.INT)); - - // return type exists as an object type - var returnType = typeof(SimpleMethodController).GetMethod(nameof(SimpleMethodController.TestActionMethod)).ReturnType; - Assert.IsTrue(schema.KnownTypes.Contains(returnType, TypeKind.OBJECT)); - } - - [Test] - public void AddSingleQueryAction_NestedRouting_EnsureTypeStructure() - { - var schema = new GraphSchema(); - schema.SetNoAlterationConfiguration(); - - var manager = new GraphSchemaManager(schema); - manager.EnsureGraphType(); - - // query root exists, mutation does not (nothing was added to it) - Assert.AreEqual(1, schema.Operations.Count); - Assert.IsTrue(schema.Operations.ContainsKey(GraphOperationType.Query)); - Assert.IsFalse(schema.Operations.ContainsKey(GraphOperationType.Mutation)); - - Assert.AreEqual(8, schema.KnownTypes.Count); - - // expect 3 scalars - Assert.IsNotNull(schema.KnownTypes.FindGraphType(Constants.ScalarNames.FLOAT)); - Assert.IsNotNull(schema.KnownTypes.FindGraphType(Constants.ScalarNames.DATETIME)); - Assert.IsNotNull(schema.KnownTypes.FindGraphType(Constants.ScalarNames.STRING)); - - // expect 5 types to be generated - // ---------------------------------- - // the query operation type - // the top level field representing the controller, "path0" - // the middle level defined on the method "path1" - // the return type from the method itself - // the return type of the routes - Assert.IsTrue(schema.KnownTypes.Contains("Query")); - Assert.IsTrue(schema.KnownTypes.Contains("Query_path0")); - Assert.IsTrue(schema.KnownTypes.Contains("Query_path0_path1")); - Assert.IsTrue(schema.KnownTypes.Contains(nameof(TwoPropertyObjectV2))); - Assert.IsTrue(schema.KnownTypes.Contains(nameof(VirtualResolvedObject))); - - // expect 2 actual reference type to be assigned - // the return type from the method and the virtual result fro the route - // all others are virtual types in this instance - Assert.IsTrue(schema.KnownTypes.Contains(typeof(TwoPropertyObjectV2), TypeKind.OBJECT)); - Assert.IsTrue(schema.KnownTypes.Contains(typeof(VirtualResolvedObject), TypeKind.OBJECT)); - } - - [Test] - public void AddSingleQueryAction_NestedObjectsOnReturnType_EnsureAllTypesAreAdded() - { - var schema = new GraphSchema() as ISchema; - schema.SetNoAlterationConfiguration(); - var manager = new GraphSchemaManager(schema); - manager.EnsureGraphType(); - - // mutation root exists and query exists (it must by definition even if blank) - Assert.AreEqual(2, schema.Operations.Count); - Assert.IsTrue(schema.Operations.ContainsKey(GraphOperationType.Query)); - Assert.IsTrue(schema.Operations.ContainsKey(GraphOperationType.Mutation)); - - // 5 distinct scalars (int, uint, float, decimal, string) - Assert.AreEqual(5, schema.KnownTypes.Count(x => x.Kind == TypeKind.SCALAR)); - Assert.IsNotNull(schema.KnownTypes.FindGraphType(Constants.ScalarNames.STRING)); - Assert.IsNotNull(schema.KnownTypes.FindGraphType(Constants.ScalarNames.INT)); - Assert.IsNotNull(schema.KnownTypes.FindGraphType(Constants.ScalarNames.DECIMAL)); - Assert.IsNotNull(schema.KnownTypes.FindGraphType(Constants.ScalarNames.FLOAT)); - Assert.IsNotNull(schema.KnownTypes.FindGraphType(Constants.ScalarNames.UINT)); - - // 8 types - // ---------------------- - // mutation operation-type - // query operation-type - // path0 segment - // PersonData - // JobData - // AddressData - // CountryData - // VirtualResolvedObject - Assert.AreEqual(8, schema.KnownTypes.Count(x => x.Kind == TypeKind.OBJECT)); - - // expect a type for the root operation type - Assert.IsTrue(schema.KnownTypes.Contains(Constants.ReservedNames.MUTATION_TYPE_NAME)); - Assert.IsTrue(schema.KnownTypes.Contains(Constants.ReservedNames.QUERY_TYPE_NAME)); - - // expect a type representing the controller top level path - Assert.IsTrue(schema.KnownTypes.Contains($"{Constants.ReservedNames.MUTATION_TYPE_NAME}_path0")); - - // expect a type for the method return type - Assert.IsTrue(schema.KnownTypes.Contains(nameof(PersonData))); - - // person data contains job data - Assert.IsTrue(schema.KnownTypes.Contains(typeof(JobData), TypeKind.OBJECT)); - - // person data contains address data - Assert.IsTrue(schema.KnownTypes.Contains(typeof(AddressData), TypeKind.OBJECT)); - - // address data contains country data - Assert.IsTrue(schema.KnownTypes.Contains(typeof(CountryData), TypeKind.OBJECT)); - } - - [Test] - public void KitchenSinkController_SchemaInjection_FullFieldStructureAndTypeCheck() - { - var server = new TestServerBuilder(TestOptions.UseCodeDeclaredNames) - .AddGraphQL(o => - { - o.DeclarationOptions.DisableIntrospection = true; - o.AddType(); - }) - .Build(); - - var schema = server.Schema; - - // mutation and query - Assert.AreEqual(2, schema.Operations.Count); - - // Query Inspection - // ------------------------------ - - // the controller segment: "Query_path0" - // the method "myActionOperation" should register as a root query - // The Query root itself contains the `__typename` metafield - Assert.AreEqual(3, schema.Operations[GraphOperationType.Query].Fields.Count); - var controllerQueryField = schema.Operations[GraphOperationType.Query]["path0"]; - var methodAsQueryRootField = schema.Operations[GraphOperationType.Query]["myActionOperation"]; - Assert.IsNotNull(schema.Operations[GraphOperationType.Query][Constants.ReservedNames.TYPENAME_FIELD]); - - // deep inspection of the created controller-query-field - Assert.IsNotNull(controllerQueryField); - Assert.AreEqual(0, controllerQueryField.Arguments.Count); - Assert.AreEqual("Kitchen sinks are great", controllerQueryField.Description); - - // the top level controller field should have one field on it - // created from the sub path on the controller route definition "path1" - // that field should be registered as a virtual field - var controllerQueryFieldType = schema.KnownTypes.FindGraphType(controllerQueryField) as IObjectGraphType; - Assert.AreEqual(2, controllerQueryFieldType.Fields.Count); // declared field + __typename - var queryPath1 = controllerQueryFieldType.Fields["path1"]; - Assert.IsTrue(queryPath1 is VirtualGraphField); - Assert.AreEqual(string.Empty, queryPath1.Description); - - // the virtual field (path1) should have two real actions (TestActionMethod, TestAction2) - // and 1 virtual field ("path2") hung off it - var queryPath1Type = schema.KnownTypes.FindGraphType(queryPath1) as IObjectGraphType; - Assert.IsTrue(queryPath1Type is VirtualObjectGraphType); - Assert.AreEqual(3, queryPath1Type.Fields.Count); // declared fields + __typename - - Assert.IsTrue(queryPath1Type.Fields.Any(x => x.Name == "TestActionMethod")); - Assert.IsTrue(queryPath1Type.Fields.Any(x => x.Name == "TestAction2")); - - // path 2 is only declared on mutations - Assert.IsFalse(queryPath1Type.Fields.ContainsKey("path2")); - - // top level query field made from a controller method - Assert.IsNotNull(methodAsQueryRootField); - Assert.AreEqual("myActionOperation", methodAsQueryRootField.Name); - Assert.AreEqual("This is my\n Top Level Query Field", methodAsQueryRootField.Description); - - // Mutation Inspection - // ------------------------------ - var controllerMutationField = schema.Operations[GraphOperationType.Mutation]["path0"]; - var methodAsMutationTopLevelField = schema.Operations[GraphOperationType.Mutation]["SupeMutation"]; - - // deep inspection of the created controller-mutation-field - Assert.IsNotNull(controllerMutationField); - Assert.AreEqual(0, controllerMutationField.Arguments.Count); - Assert.AreEqual("Kitchen sinks are great", controllerMutationField.Description); - - // the controller field on the mutation side should have one field on it - // created from the sub path on the controller route definition "path1" - // that field should be registered as a virtual field - var controllerMutationFieldType = schema.KnownTypes.FindGraphType(controllerMutationField) as IObjectGraphType; - Assert.AreEqual(2, controllerMutationFieldType.Fields.Count); // declared field + __typename - var mutationPath1 = controllerMutationFieldType.Fields["path1"]; - Assert.IsTrue(mutationPath1 is VirtualGraphField); - Assert.AreEqual(string.Empty, mutationPath1.Description); - - // walk down the mutationPath through all its nested layers to the action method - // let an exception be thrown (incorrectly) if any path segment doesnt exist - var mutationPath1Type = schema.KnownTypes.FindGraphType(mutationPath1) as IObjectGraphType; - var childField = mutationPath1Type.Fields["path2"]; - var childFieldType = schema.KnownTypes.FindGraphType(childField) as IObjectGraphType; - Assert.AreEqual(string.Empty, childField.Description); - Assert.IsFalse(childField.IsDeprecated); - - childField = childFieldType.Fields["PAth3"]; - childFieldType = schema.KnownTypes.FindGraphType(childField) as IObjectGraphType; - Assert.AreEqual(string.Empty, childField.Description); - Assert.IsFalse(childField.IsDeprecated); - - childField = childFieldType.Fields["PaTh4"]; - childFieldType = schema.KnownTypes.FindGraphType(childField) as IObjectGraphType; - Assert.AreEqual(string.Empty, childField.Description); - Assert.IsFalse(childField.IsDeprecated); - - childField = childFieldType.Fields["PAT_H5"]; - childFieldType = schema.KnownTypes.FindGraphType(childField) as IObjectGraphType; - Assert.AreEqual(string.Empty, childField.Description); - Assert.IsFalse(childField.IsDeprecated); - - childField = childFieldType.Fields["pathSix"]; - childFieldType = schema.KnownTypes.FindGraphType(childField) as IObjectGraphType; - Assert.AreEqual(string.Empty, childField.Description); - Assert.IsFalse(childField.IsDeprecated); - - var mutationAction = childFieldType.Fields["deepNestedMethod"]; - Assert.AreEqual("This is a mutation", mutationAction.Description); - Assert.IsTrue(mutationAction.IsDeprecated); - Assert.AreEqual("To be removed tomorrow", mutationAction.DeprecationReason); - - // check the top level mutation field - Assert.AreEqual("SupeMutation", methodAsMutationTopLevelField.Name); - Assert.AreEqual("This is my\n Top Level MUtation Field!@@!!", methodAsMutationTopLevelField.Description); - - // Type Checks - // ----------------------------------------------------- - // scalars (2): string, int (from TwoPropertyObject & deprecatedDirective) - // scalars (2): float, datetime (from TwoPropertyObjectV2) - // scalars (2): ulong, long (from method declarations) - // scalars (1): decimal (from CompletePropertyObject) - // scalars (1): bool (from @include and @skip directives) - // the nullable types resolve to their non-nullable scalar in the type list - var scalars = schema.KnownTypes.Where(x => x.Kind == TypeKind.SCALAR).ToList(); - Assert.AreEqual(8, schema.KnownTypes.Count(x => x.Kind == TypeKind.SCALAR)); - Assert.IsNotNull(schema.KnownTypes.FindGraphType(typeof(string))); - Assert.IsNotNull(schema.KnownTypes.FindGraphType(typeof(int))); - Assert.IsNotNull(schema.KnownTypes.FindGraphType(typeof(ulong))); - Assert.IsNotNull(schema.KnownTypes.FindGraphType(typeof(DateTime))); - Assert.IsNotNull(schema.KnownTypes.FindGraphType(typeof(DateTime?))); - Assert.IsNotNull(schema.KnownTypes.FindGraphType(typeof(long))); - Assert.IsNotNull(schema.KnownTypes.FindGraphType(typeof(long?))); - Assert.IsNotNull(schema.KnownTypes.FindGraphType(typeof(decimal))); - - // should not have double - Assert.IsNull(schema.KnownTypes.FindGraphType(typeof(double))); - - // enumerations - Assert.AreEqual(1, schema.KnownTypes.Count(x => x.Kind == TypeKind.ENUM)); - Assert.IsTrue(schema.KnownTypes.Contains(typeof(TestEnumerationOptions), TypeKind.ENUM)); - - // input type checks (TwoPropertyObject, EmptyObject) - Assert.AreEqual(2, schema.KnownTypes.Count(x => x.Kind == TypeKind.INPUT_OBJECT)); - Assert.IsTrue(schema.KnownTypes.Contains(typeof(EmptyObject), TypeKind.INPUT_OBJECT)); - Assert.IsTrue(schema.KnownTypes.Contains(typeof(TwoPropertyObject), TypeKind.INPUT_OBJECT)); - - // general object types - var concreteTypes = schema.KnownTypes.Where(x => (x is ObjectGraphType)).ToList(); - Assert.AreEqual(5, concreteTypes.Count); - Assert.IsTrue(schema.KnownTypes.Contains(typeof(Person), TypeKind.OBJECT)); - Assert.IsTrue(schema.KnownTypes.Contains(typeof(CompletePropertyObject), TypeKind.OBJECT)); - Assert.IsTrue(schema.KnownTypes.Contains(typeof(TwoPropertyObject), TypeKind.OBJECT)); - Assert.IsTrue(schema.KnownTypes.Contains(typeof(TwoPropertyObjectV2), TypeKind.OBJECT)); - Assert.IsTrue(schema.KnownTypes.Contains(typeof(VirtualResolvedObject), TypeKind.OBJECT)); - - // 9 "route" types should ahve been created - // ----------------------------- - // 1. controller query field (path0) - // 2. query virtual path segment path1 - // 3. controller mutation field (path0) - // 4. mutation virtual path segment path1 - // 5. mutation virtual path segment path2 - // 6. mutation virtual path segment PAth3 - // 7. mutation virtual path segment PaTh4 - // 8. mutation virtual path segment PAT_H5 - // 9. mutation virtual path segment pathSix - var virtualTypes = schema.KnownTypes.Where(x => x is VirtualObjectGraphType).ToList(); - Assert.AreEqual(9, virtualTypes.Count); - - // pathSix should have one "real" field, the method named 'deepNestedMethod' - var pathSix = virtualTypes.FirstOrDefault(x => x.Name.Contains("pathSix")) as IObjectGraphType; - Assert.IsNotNull(pathSix); - Assert.AreEqual(2, pathSix.Fields.Count); // declared field + __typename - Assert.IsNotNull(pathSix["deepNestedMethod"]); - - // query_path1 should have two "real" fields, the method named 'TestActionMethod' and 'TestAction2' - var querPath1 = virtualTypes.FirstOrDefault(x => x.Name.Contains("Query_path0_path1")) as IObjectGraphType; - - Assert.IsNotNull(querPath1); - Assert.AreEqual(3, querPath1.Fields.Count); // declared field + __typename - Assert.IsNotNull(querPath1[nameof(KitchenSinkController.TestActionMethod)]); - Assert.IsNotNull(querPath1["TestAction2"]); - } - - [Test] - public void EnsureGraphType_NormalObject_IsAddedWithTypeReference() - { - var schema = new GraphSchema() as ISchema; - var manager = new GraphSchemaManager(schema); - - manager.EnsureGraphType(typeof(CountryData)); - - // CountryData, string, float?, Query - Assert.AreEqual(4, schema.KnownTypes.Count); - Assert.AreEqual(3, schema.KnownTypes.TypeReferences.Count()); - - Assert.IsTrue(schema.KnownTypes.Contains(typeof(CountryData), TypeKind.OBJECT)); - Assert.IsTrue(schema.KnownTypes.Contains("CountryData")); - } - - [Test] - public void EnsureGraphType_Enum_WithNoKindSupplied_IsAddedCorrectly() - { - var schema = new GraphSchema() as ISchema; - var manager = new GraphSchemaManager(schema); - manager.EnsureGraphType(typeof(RandomEnum)); - Assert.AreEqual(3, schema.KnownTypes.Count); // added type + query + string - Assert.IsTrue(schema.KnownTypes.Contains(typeof(RandomEnum))); - Assert.IsTrue(schema.KnownTypes.Contains(typeof(string))); - } - - [Test] - public void EnsureGraphType_Enum_WithKindSupplied_IsAddedCorrectly() - { - var schema = new GraphSchema() as ISchema; - var manager = new GraphSchemaManager(schema); - manager.EnsureGraphType(typeof(RandomEnum), TypeKind.ENUM); - Assert.AreEqual(3, schema.KnownTypes.Count); // added type + query + string - Assert.IsTrue(schema.KnownTypes.Contains(typeof(RandomEnum), TypeKind.ENUM)); - Assert.IsTrue(schema.KnownTypes.Contains(typeof(string), TypeKind.SCALAR)); - } - - [Test] - public void EnsureGraphType_Enum_WithIncorrectKindSupplied_ThrowsException() - { - var schema = new GraphSchema() as ISchema; - var manager = new GraphSchemaManager(schema); - Assert.Throws(() => - { - manager.EnsureGraphType(typeof(RandomEnum), TypeKind.SCALAR); - }); - } - - [Test] - public void EnsureGraphType_Enum_WithIncorrectKindSupplied_ThatIsCoercable_AddsCorrectly() - { - var schema = new GraphSchema() as ISchema; - var manager = new GraphSchemaManager(schema); - - // object will be coerced to enum - manager.EnsureGraphType(typeof(RandomEnum), TypeKind.OBJECT); - Assert.AreEqual(3, schema.KnownTypes.Count); // added type + query + string - Assert.IsTrue(schema.KnownTypes.Contains(typeof(string), TypeKind.SCALAR)); - Assert.IsTrue(schema.KnownTypes.Contains(typeof(RandomEnum), TypeKind.ENUM)); - Assert.IsFalse(schema.KnownTypes.Contains(typeof(RandomEnum), TypeKind.OBJECT)); - } - - [Test] - public void EnsureGraphType_Scalar_WithNoKindSupplied_IsAddedCorrectly() - { - var schema = new GraphSchema() as ISchema; - var manager = new GraphSchemaManager(schema); - manager.EnsureGraphType(typeof(string)); - Assert.AreEqual(2, schema.KnownTypes.Count); // added type + query - Assert.IsTrue(schema.KnownTypes.Contains(typeof(string))); - } - - [Test] - public void EnsureGraphType_Scalar_WithKindSupplied_IsAddedCorrectly() - { - var schema = new GraphSchema() as ISchema; - var manager = new GraphSchemaManager(schema); - manager.EnsureGraphType(typeof(string), TypeKind.SCALAR); - Assert.AreEqual(2, schema.KnownTypes.Count); // added type + query - Assert.IsTrue(schema.KnownTypes.Contains(typeof(string), TypeKind.SCALAR)); - } - - [Test] - public void EnsureGraphType_Scalar_WithIncorrectKindSupplied_ThrowsException() - { - var schema = new GraphSchema() as ISchema; - var manager = new GraphSchemaManager(schema); - Assert.Throws(() => - { - manager.EnsureGraphType(typeof(string), TypeKind.ENUM); - }); - } - - [Test] - public void EnsureGraphType_ScalarTwice_EndsUpInScalarCollectionOnce() - { - var schema = new GraphSchema() as ISchema; - var manager = new GraphSchemaManager(schema); - manager.EnsureGraphType(typeof(int)); - manager.EnsureGraphType(typeof(int)); - - Assert.AreEqual(3, schema.KnownTypes.Count); // added type + query + string - Assert.IsNotNull(schema.KnownTypes.FindGraphType(typeof(int))); - Assert.IsNotNull(schema.KnownTypes.FindGraphType(Constants.ScalarNames.INT)); - Assert.IsNotNull(schema.KnownTypes.FindGraphType(Constants.ScalarNames.STRING)); - Assert.IsTrue(schema.KnownTypes.Contains(typeof(int))); - } - - [Test] - public void EnsureGraphType_TwoScalar_EndsUpInScalarCollectionOnceEach() - { - var schema = new GraphSchema() as ISchema; - var manager = new GraphSchemaManager(schema); - manager.EnsureGraphType(typeof(int)); - manager.EnsureGraphType(typeof(long)); - - Assert.AreEqual(4, schema.KnownTypes.Count); // added types + query + string - Assert.IsNotNull(schema.KnownTypes.FindGraphType(typeof(int))); - Assert.IsNotNull(schema.KnownTypes.FindGraphType(Constants.ScalarNames.INT)); - Assert.IsNotNull(schema.KnownTypes.FindGraphType(typeof(long))); - Assert.IsNotNull(schema.KnownTypes.FindGraphType(Constants.ScalarNames.LONG)); - Assert.IsNotNull(schema.KnownTypes.FindGraphType(Constants.ScalarNames.STRING)); - } - - [Test] - public void EnsureGraphType_IEnumerableT_EndsWithTInGraphType() - { - var schema = new GraphSchema() as ISchema; - var manager = new GraphSchemaManager(schema); - manager.EnsureGraphType(typeof(IEnumerable)); - - Assert.AreEqual(3, schema.KnownTypes.Count); // added type + query + string - Assert.IsTrue(schema.KnownTypes.Contains(typeof(int))); - Assert.IsTrue(schema.KnownTypes.Contains(Constants.ScalarNames.INT)); - Assert.IsTrue(schema.KnownTypes.Contains(Constants.ScalarNames.STRING)); - } - - [Test] - public void EnsureGraphType_ListT_EndsWithTInGraphType() - { - var schema = new GraphSchema() as ISchema; - var manager = new GraphSchemaManager(schema); - manager.EnsureGraphType(typeof(List)); - - Assert.AreEqual(3, schema.KnownTypes.Count); // added type + query + string - Assert.IsTrue(schema.KnownTypes.Contains(typeof(int))); - Assert.IsTrue(schema.KnownTypes.Contains(Constants.ScalarNames.INT)); - Assert.IsTrue(schema.KnownTypes.Contains(Constants.ScalarNames.STRING)); - } - - [Test] - public void EnsureGraphType_ListT_AfterManualAddOfScalar_Succeeds() - { - var schema = new GraphSchema() as ISchema; - var manager = new GraphSchemaManager(schema); - - var intScalar = GraphQLProviders.ScalarProvider.CreateScalar(typeof(int)); - schema.KnownTypes.EnsureGraphType(intScalar, typeof(int)); - manager.EnsureGraphType(typeof(List)); - - Assert.AreEqual(3, schema.KnownTypes.Count); // added type + query + string - Assert.IsTrue(schema.KnownTypes.Contains(typeof(int))); - Assert.IsTrue(schema.KnownTypes.Contains(Constants.ScalarNames.INT)); - Assert.IsTrue(schema.KnownTypes.Contains(Constants.ScalarNames.STRING)); - - var includedType = schema.KnownTypes.FindGraphType(typeof(int)); - Assert.AreEqual(includedType, intScalar); - } - - [Test] - public void EnsureGraphType_DictionaryTK_ThrowsExeption() - { - Assert.Throws(() => - { - var schema = new GraphSchema() as ISchema; - var manager = new GraphSchemaManager(schema); - manager.EnsureGraphType(typeof(Dictionary)); - }); - } - - [Test] - public void EnsureGraphType_WithSubTypes_AreAddedCorrectly() - { - var schema = new GraphSchema() as ISchema; - schema.SetNoAlterationConfiguration(); - var manager = new GraphSchemaManager(schema); - manager.EnsureGraphType(typeof(PersonData)); - - Assert.AreEqual(10, schema.KnownTypes.Count); // added types + query - Assert.IsTrue(schema.KnownTypes.Contains(typeof(AddressData))); - Assert.IsTrue(schema.KnownTypes.Contains(typeof(PersonData))); - Assert.IsTrue(schema.KnownTypes.Contains(typeof(CountryData))); - Assert.IsTrue(schema.KnownTypes.Contains(typeof(JobData))); - Assert.IsTrue(schema.KnownTypes.Contains(typeof(string))); - Assert.IsTrue(schema.KnownTypes.Contains(typeof(float))); - Assert.IsTrue(schema.KnownTypes.Contains(typeof(float?))); - Assert.IsTrue(schema.KnownTypes.Contains(typeof(uint))); - Assert.IsTrue(schema.KnownTypes.Contains(typeof(decimal))); - } - - [Test] - public void EnsureGraphType_WhenRootControllerActionOfSameNameAsAType_IsAdded_ThrowsException() - { - var schema = new GraphSchema() as ISchema; - schema.SetNoAlterationConfiguration(); - var manager = new GraphSchemaManager(schema); - - // ThingController declares two routes - // [Query]/Thing (A root operation) - // [Query]/Thing/moreData (a nested operation under a "thing" controller) - // there is also a type [Type]/Thing in the schema - // - // this should create an impossible situation where - // [Query]/Thing returns the "Thing" graph type - // and the controller will try to nest "moreData" into this OBJECT type - // which should fail - Assert.Throws(() => - { - manager.EnsureGraphType(); - }); - } - - [Test] - public void EnsureGraphType_WhenTwoControllersDecalreTheNameRootRouteName_AMeaningfulExceptionisThrown() - { - var schema = new GraphSchema() as ISchema; - schema.SetNoAlterationConfiguration(); - var manager = new GraphSchemaManager(schema); - - manager.EnsureGraphType(); - - Assert.Throws(() => - { - manager.EnsureGraphType(); - }); - } - - [Test] - public void EnsureGraphType_WhenControllerReturnTypeIsGraphTypeIsAFlatArray_IsAddedCorrectly() - { - var schema = new GraphSchema() as ISchema; - schema.SetNoAlterationConfiguration(); - - var manager = new GraphSchemaManager(schema); - manager.EnsureGraphType(); - - Assert.AreEqual(4, schema.KnownTypes.Count); // added types + query - Assert.IsTrue(schema.KnownTypes.Contains(typeof(int))); - Assert.IsTrue(schema.KnownTypes.Contains(typeof(string))); - Assert.IsTrue(schema.KnownTypes.Contains(typeof(TwoPropertyObject))); - } - - [Test] - public void EnsureGraphType_WhenControllerReturnTypeDeclarationIsGraphTypeIsAFlatArray_IsAddedCorrectly() - { - var schema = new GraphSchema() as ISchema; - schema.SetNoAlterationConfiguration(); - - var manager = new GraphSchemaManager(schema); - manager.EnsureGraphType(); - - Assert.AreEqual(4, schema.KnownTypes.Count); // added types + query - Assert.IsTrue(schema.KnownTypes.Contains(typeof(int))); - Assert.IsTrue(schema.KnownTypes.Contains(typeof(string))); - Assert.IsTrue(schema.KnownTypes.Contains(typeof(TwoPropertyObject))); - } - - [Test] - public void EnsureGraphType_WhenPropertyIsFlatArray_IsAddedCorrectly() - { - var schema = new GraphSchema() as ISchema; - schema.SetNoAlterationConfiguration(); - - var manager = new GraphSchemaManager(schema); - manager.EnsureGraphType(); - - Assert.AreEqual(5, schema.KnownTypes.Count); // added types + query - Assert.IsTrue(schema.KnownTypes.Contains(typeof(ArrayPropertyObject))); - Assert.IsTrue(schema.KnownTypes.Contains(typeof(string))); - Assert.IsTrue(schema.KnownTypes.Contains(typeof(int))); - Assert.IsTrue(schema.KnownTypes.Contains(typeof(TwoPropertyObject))); - } - - [Test] - public void EnsureGraphType_WhenMethodReturnIsFlatArray_IsAddedCorrectly() - { - var schema = new GraphSchema() as ISchema; - schema.SetNoAlterationConfiguration(); - - var manager = new GraphSchemaManager(schema); - manager.EnsureGraphType(); - - Assert.AreEqual(5, schema.KnownTypes.Count); // added types + query - - Assert.IsTrue(schema.KnownTypes.Contains(typeof(ArrayMethodObject))); - Assert.IsTrue(schema.KnownTypes.Contains(typeof(string))); - Assert.IsTrue(schema.KnownTypes.Contains(typeof(int))); - Assert.IsTrue(schema.KnownTypes.Contains(typeof(TwoPropertyObject))); - } - - [Test] - public void EnsureGraphType_WhenContainsAGenericType_IsAddedCorrectly() - { - var schema = new GraphSchema() as ISchema; - schema.SetNoAlterationConfiguration(); - - var manager = new GraphSchemaManager(schema); - manager.EnsureGraphType(); - - Assert.AreEqual(5, schema.KnownTypes.Count); // added types + query - - Assert.IsTrue(schema.KnownTypes.Contains(typeof(KeyValuePairObject))); - Assert.IsTrue(schema.KnownTypes.Contains(typeof(string))); - Assert.IsTrue(schema.KnownTypes.Contains(typeof(int))); - Assert.IsTrue(schema.KnownTypes.Contains(typeof(KeyValuePair))); - } - - [Test] - public void EnsureGraphType_WhenIsAGenericType_IsAddedCorrectly() - { - var schema = new GraphSchema() as ISchema; - schema.SetNoAlterationConfiguration(); - - var manager = new GraphSchemaManager(schema); - manager.EnsureGraphType>(); - manager.EnsureGraphType>(); - - Assert.AreEqual(7, schema.KnownTypes.Count); // added types + query - - Assert.IsTrue(schema.KnownTypes.Contains(typeof(TwoPropertyGenericObject))); - Assert.IsTrue(schema.KnownTypes.Contains(typeof(TwoPropertyGenericObject))); - Assert.IsTrue(schema.KnownTypes.Contains(typeof(int))); - Assert.IsTrue(schema.KnownTypes.Contains(typeof(string))); - Assert.IsTrue(schema.KnownTypes.Contains(typeof(DateTime))); - Assert.IsTrue(schema.KnownTypes.Contains(typeof(double))); - } - - [Test] - public void EnsureGraphType_WhenIsAGenericType_WithListTypeParam_IsAddedCorrectly() - { - var schema = new GraphSchema() as ISchema; - schema.SetNoAlterationConfiguration(); - - var manager = new GraphSchemaManager(schema); - manager.EnsureGraphType>(); - - Assert.AreEqual(4, schema.KnownTypes.Count); // added types + query - - Assert.IsTrue(schema.KnownTypes.Contains(typeof(TwoPropertyGenericObject))); - Assert.IsTrue(schema.KnownTypes.Contains(typeof(int))); - Assert.IsTrue(schema.KnownTypes.Contains(typeof(string))); - - var type = schema.KnownTypes.FindGraphType(typeof(TwoPropertyGenericObject)); - } - - [Test] - public void EnsureGraphType_WhenIsAGenericType_ButDeclaresACustomName_ThrowsException() - { - var schema = new GraphSchema() as ISchema; - schema.SetNoAlterationConfiguration(); - - var manager = new GraphSchemaManager(schema); - try - { - manager.EnsureGraphType>(); - } - catch (GraphTypeDeclarationException ex) - { - var name = typeof(GenericObjectTypeWithGraphTypeName).GetGenericTypeDefinition().FriendlyName(); - Assert.IsTrue(ex.Message.Contains(name)); - return; - } - - Assert.Fail("No exception was thrown when one was expected."); - } - - [Test] - public void AttemptingToExtendATypeDirectly_AndThroughInterface_ThrowsException() - { - var schema = new GraphSchema() as ISchema; - schema.SetNoAlterationConfiguration(); - - var manager = new GraphSchemaManager(schema); - - try - { - manager.EnsureGraphType(); - } - catch (GraphTypeDeclarationException ex) - { - var name = typeof(TwoPropertyObject).FriendlyName(); - Assert.IsTrue(ex.Message.Contains(name)); - return; - } - - Assert.Fail("No exception was thrown when one was expected."); - } - - [Test] - public void EnsureGraphType_WhenATypeWithNoStringsIsAdded_StringIsStillAddedBecauseOfTypeName() - { - var schema = new GraphSchema() as ISchema; - schema.SetNoAlterationConfiguration(); - - var manager = new GraphSchemaManager(schema); - - manager.EnsureGraphType(); - - // query, ObjectWittNoStrings, int, string - Assert.AreEqual(4, schema.KnownTypes.Count); - - Assert.AreEqual(1, schema.Operations.Values.Count); - Assert.IsTrue(schema.KnownTypes.Contains(typeof(ObjectWithNoStrings))); // the item itself - Assert.IsTrue(schema.KnownTypes.Contains(typeof(int))); // for the declared property - Assert.IsTrue(schema.KnownTypes.Contains(typeof(string))); // for __typename - } - - [Test] - public void ValidateSchemaIntegrity_WhenInterfaceArgument_OnField_ThrowsException() - { - var schema = new GraphSchema(); - var manager = new GraphSchemaManager(schema); - manager.EnsureGraphType(); - - var ex = Assert.Throws(() => - { - manager.ValidateSchemaIntegrity(); - }); - } - } -} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaLanguageGeneratorTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaLanguageGeneratorTests.cs index 8f96ed6d4..c81eb3179 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaLanguageGeneratorTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaLanguageGeneratorTests.cs @@ -19,6 +19,7 @@ namespace GraphQL.AspNet.Tests.Schemas using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Schemas.TypeSystem.Scalars; using GraphQL.AspNet.Tests.Framework; using GraphQL.AspNet.Tests.Framework.CommonHelpers; using GraphQL.AspNet.Tests.Schemas.QueryLanguageTestData; @@ -234,8 +235,7 @@ public SchemaLanguageGeneratorTests() // ensure all scalars represented _unUsedScalarTypes = new List(); - var scalarProvider = new DefaultScalarGraphTypeProvider(); - foreach (var type in scalarProvider.ConcreteTypes) + foreach (var type in GlobalScalars.ConcreteTypes) { if (Validation.IsNullableOfT(type)) continue; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTypeCollectionInterefaceImplementationTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTypeCollectionInterefaceImplementationTests.cs index 0e0804104..0d4b251d1 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTypeCollectionInterefaceImplementationTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTypeCollectionInterefaceImplementationTests.cs @@ -19,6 +19,9 @@ namespace GraphQL.AspNet.Tests.Schemas using GraphQL.AspNet.Tests.Framework; using GraphQL.AspNet.Tests.Schemas.SchemaTestData.InterfaceRegistrationTestData; using NUnit.Framework; + using GraphQL.AspNet.Schemas.Generation; + using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Schemas; [TestFixture] [FixtureLifeCycle(LifeCycle.InstancePerTestCase)] @@ -75,7 +78,10 @@ public SchemaTypeCollectionInterefaceImplementationTests() _donut = this.MakeGraphType(typeof(Donut), TypeKind.OBJECT) as IObjectGraphType; // type extension - var template = GraphQLProviders.TemplateProvider.ParseType(typeof(PastryExtensionController)) as IGraphControllerTemplate; + var template = new GraphControllerTemplate(typeof(PastryExtensionController)) as IGraphControllerTemplate; + template.Parse(); + template.ValidateOrThrow(); + var hasSugarTemplate = template.Extensions.FirstOrDefault(x => x.InternalName == nameof(PastryExtensionController.HasSugarExtension)); var hasGlazeTemplate = template.Extensions.FirstOrDefault(x => x.InternalName == nameof(PastryExtensionController.HasGlazeExtension)); var hasDoubleGlazeTemplate = template.Extensions.FirstOrDefault(x => x.InternalName == nameof(PastryExtensionController.HasDoubleGlazeExtension)); @@ -94,14 +100,22 @@ private IGraphType MakeGraphType(Type type, TypeKind kind) { var testServer = new TestServerBuilder().Build(); - var maker = GraphQLProviders.GraphTypeMakerProvider.CreateTypeMaker(testServer.Schema, kind); - return maker.CreateGraphType(type).GraphType; + var factory = new DefaultGraphQLTypeMakerFactory(); + factory.Initialize(testServer.Schema); + + var template = factory.MakeTemplate(type, kind); + var maker = factory.CreateTypeMaker(type, kind); + return maker.CreateGraphType(template).GraphType; } private IGraphField MakeGraphField(IGraphFieldTemplate fieldTemplate) { var testServer = new TestServerBuilder().Build(); - var maker = new GraphFieldMaker(testServer.Schema); + + var factory = new DefaultGraphQLTypeMakerFactory(); + factory.Initialize(testServer.Schema); + + var maker = factory.CreateFieldMaker(); return maker.CreateField(fieldTemplate).Field; } diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTypeCollectionTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTypeCollectionTests.cs index c6caabcb3..7def0c236 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTypeCollectionTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTypeCollectionTests.cs @@ -24,6 +24,11 @@ namespace GraphQL.AspNet.Tests.Schemas using GraphQL.AspNet.Tests.Schemas.SchemaTestData; using NUnit.Framework; using GraphQL.AspNet.Tests.Framework.Interfaces; + using GraphQL.AspNet.Schemas.Generation; + using GraphQL.AspNet.Schemas.Generation.TypeMakers; + using GraphQL.AspNet.Internal.TypeTemplates; + using Microsoft.AspNetCore.Hosting.Server; + using GraphQL.AspNet.Schemas; [TestFixture] public class SchemaTypeCollectionTests @@ -38,24 +43,21 @@ public enum RandomEnum private IGraphType MakeGraphType(Type type, TypeKind kind) { var testServer = new TestServerBuilder().Build(); + var factory = new DefaultGraphQLTypeMakerFactory(); + factory.Initialize(testServer.Schema); - switch (kind) - { - case TypeKind.UNION: - var proxy = GraphQLProviders.GraphTypeMakerProvider.CreateUnionProxyFromType(type); - var unionMaker = GraphQLProviders.GraphTypeMakerProvider.CreateUnionMaker(testServer.Schema); - return unionMaker.CreateUnionFromProxy(proxy).GraphType; - - default: - var maker = GraphQLProviders.GraphTypeMakerProvider.CreateTypeMaker(testServer.Schema, kind); - return maker.CreateGraphType(type).GraphType; - } + var template = GraphQLTemplateHelper.CreateGraphTypeTemplate(type, kind); + return factory.CreateTypeMaker(type, kind).CreateGraphType(template).GraphType; } private IGraphField MakeGraphField(IGraphFieldTemplate fieldTemplate) { var testServer = new TestServerBuilder().Build(); - var maker = new GraphFieldMaker(testServer.Schema); + var factory = new DefaultGraphQLTypeMakerFactory(); + factory.Initialize(testServer.Schema); + + + var maker = new GraphFieldMaker(testServer.Schema, factory); return maker.CreateField(fieldTemplate).Field; } @@ -220,7 +222,10 @@ public void EnsureGraphType_OverloadedAddsForEqualValueScalars_Succeeds() public void QueueExtension_WhenAddedBeforeType_IsAssignedAfterTypeIsAdded() { var collection = new SchemaTypeCollection(); - var template = GraphQLProviders.TemplateProvider.ParseType(typeof(TypeExtensionController)) as IGraphControllerTemplate; + + var template = new GraphControllerTemplate(typeof(TypeExtensionController)); + template.Parse(); + template.ValidateOrThrow(); var graphType = this.MakeGraphType(typeof(TwoPropertyObject), TypeKind.OBJECT) as IObjectGraphType; @@ -247,7 +252,10 @@ public void QueueExtension_WhenAddedBeforeType_IsAssignedAfterTypeIsAdded() public void QueueExtension_WhenAddedAfterType_IsAddedToTheTypeAndNotQueued() { var collection = new SchemaTypeCollection(); - var template = GraphQLProviders.TemplateProvider.ParseType(typeof(TypeExtensionController)) as IGraphControllerTemplate; + + var template = new GraphControllerTemplate(typeof(TypeExtensionController)); + template.Parse(); + template.ValidateOrThrow(); var twoObjectGraphType = this.MakeGraphType(typeof(TwoPropertyObject), TypeKind.OBJECT) as IObjectGraphType; diff --git a/src/unit-tests/graphql-aspnet-tests/ServerExtensions/MutlipartRequests/MultiPartRequestServerExtensionTests.cs b/src/unit-tests/graphql-aspnet-tests/ServerExtensions/MutlipartRequests/MultiPartRequestServerExtensionTests.cs index 2092752be..0572d6296 100644 --- a/src/unit-tests/graphql-aspnet-tests/ServerExtensions/MutlipartRequests/MultiPartRequestServerExtensionTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/ServerExtensions/MutlipartRequests/MultiPartRequestServerExtensionTests.cs @@ -10,7 +10,6 @@ namespace GraphQL.AspNet.Tests.ServerExtensions.MutlipartRequests { using System.Linq; - using System.Threading.Tasks; using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Configuration.Exceptions; using GraphQL.AspNet.Engine; @@ -20,7 +19,6 @@ namespace GraphQL.AspNet.Tests.ServerExtensions.MutlipartRequests using GraphQL.AspNet.ServerExtensions.MultipartRequests.Engine; using GraphQL.AspNet.ServerExtensions.MultipartRequests.Model; using GraphQL.AspNet.ServerExtensions.MultipartRequests.Schema; - using GraphQL.AspNet.Tests.Execution.TestData.DirectiveProcessorTypeSystemLocationTestData; using GraphQL.AspNet.Tests.Framework; using GraphQL.AspNet.Tests.ServerExtensions.MutlipartRequests.TestData; using Microsoft.Extensions.DependencyInjection; @@ -33,9 +31,6 @@ public class MultiPartRequestServerExtensionTests [Test] public void DefaultUsage_DefaultProcessorIsRegistered() { - using var restorePoint = new GraphQLGlobalRestorePoint(); - GraphQLProviders.ScalarProvider = new DefaultScalarGraphTypeProvider(); - var collection = new ServiceCollection(); var options = new SchemaOptions(collection); @@ -47,25 +42,17 @@ public void DefaultUsage_DefaultProcessorIsRegistered() [Test] public void DefaultUsage_ScalarIsRegistered() { - using var restorePoint = new GraphQLGlobalRestorePoint(); - GraphQLProviders.ScalarProvider = new DefaultScalarGraphTypeProvider(); - var collection = new ServiceCollection(); var options = new SchemaOptions(collection); - Assert.IsFalse(GraphQLProviders.ScalarProvider.IsScalar(typeof(FileUpload))); - options.RegisterExtension(); - Assert.IsTrue(GraphQLProviders.ScalarProvider.IsScalar(typeof(FileUpload))); + Assert.IsTrue(options.SchemaTypesToRegister.Any(x => x.Type == typeof(FileUploadScalarGraphType))); } [Test] public void DefaultUsage_WhenProcessorIsAlreadyRegistered_ThrowsException() { - using var restorePoint = new GraphQLGlobalRestorePoint(); - GraphQLProviders.ScalarProvider = new DefaultScalarGraphTypeProvider(); - var collection = new ServiceCollection(); var options = new SchemaOptions(collection); options.QueryHandler.HttpProcessorType = typeof(DefaultGraphQLHttpProcessor); @@ -79,9 +66,6 @@ public void DefaultUsage_WhenProcessorIsAlreadyRegistered_ThrowsException() [Test] public void DefaultUsage_CustomProcessorIsChangedToSomethingNotCompatiable_ThrowsExceptionOnUsage() { - using var restorePoint = new GraphQLGlobalRestorePoint(); - GraphQLProviders.ScalarProvider = new DefaultScalarGraphTypeProvider(); - var collection = new ServiceCollection(); var options = new SchemaOptions(collection); @@ -102,8 +86,6 @@ public void DefaultUsage_CustomProcessorIsChangedToSomethingNotCompatiable_Throw [Test] public void DeclineDefaultProcessor_CustomProcessorIsSetManually_NoException() { - using var restorePoint = new GraphQLGlobalRestorePoint(true); - var collection = new ServiceCollection(); var options = new SchemaOptions(collection); @@ -125,8 +107,6 @@ public void DeclineDefaultProcessor_CustomProcessorIsSetManually_NoException() [Test] public void UseExtension_WithNoProvider_DoesNothing() { - using var restorePoint = new GraphQLGlobalRestorePoint(true); - var collection = new ServiceCollection(); var options = new SchemaOptions(collection); @@ -148,8 +128,6 @@ public void UseExtension_WithNoProvider_DoesNothing() [Test] public void UseExtension_CheckingForACompatiableProvider_NoConfigChanges_ProviderFirst_ThrowsException() { - using var restorePoint = new GraphQLGlobalRestorePoint(true); - var extension = new MultipartRequestServerExtension((o) => { }); var serverBuilder = new TestServerBuilder(); @@ -171,8 +149,6 @@ public void UseExtension_CheckingForACompatiableProvider_NoConfigChanges_Provide [Test] public void UseExtension_CheckingForACompatiableProvider_NoConfigChanges_ProviderLast_IsValid() { - using var restorePoint = new GraphQLGlobalRestorePoint(true); - var extension = new MultipartRequestServerExtension((o) => { }); var serverBuilder = new TestServerBuilder(); @@ -191,8 +167,6 @@ public void UseExtension_CheckingForACompatiableProvider_NoConfigChanges_Provide [Test] public void UseExtension_NotRegisteringProvider_CheckingForACompatiableProvider_ProviderLast_IsValid() { - using var restorePoint = new GraphQLGlobalRestorePoint(true); - var extension = new MultipartRequestServerExtension((o) => { o.RegisterMultipartRequestHttpProcessor = false; @@ -216,8 +190,6 @@ public void UseExtension_NotRegisteringProvider_CheckingForACompatiableProvider_ [Test] public void UseExtension_NotRegisteringProvider_CheckingForACompatiableProvider_ProviderFirst_IsValid() { - using var restorePoint = new GraphQLGlobalRestorePoint(true); - var extension = new MultipartRequestServerExtension((o) => { o.RegisterMultipartRequestHttpProcessor = false; diff --git a/src/unit-tests/graphql-aspnet-tests/ServerExtensions/MutlipartRequests/MultipartRequestExtensionMethodsTests.cs b/src/unit-tests/graphql-aspnet-tests/ServerExtensions/MutlipartRequests/MultipartRequestExtensionMethodsTests.cs index e0cb9360a..fcfc5d342 100644 --- a/src/unit-tests/graphql-aspnet-tests/ServerExtensions/MutlipartRequests/MultipartRequestExtensionMethodsTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/ServerExtensions/MutlipartRequests/MultipartRequestExtensionMethodsTests.cs @@ -14,8 +14,6 @@ namespace GraphQL.AspNet.Tests.ServerExtensions.MutlipartRequests using GraphQL.AspNet.Schemas; using GraphQL.AspNet.ServerExtensions.MultipartRequests; using GraphQL.AspNet.ServerExtensions.MultipartRequests.Interfaces; - using GraphQL.AspNet.ServerExtensions.MultipartRequests.Model; - using GraphQL.AspNet.Tests.Framework; using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; @@ -28,8 +26,6 @@ public class SecondSchema : GraphSchema [Test] public void AddMultipartRequestSupport_DoesNotThrowExceptionWhenNotPassingAction() { - using var restorePoint = new GraphQLGlobalRestorePoint(true); - var options = new SchemaOptions(new ServiceCollection()); options.AddMultipartRequestSupport(); } @@ -37,8 +33,6 @@ public void AddMultipartRequestSupport_DoesNotThrowExceptionWhenNotPassingAction [Test] public void AddMultipartRequestSupport_ProvidedActionMethodIsCalled() { - using var restorePoint = new GraphQLGlobalRestorePoint(true); - var wasCalled = false; var collection = new ServiceCollection(); @@ -62,16 +56,12 @@ public void AddMultipartRequestSupport_ProvidedActionMethodIsCalled() .SingleOrDefault(x => x.ServiceType == typeof(IFileUploadScalarValueMaker))); - GraphQLProviders.ScalarProvider.IsScalar(typeof(FileUpload)); - Assert.IsTrue(wasCalled); } [Test] public void AddMultipartRequestSupport_OnMultipleSchemas_RegistersGlobalEntitiesOnce() { - using var restorePoint = new GraphQLGlobalRestorePoint(true); - var wasCalled1 = false; var collection = new ServiceCollection(); @@ -112,8 +102,6 @@ public void AddMultipartRequestSupport_OnMultipleSchemas_RegistersGlobalEntities .SingleOrDefault(x => x.ServiceType == typeof(IFileUploadScalarValueMaker))); - GraphQLProviders.ScalarProvider.IsScalar(typeof(FileUpload)); - Assert.IsTrue(wasCalled2); } } diff --git a/src/unit-tests/graphql-aspnet-tests/ServerExtensions/MutlipartRequests/MultipartRequestGraphQLHttpProcessorTests.cs b/src/unit-tests/graphql-aspnet-tests/ServerExtensions/MutlipartRequests/MultipartRequestGraphQLHttpProcessorTests.cs index a50ab4e93..a6b494444 100644 --- a/src/unit-tests/graphql-aspnet-tests/ServerExtensions/MutlipartRequests/MultipartRequestGraphQLHttpProcessorTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/ServerExtensions/MutlipartRequests/MultipartRequestGraphQLHttpProcessorTests.cs @@ -93,10 +93,10 @@ public class MultipartRequestGraphQLHttpProcessorTests var builder = new TestServerBuilder(); - GraphQLProviders.ScalarProvider.RegisterCustomScalar(typeof(FileUploadScalarGraphType)); builder.AddSingleton(); builder.AddGraphQL(o => { + o.AddType(); o.AddController(); o.ResponseOptions.TimeStampLocalizer = (d) => _staticFailDate; }); @@ -130,8 +130,6 @@ private string ExtractResponseString(HttpContext context) [Test] public async Task NotAMultiPartRequest_ParsesAsNormal() { - using var restorePoint = new GraphQLGlobalRestorePoint(true); - var (context, processor) = this.CreateTestObjects(); var _options = new JsonSerializerOptions(); @@ -172,8 +170,6 @@ public async Task NotAMultiPartRequest_ParsesAsNormal() [Test] public async Task NonBatchedQuery_NoFiles_ReturnsStandardResult() { - using var restorePoint = new GraphQLGlobalRestorePoint(true); - var (context, processor) = this.CreateTestObjects( fields: new[] { @@ -207,8 +203,6 @@ private string PrepQuery(string queryText) [Test] public async Task NonBatchedQuery_SingleFile_ReturnsStandardResult() { - using var restorePoint = new GraphQLGlobalRestorePoint(true); - var query1 = @" query($inboundFile: Upload!) { @@ -255,8 +249,6 @@ public async Task NonBatchedQuery_SingleFile_ReturnsStandardResult() [Test] public async Task NonBatchedQuery_SingleFile_InvalidMapField_Errors() { - using var restorePoint = new GraphQLGlobalRestorePoint(true); - var query1 = @" query($inboundFile: Upload!) { @@ -292,7 +284,6 @@ public async Task NonBatchedQuery_SingleFile_InvalidMapField_Errors() [Test] public async Task InvalidOperationsJson_HandlesParsingException() { - using var restorePoint = new GraphQLGlobalRestorePoint(true); var (context, processor) = this.CreateTestObjects( fields: new[] { @@ -309,7 +300,6 @@ public async Task InvalidOperationsJson_HandlesParsingException() [Test] public async Task NoQueriesOnBatch_HandlesParsingException() { - using var restorePoint = new GraphQLGlobalRestorePoint(true); var (context, processor) = this.CreateTestObjects( fields: new[] { @@ -323,8 +313,6 @@ public async Task NoQueriesOnBatch_HandlesParsingException() [Test] public async Task MultiPartForm_NoFiles_ReturnsStandardResult() { - using var restorePoint = new GraphQLGlobalRestorePoint(true); - var query1 = @" query { @@ -383,8 +371,6 @@ public async Task MultiPartForm_NoFiles_ReturnsStandardResult() [Test] public async Task RuntimeThrowsException_CustomResultIsGenerated() { - using var restorePoint = new GraphQLGlobalRestorePoint(true); - var runtime = new Mock>(); runtime.Setup(x => x.ExecuteRequestAsync( It.IsAny(), From b4b261c5ef09e60c67e42b75e8f7ff55019ed195 Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Tue, 11 Jul 2023 05:30:17 -0700 Subject: [PATCH 28/63] WIP, global providers removed. All tests passed. --- ...ubscriptionEnabledGraphTypeMakerFactory.cs | 7 +++- .../SubscriptionEnabledGraphFieldMaker.cs | 15 ++++--- .../SubscriptionPublisherSchemaExtension.cs | 24 ++++++++++- .../SubscriptionReceiverSchemaExtension.cs | 21 +++++++++- ...DefaultGraphQLSchemaFactory_Controllers.cs | 4 +- .../Generation/TypeMakers/GraphFieldMaker.cs | 42 +++++++++++-------- ...SubscriptionEnabledFieldFieldMakerTests.cs | 8 +++- .../GraphControllerTemplateTests.cs | 3 ++ .../SubscriptionReceiverExtensionTests.cs | 3 +- 9 files changed, 95 insertions(+), 32 deletions(-) diff --git a/src/graphql-aspnet-subscriptions/Engine/SubscriptionEnabledGraphTypeMakerFactory.cs b/src/graphql-aspnet-subscriptions/Engine/SubscriptionEnabledGraphTypeMakerFactory.cs index e2a151308..6a5d09cbe 100644 --- a/src/graphql-aspnet-subscriptions/Engine/SubscriptionEnabledGraphTypeMakerFactory.cs +++ b/src/graphql-aspnet-subscriptions/Engine/SubscriptionEnabledGraphTypeMakerFactory.cs @@ -48,7 +48,12 @@ public SubscriptionEnabledGraphQLTypeMakerFactory() public override IGraphTypeTemplate MakeTemplate(Type objectType, TypeKind? kind = null) { if (Validation.IsCastable(objectType)) - return new SubscriptionGraphControllerTemplate(objectType); + { + var template = new SubscriptionGraphControllerTemplate(objectType); + template.Parse(); + template.ValidateOrThrow(); + return template; + } return base.MakeTemplate(objectType, kind); } diff --git a/src/graphql-aspnet-subscriptions/Engine/TypeMakers/SubscriptionEnabledGraphFieldMaker.cs b/src/graphql-aspnet-subscriptions/Engine/TypeMakers/SubscriptionEnabledGraphFieldMaker.cs index 6c385af9f..8d11a3ee4 100644 --- a/src/graphql-aspnet-subscriptions/Engine/TypeMakers/SubscriptionEnabledGraphFieldMaker.cs +++ b/src/graphql-aspnet-subscriptions/Engine/TypeMakers/SubscriptionEnabledGraphFieldMaker.cs @@ -35,11 +35,13 @@ namespace GraphQL.AspNet.Engine.TypeMakers public class SubscriptionEnabledGraphFieldMaker : GraphFieldMaker { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// The schema. - public SubscriptionEnabledGraphFieldMaker(ISchema schema, IGraphQLTypeMakerFactory factory) - : base(schema, factory) + /// The schema instance to reference when creating fields. + /// The maker factory to create dependnet makers + /// if and when necessary. + public SubscriptionEnabledGraphFieldMaker(ISchema schema, IGraphQLTypeMakerFactory makerFactory) + : base(schema, makerFactory) { } @@ -56,9 +58,12 @@ protected override MethodGraphField InstantiateField( { var directives = template.CreateAppliedDirectives(); + var schemaTypeName = this.PrepareTypeName(template); + var typeExpression = template.TypeExpression.CloneTo(schemaTypeName); + return new SubscriptionMethodGraphField( formatter.FormatFieldName(template.Name), - template.TypeExpression.CloneTo(formatter.FormatGraphTypeName(template.TypeExpression.TypeName)), + typeExpression, template.Route, template.InternalName, template.ObjectType, diff --git a/src/graphql-aspnet-subscriptions/SubscriptionServer/SubscriptionPublisherSchemaExtension.cs b/src/graphql-aspnet-subscriptions/SubscriptionServer/SubscriptionPublisherSchemaExtension.cs index ebc73ae37..706039016 100644 --- a/src/graphql-aspnet-subscriptions/SubscriptionServer/SubscriptionPublisherSchemaExtension.cs +++ b/src/graphql-aspnet-subscriptions/SubscriptionServer/SubscriptionPublisherSchemaExtension.cs @@ -10,12 +10,16 @@ namespace GraphQL.AspNet.SubscriptionServer { using System; + using System.Linq; using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Engine; using GraphQL.AspNet.Interfaces.Configuration; + using GraphQL.AspNet.Interfaces.Engine; using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Schemas.TypeSystem; using Microsoft.AspNetCore.Builder; + using Microsoft.Extensions.DependencyInjection; + using Microsoft.Extensions.DependencyInjection.Extensions; /// /// A schema extension encapsulating the ability for a given schema to publish subscription events from @@ -49,8 +53,24 @@ public void Configure(SchemaOptions options) // swap out the master providers for the ones that includes // support for the subscription action type - // need to register the schema enabled type maker factory - throw new NotImplementedException(); + // swap out the master templating provider for the schema to one that includes + // support for the subscription action type if and only if the developer has not + // already registered their own custom one + var existing = options.ServiceCollection.FirstOrDefault(x => x.ServiceType == typeof(IGraphQLTypeMakerFactory)); + if (existing != null) + { + options + .ServiceCollection + .RemoveAll(typeof(IGraphQLTypeMakerFactory)); + } + + options + .ServiceCollection + .TryAdd( + new ServiceDescriptor( + typeof(IGraphQLTypeMakerFactory), + typeof(SubscriptionEnabledGraphQLTypeMakerFactory), + ServiceLifetime.Transient)); } /// diff --git a/src/graphql-aspnet-subscriptions/SubscriptionServer/SubscriptionReceiverSchemaExtension.cs b/src/graphql-aspnet-subscriptions/SubscriptionServer/SubscriptionReceiverSchemaExtension.cs index a680e8355..4ef66c51c 100644 --- a/src/graphql-aspnet-subscriptions/SubscriptionServer/SubscriptionReceiverSchemaExtension.cs +++ b/src/graphql-aspnet-subscriptions/SubscriptionServer/SubscriptionReceiverSchemaExtension.cs @@ -10,10 +10,13 @@ namespace GraphQL.AspNet.SubscriptionServer { using System; + using System.Linq; using GraphQL.AspNet.Common; + using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Engine; using GraphQL.AspNet.Interfaces.Configuration; + using GraphQL.AspNet.Interfaces.Engine; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Logging; using GraphQL.AspNet.Interfaces.Schema; @@ -89,11 +92,25 @@ public void Configure(SchemaOptions options) $"authorization method. (Current authorization method is \"{_schemaBuilder.Options.AuthorizationOptions.Method}\")"); } - // swap out the master templating provider for the one that includes + // swap out the master templating provider for the schema to one that includes // support for the subscription action type if and only if the developer has not // already registered their own custom one + var existing = _schemaBuilder.Options.ServiceCollection.FirstOrDefault(x => x.ServiceType == typeof(IGraphQLTypeMakerFactory)); + if (existing != null) + { + _schemaBuilder.Options + .ServiceCollection + .RemoveAll(typeof(IGraphQLTypeMakerFactory)); + } + + _schemaBuilder.Options + .ServiceCollection + .TryAdd( + new ServiceDescriptor( + typeof(IGraphQLTypeMakerFactory), + typeof(SubscriptionEnabledGraphQLTypeMakerFactory), + ServiceLifetime.Transient)); - // need to register the subscription enable graph type maker factory // Update the query execution pipeline // ------------------------------------------ diff --git a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Controllers.cs b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Controllers.cs index d9fd8e7a4..4fd394969 100644 --- a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Controllers.cs +++ b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Controllers.cs @@ -65,9 +65,9 @@ protected virtual void AddTypeExtension(IGraphFieldTemplate extension) /// The action to add to the schema. protected virtual void AddAction(IGraphFieldTemplate action) { - if (this.Schema.Configuration.DeclarationOptions.AllowedOperations.Contains(action.Route.RootCollection.ToGraphOperationType())) + var operation = action.Route.RootCollection.ToGraphOperationType(); + if (this.Schema.Configuration.DeclarationOptions.AllowedOperations.Contains(operation)) { - var operation = action.Route.RootCollection.ToGraphOperationType(); this.EnsureGraphOperationType(operation); var parentField = this.AddOrRetrieveControllerRoutePath(action); this.AddActionAsField(parentField, action); diff --git a/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphFieldMaker.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphFieldMaker.cs index 15ec5d4d9..e4ca231eb 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphFieldMaker.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphFieldMaker.cs @@ -12,11 +12,13 @@ namespace GraphQL.AspNet.Schemas.Generation.TypeMakers using System; using System.Collections.Generic; using System.Runtime.CompilerServices; + using System.Runtime.Serialization; using GraphQL.AspNet.Common; using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Common.Generics; using GraphQL.AspNet.Configuration.Formatting; using GraphQL.AspNet.Engine.TypeMakers; + using GraphQL.AspNet.Execution.RulesEngine.RuleSets.DocumentValidation.FieldSelectionSteps; using GraphQL.AspNet.Interfaces.Configuration; using GraphQL.AspNet.Interfaces.Engine; using GraphQL.AspNet.Interfaces.Internal; @@ -59,11 +61,6 @@ public virtual GraphFieldCreationResult CreateField(IGraphFieldTemp // field for evaluation var securityGroups = new List(); - if (template.Parent.ObjectType.Name == "ParentWithNullableChildObject") - { - string str = ""; - } - if (template.Parent?.SecurityPolicies?.Count > 0) securityGroups.Add(template.Parent.SecurityPolicies); @@ -109,19 +106,12 @@ public virtual GraphFieldCreationResult CreateField(IGraphFieldTemp } /// - /// Instantiates the graph field according to the data provided. + /// Finds and applies proper casing to the graph type name returned by this field. /// - /// The formatter. - /// The template. - /// The security groups. - /// MethodGraphField. - protected virtual MethodGraphField InstantiateField( - GraphNameFormatter formatter, - IGraphFieldTemplate template, - List securityGroups) + /// The template to inspect. + /// System.String. + protected virtual string PrepareTypeName(IGraphFieldTemplate template) { - var directives = template.CreateAppliedDirectives(); - // all fields return either an object, interface, union, scalar or enum IGraphType existingGraphType; string fallbackTypeName; @@ -158,8 +148,26 @@ protected virtual MethodGraphField InstantiateField( // enforce non-renaming standards in the maker since the // directly controls the formatter if (GlobalScalars.CanBeRenamed(schemaTypeName)) - schemaTypeName = formatter.FormatGraphTypeName(schemaTypeName); + schemaTypeName = _schema.Configuration.DeclarationOptions.GraphNamingFormatter.FormatGraphTypeName(schemaTypeName); + + return schemaTypeName; + } + + /// + /// Instantiates the graph field according to the data provided. + /// + /// The formatter. + /// The template. + /// The security groups. + /// MethodGraphField. + protected virtual MethodGraphField InstantiateField( + GraphNameFormatter formatter, + IGraphFieldTemplate template, + List securityGroups) + { + var directives = template.CreateAppliedDirectives(); + var schemaTypeName = this.PrepareTypeName(template); var typeExpression = template.TypeExpression.CloneTo(schemaTypeName); switch (template.FieldSource) diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/SubscriptionEnabledFieldFieldMakerTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/SubscriptionEnabledFieldFieldMakerTests.cs index 020099555..5e62a5ab5 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/SubscriptionEnabledFieldFieldMakerTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/SubscriptionEnabledFieldFieldMakerTests.cs @@ -19,6 +19,8 @@ namespace GraphQL.AspNet.Tests.Engine using Moq; using NUnit.Framework; using GraphQL.AspNet.Schemas.Generation; + using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Engine; [TestFixture] public class SubscriptionEnabledFieldFieldMakerTests @@ -40,8 +42,10 @@ public void SubscriptionActionField_TransfersDirectives() var schema = new TestServerBuilder().Build().Schema; - // var factory = SchemaEnabledGraphTypeFactory(); - var maker = new SubscriptionEnabledGraphFieldMaker(schema, null); + var factory = new SubscriptionEnabledGraphQLTypeMakerFactory(); + factory.Initialize(schema); + + var maker = new SubscriptionEnabledGraphFieldMaker(schema, factory); var field = maker.CreateField(actionTemplate).Field; diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/GraphControllerTemplateTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/GraphControllerTemplateTests.cs index 279709993..77708d8d1 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/GraphControllerTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/GraphControllerTemplateTests.cs @@ -21,6 +21,9 @@ public class GraphControllerTemplateTests public void Parse_SingleSubscriptionRoute_CreatesCorrectActionTemplate() { var template = new SubscriptionGraphControllerTemplate(typeof(SimpleSubscriptionController)) as GraphControllerTemplate; + template.Parse(); + template.ValidateOrThrow(); + Assert.IsNotNull(template); Assert.AreEqual(1, template.FieldTemplates.Count()); diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionReceiverExtensionTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionReceiverExtensionTests.cs index 2e4eb9bc3..767a72e10 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionReceiverExtensionTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionReceiverExtensionTests.cs @@ -83,10 +83,11 @@ public void ServiceCollection_VerifyDefaultInjectedObjects() Assert.IsTrue(primaryOptions.DeclarationOptions.AllowedOperations.Contains(GraphOperationType.Subscription)); - Assert.AreEqual(8, primaryOptions.ServiceCollection.Count); + Assert.AreEqual(9, primaryOptions.ServiceCollection.Count); // primary server objects Assert.IsNotNull(primaryOptions.ServiceCollection.SingleOrDefault(x => x.ServiceType == typeof(SubscriptionServerOptions))); + Assert.IsNotNull(primaryOptions.ServiceCollection.SingleOrDefault(x => x.ImplementationType == typeof(SubscriptionEnabledGraphQLTypeMakerFactory))); Assert.IsNotNull(primaryOptions.ServiceCollection.SingleOrDefault(x => x.ServiceType == typeof(ISubscriptionServerClientFactory))); Assert.IsNotNull(primaryOptions.ServiceCollection.SingleOrDefault(x => x.ServiceType == typeof(IGlobalSubscriptionClientProxyCollection))); Assert.IsNotNull(primaryOptions.ServiceCollection.SingleOrDefault(x => x.ServiceType == typeof(ISubscriptionEventDispatchQueue))); From 1320b83f5974f92a61f6c6d7650bd7ee61cedade Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Tue, 11 Jul 2023 17:04:52 -0700 Subject: [PATCH 29/63] WIP, Combined global union and scalar instantiators --- ...nabledGraphQLTypeMakerFactory{TSchema}.cs} | 9 --- .../SubscriptionReceiverSchemaExtension.cs | 1 - .../DirectiveBindingSchemaExtension.cs | 4 +- .../Configuration/SchemaOptions.cs | 34 ++------- .../Startup/GraphQLSchemaInjector{TSchema}.cs | 6 +- .../Engine/DefaultGraphQLSchemaFactory.cs | 8 +- .../Engine/DefaultGraphQLTypeMakerFactory.cs | 4 +- src/graphql-aspnet/GraphQLProviders.cs | 55 -------------- .../Configuration/IGraphQLServerExtension.cs | 75 ++++++++++++++++--- .../Configuration/ISchemaExtension.cs | 26 ------- .../Engine/IGraphQLSchemaFactory{TSchema}.cs | 4 +- .../IQueryExecutionPlanCacheProvider.cs | 2 +- .../Interfaces/Schema/ISchemaItemValidator.cs | 9 ++- .../TypeTemplates/GraphFieldTemplateBase.cs | 3 +- .../TypeTemplates/ScalarGraphTypeTemplate.cs | 8 +- .../TypeMakers/GraphArgumentMaker.cs | 2 +- .../Generation/TypeMakers/GraphFieldMaker.cs | 2 +- .../TypeMakers/ScalarGraphTypeMaker.cs | 2 +- .../TypeMakers/UnionGraphTypeMaker.cs | 3 +- src/graphql-aspnet/Schemas/GraphTypeNames.cs | 4 +- .../GraphArgumentValidator.cs | 1 - .../GraphFieldValidator.cs | 1 - .../GlobalScalars.cs => GlobalTypes.cs} | 66 ++++++++++++---- .../Model/IntrospectedDirective.cs | 4 - .../Introspection/Model/IntrospectedField.cs | 5 -- .../Introspection/Model/IntrospectedType.cs | 9 --- .../Introspection/Model/Introspection.cs | 5 -- .../TypeSystem/Scalars/ScalarGraphTypeBase.cs | 4 +- .../TypeCollections/SchemaTypeCollection.cs | 1 - .../Schemas/TypeSystem/VirtualGraphField.cs | 3 - .../GraphQLTemplateHelper.cs | 2 +- .../Configuration/DirectiveApplicatorTests.cs | 6 +- .../ScalarTestBase.cs | 2 +- .../DirectiveProcessorTypeSystemTests.cs | 2 +- .../RulesEngine/EnsureValidationRuleUrls.cs | 3 +- .../Internal/InputResolverGeneratorTests.cs | 2 +- .../Templating/GraphTypeNamesTests.cs | 4 +- .../Schemas/DefaultTypeTests.cs | 4 +- .../Schemas/IExternalArgumentChecker.cs | 12 --- .../Schemas/SchemaLanguageGeneratorTests.cs | 2 +- 40 files changed, 171 insertions(+), 228 deletions(-) rename src/graphql-aspnet-subscriptions/Engine/{SubscriptionEnabledGraphTypeMakerFactory.cs => SubscriptionEnabledGraphQLTypeMakerFactory{TSchema}.cs} (88%) delete mode 100644 src/graphql-aspnet/GraphQLProviders.cs delete mode 100644 src/graphql-aspnet/Interfaces/Configuration/ISchemaExtension.cs rename src/graphql-aspnet/Schemas/TypeSystem/{Scalars/GlobalScalars.cs => GlobalTypes.cs} (89%) delete mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/IExternalArgumentChecker.cs diff --git a/src/graphql-aspnet-subscriptions/Engine/SubscriptionEnabledGraphTypeMakerFactory.cs b/src/graphql-aspnet-subscriptions/Engine/SubscriptionEnabledGraphQLTypeMakerFactory{TSchema}.cs similarity index 88% rename from src/graphql-aspnet-subscriptions/Engine/SubscriptionEnabledGraphTypeMakerFactory.cs rename to src/graphql-aspnet-subscriptions/Engine/SubscriptionEnabledGraphQLTypeMakerFactory{TSchema}.cs index 6a5d09cbe..f5154b6fe 100644 --- a/src/graphql-aspnet-subscriptions/Engine/SubscriptionEnabledGraphTypeMakerFactory.cs +++ b/src/graphql-aspnet-subscriptions/Engine/SubscriptionEnabledGraphQLTypeMakerFactory{TSchema}.cs @@ -7,15 +7,6 @@ // License: MIT // ************************************************************* -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - namespace GraphQL.AspNet.Engine { using System; diff --git a/src/graphql-aspnet-subscriptions/SubscriptionServer/SubscriptionReceiverSchemaExtension.cs b/src/graphql-aspnet-subscriptions/SubscriptionServer/SubscriptionReceiverSchemaExtension.cs index 4ef66c51c..f16d85143 100644 --- a/src/graphql-aspnet-subscriptions/SubscriptionServer/SubscriptionReceiverSchemaExtension.cs +++ b/src/graphql-aspnet-subscriptions/SubscriptionServer/SubscriptionReceiverSchemaExtension.cs @@ -111,7 +111,6 @@ public void Configure(SchemaOptions options) typeof(SubscriptionEnabledGraphQLTypeMakerFactory), ServiceLifetime.Transient)); - // Update the query execution pipeline // ------------------------------------------ // Wipe out the current execution pipeline and rebuild with diff --git a/src/graphql-aspnet/Configuration/DirectiveBindingSchemaExtension.cs b/src/graphql-aspnet/Configuration/DirectiveBindingSchemaExtension.cs index 62c9bab21..dcd2786ac 100644 --- a/src/graphql-aspnet/Configuration/DirectiveBindingSchemaExtension.cs +++ b/src/graphql-aspnet/Configuration/DirectiveBindingSchemaExtension.cs @@ -21,7 +21,7 @@ namespace GraphQL.AspNet.Configuration /// A configuration class used to apply a late-bound directive to a set of schema items /// matching a filter. /// - public sealed class DirectiveBindingSchemaExtension : ISchemaExtension + public sealed class DirectiveBindingSchemaExtension : IGraphQLServerExtension { // a set of default filters applied to any directive applicator unless explicitly removed // by the developer. Used to auto filter items down to those reasonably assumed @@ -81,7 +81,7 @@ private DirectiveBindingSchemaExtension() } /// - void ISchemaExtension.Extend(ISchema schema) + void IGraphQLServerExtension.EnsureSchema(ISchema schema) { var allFilters = _defaultFilters.Concat(_customFilters).ToList(); foreach (var schemaItem in schema.AllSchemaItems(includeDirectives: false)) diff --git a/src/graphql-aspnet/Configuration/SchemaOptions.cs b/src/graphql-aspnet/Configuration/SchemaOptions.cs index 51dcb8722..e87b2e894 100644 --- a/src/graphql-aspnet/Configuration/SchemaOptions.cs +++ b/src/graphql-aspnet/Configuration/SchemaOptions.cs @@ -31,12 +31,11 @@ namespace GraphQL.AspNet.Configuration /// public abstract class SchemaOptions { - private readonly Dictionary _serverExtensions; + private readonly List _serverExtensions; private readonly HashSet _possibleTypes; private readonly List _registeredServices; private readonly List _runtimeTemplates; - private List _configExtensions; /// /// Initializes a new instance of the class. @@ -53,9 +52,8 @@ public SchemaOptions(Type schemaType, IServiceCollection serviceCollection) _possibleTypes = new HashSet(SchemaTypeToRegister.DefaultEqualityComparer); _runtimeTemplates = new List(); - _serverExtensions = new Dictionary(); + _serverExtensions = new List(); _registeredServices = new List(); - _configExtensions = new List(); this.DeclarationOptions = new SchemaDeclarationConfiguration(); this.CacheOptions = new SchemaQueryExecutionPlanCacheConfiguration(); @@ -272,20 +270,7 @@ public void RegisterExtension(TExtensionType extension) Validation.ThrowIfNull(extension, nameof(extension)); extension.Configure(this); - _serverExtensions.Add(extension.GetType(), extension); - } - - /// - /// Adds an extension to allow processing of schema instance by an extenal object - /// before the schema is complete. The state of the schema is not garunteed - /// when then extension is executed. It is highly likely that the schema will undergo - /// further processing after the extension executes. - /// - /// The extension to apply. - public void AddSchemaExtension(ISchemaExtension extension) - { - Validation.ThrowIfNull(extension, nameof(extension)); - _configExtensions.Add(extension); + _serverExtensions.Add(extension); } /// @@ -313,7 +298,7 @@ public DirectiveBindingSchemaExtension ApplyDirective(Type directiveType) this.AddType(directiveType, null, null); var applicator = new DirectiveBindingSchemaExtension(directiveType); - this.AddSchemaExtension(applicator); + this.RegisterExtension(applicator); return applicator; } @@ -329,7 +314,7 @@ public DirectiveBindingSchemaExtension ApplyDirective(string directiveName) { directiveName = Validation.ThrowIfNullWhiteSpaceOrReturn(directiveName, nameof(directiveName)); var applicator = new DirectiveBindingSchemaExtension(directiveName); - this.AddSchemaExtension(applicator); + this.RegisterExtension(applicator); return applicator; } @@ -381,13 +366,6 @@ internal void AddRuntimeSchemaItem(IGraphQLRuntimeSchemaItemDefinition template) /// The registered schema types. public IEnumerable SchemaTypesToRegister => _possibleTypes; - /// - /// Gets the configuration extensions that will be applied to the schema instance when its - /// created. - /// - /// The configuration extensions. - public IEnumerable SchemaExtensions => _configExtensions; - /// /// Gets or sets a value indicating whether any , or /// any classes that implement at least one graph attribute, that are part of the entry assembly, are automatically @@ -438,7 +416,7 @@ internal void AddRuntimeSchemaItem(IGraphQLRuntimeSchemaItemDefinition template) /// Gets the set of options extensions added to this schema configuration. /// /// The extensions. - public IReadOnlyDictionary ServerExtensions => _serverExtensions; + public IEnumerable ServerExtensions => _serverExtensions; /// /// Gets the service collection which contains all the required entries for diff --git a/src/graphql-aspnet/Configuration/Startup/GraphQLSchemaInjector{TSchema}.cs b/src/graphql-aspnet/Configuration/Startup/GraphQLSchemaInjector{TSchema}.cs index 3a970d820..9ce2e30b4 100644 --- a/src/graphql-aspnet/Configuration/Startup/GraphQLSchemaInjector{TSchema}.cs +++ b/src/graphql-aspnet/Configuration/Startup/GraphQLSchemaInjector{TSchema}.cs @@ -193,7 +193,7 @@ private TSchema BuildNewSchemaInstance(IServiceProvider serviceProvider) schemaConfig, _options.SchemaTypesToRegister, _options.RuntimeTemplates, - _options.SchemaExtensions); + _options.ServerExtensions); serviceProvider.WriteLogEntry( (l) => l.SchemaInstanceCreated(schemaInstance)); @@ -214,7 +214,7 @@ public void UseSchema(IApplicationBuilder appBuilder) if (_options.ServerExtensions != null) { foreach (var additionalOptions in _options.ServerExtensions) - additionalOptions.Value.UseExtension(appBuilder, appBuilder.ApplicationServices); + additionalOptions.UseExtension(appBuilder, appBuilder.ApplicationServices); } if (!_options.QueryHandler.DisableDefaultRoute) @@ -256,7 +256,7 @@ private void UseSchema(IServiceProvider serviceProvider, bool invokeServerExtens if (invokeServerExtensions) { foreach (var additionalOptions in _options.ServerExtensions) - additionalOptions.Value.UseExtension(serviceProvider: serviceProvider); + additionalOptions.UseExtension(serviceProvider: serviceProvider); } // try and build the schema diff --git a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory.cs b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory.cs index 9d265708c..881436421 100644 --- a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory.cs +++ b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory.cs @@ -67,7 +67,7 @@ public virtual TSchema CreateInstance( ISchemaConfiguration configuration, IEnumerable typesToRegister = null, IEnumerable runtimeItemDefinitions = null, - IEnumerable schemaExtensions = null) + IEnumerable schemaExtensions = null) { Validation.ThrowIfNull(serviceScope, nameof(serviceScope)); Validation.ThrowIfNull(configuration, nameof(configuration)); @@ -76,7 +76,7 @@ public virtual TSchema CreateInstance( runtimeItemDefinitions = runtimeItemDefinitions ?? Enumerable.Empty(); typesToRegister = typesToRegister ?? Enumerable.Empty(); - schemaExtensions = schemaExtensions ?? Enumerable.Empty(); + schemaExtensions = schemaExtensions ?? Enumerable.Empty(); this.Schema = GraphSchemaBuilder.BuildSchema(this.ServiceProvider); @@ -101,7 +101,7 @@ public virtual TSchema CreateInstance( var nonScalarsToRegister = new List(); foreach (var regType in typesToRegister) { - if (Validation.IsCastable(GlobalScalars.FindBuiltInScalarType(regType.Type) ?? regType.Type)) + if (Validation.IsCastable(GlobalTypes.FindBuiltInScalarType(regType.Type) ?? regType.Type)) scalarsToRegister.Add(regType); else nonScalarsToRegister.Add(regType); @@ -126,7 +126,7 @@ public virtual TSchema CreateInstance( // -------------------------------------- // this includes any late bound directives added to the type system via .ApplyDirective() foreach (var extension in schemaExtensions) - extension.Extend(this.Schema); + extension.EnsureSchema(this.Schema); // Step 5: apply all queued type system directives to the now filled schema // -------------------------------------- diff --git a/src/graphql-aspnet/Engine/DefaultGraphQLTypeMakerFactory.cs b/src/graphql-aspnet/Engine/DefaultGraphQLTypeMakerFactory.cs index b27ec7a23..ea0346f2f 100644 --- a/src/graphql-aspnet/Engine/DefaultGraphQLTypeMakerFactory.cs +++ b/src/graphql-aspnet/Engine/DefaultGraphQLTypeMakerFactory.cs @@ -44,7 +44,7 @@ public virtual IGraphTypeTemplate MakeTemplate(Type objectType, TypeKind? kind = return null; // attempt to turn "int" into "IntScalarType" when necessary - objectType = GlobalScalars.FindBuiltInScalarType(objectType) ?? objectType; + objectType = GlobalTypes.FindBuiltInScalarType(objectType) ?? objectType; IGraphTypeTemplate template; if (Validation.IsCastable(objectType)) @@ -76,7 +76,7 @@ public virtual IGraphTypeMaker CreateTypeMaker(Type objectType, TypeKind? kind = if (objectType == null) return null; - objectType = GlobalScalars.FindBuiltInScalarType(objectType) ?? objectType; + objectType = GlobalTypes.FindBuiltInScalarType(objectType) ?? objectType; if (Validation.IsCastable(objectType)) return new ScalarGraphTypeMaker(this.Schema.Configuration); diff --git a/src/graphql-aspnet/GraphQLProviders.cs b/src/graphql-aspnet/GraphQLProviders.cs deleted file mode 100644 index e4bcf853b..000000000 --- a/src/graphql-aspnet/GraphQLProviders.cs +++ /dev/null @@ -1,55 +0,0 @@ -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - -namespace GraphQL.AspNet -{ - using System; - using System.Reflection; - using GraphQL.AspNet.Common; - using GraphQL.AspNet.Common.Extensions; - using GraphQL.AspNet.Common.Generics; - using GraphQL.AspNet.Engine; - using GraphQL.AspNet.Execution.Exceptions; - using GraphQL.AspNet.Interfaces.Engine; - using GraphQL.AspNet.Interfaces.Schema; - - /// - /// A global set of providers used throughout GraphQL.AspNet. These objects are static, unchanged and expected to - /// not change at runtime. Do not alter the contents of the static properties after calling .AddGraphQL(). - /// - internal static class GraphQLProviders - { - /// - /// attempts to instnatiate the provided type as a union proxy. - /// - /// Type of the proxy to create. - /// IGraphUnionProxy. - public static IGraphUnionProxy CreateUnionProxyFromType(Type proxyType) - { - if (proxyType == null) - return null; - - IGraphUnionProxy proxy = null; - if (Validation.IsCastable(proxyType)) - { - var paramlessConstructor = proxyType.GetConstructor(BindingFlags.Instance | BindingFlags.Public, null, Type.EmptyTypes, null); - if (paramlessConstructor == null) - { - throw new GraphTypeDeclarationException( - $"The union proxy type '{proxyType.FriendlyName()}' could not be instantiated. " + - "All union proxy types must declare a parameterless constructor."); - } - - proxy = InstanceFactory.CreateInstance(proxyType) as IGraphUnionProxy; - } - - return proxy; - } - } -} \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Configuration/IGraphQLServerExtension.cs b/src/graphql-aspnet/Interfaces/Configuration/IGraphQLServerExtension.cs index 712fd5c4c..c79e69601 100644 --- a/src/graphql-aspnet/Interfaces/Configuration/IGraphQLServerExtension.cs +++ b/src/graphql-aspnet/Interfaces/Configuration/IGraphQLServerExtension.cs @@ -11,11 +11,12 @@ namespace GraphQL.AspNet.Interfaces.Configuration { using System; using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Interfaces.Schema; using Microsoft.AspNetCore.Builder; /// /// - /// An interface that can be used to configure custom extensions to a schema. An extension can be almost + /// An object that can be used to configure custom extensions to a schema. An extension can be almost /// anthing that customizes the runtime for the target schema. /// /// @@ -27,30 +28,84 @@ public interface IGraphQLServerExtension /// /// /// This method is called by the schema configuration just before it is added to the extensions - /// collection. Use this method to do any sort of internal configuration, default settings, + /// collection for the target schema. Use this method to do any sort of internal configuration, default settings, /// additional DI container registrations etc. /// /// - /// This method represents the last opportunity for this extension to modify its own required - /// service collection before being incorporated with the DI container. + /// This method represents the last opportunity for this extension to add its own required + /// service collection registrations to the DI container. /// /// - /// The schema options collection to which this extension + /// The schema options representing the schema to which this extension /// is being registered. - void Configure(SchemaOptions options); + public void Configure(SchemaOptions options) + { + } /// - /// Instructs this extension to perform any final setup requirements before the server starts. + /// Instructs this extension to perform any final setup requirements before the server starts. This + /// method is called as part of .UseGraphQL() during startup. All extensions are called in the order + /// they are registered. /// /// - /// When this method is called, construction of the DI container is complete and all schemas - /// and types have been created and registered. + /// When this method is called, construction of the DI container is complete. The schema has not been + /// generated yet. + /// + /// The application builder to register against. May be null in some rare instances + /// where the middleware pipeline is not being setup. Usually during some unit testing edge cases. + public void UseExtension(IApplicationBuilder app) + { + this.UseExtension(app, null); + } + + /// + /// Instructs this extension to perform any final setup requirements before the server starts. This + /// method is called as part of .UseGraphQL() during startup. All extensions are called in the order + /// they are registered. + /// + /// + /// When this method is called, construction of the DI container is complete. The schema has not been + /// generated yet. + /// + /// The configured service provider completed during setup. In + /// most instances, this will be the instances + /// from . + public void UseExtension(IServiceProvider serviceProvider) + { + this.UseExtension(null, serviceProvider); + } + + /// + /// Instructs this extension to perform any final setup requirements before the server starts. This + /// method is called as part of .UseGraphQL() during startup. All extensions are called in the order + /// they are registered. + /// + /// + /// When this method is called, construction of the DI container is complete. The schema has not been + /// generated yet. /// /// The application builder to register against. May be null in some rare instances /// where the middleware pipeline is not being setup. Usually during some unit testing edge cases. /// The configured service provider completed during setup. In /// most instances, this will be the instances /// from . - void UseExtension(IApplicationBuilder app = null, IServiceProvider serviceProvider = null); + public void UseExtension(IApplicationBuilder app = null, IServiceProvider serviceProvider = null) + { + } + + /// + /// + /// Allows the extension the option to modify or inspect the integrity of a schema instance as its being built in order + /// to apply any necessary logic or updates to the schema items that have been registered and parsed during setup. + /// + /// + /// This method is invoked after all graph types and directives have been discovered and + /// just before type system directives are applied. + /// + /// + /// The schema to process. + public void EnsureSchema(ISchema schema) + { + } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Configuration/ISchemaExtension.cs b/src/graphql-aspnet/Interfaces/Configuration/ISchemaExtension.cs deleted file mode 100644 index eaf57ac96..000000000 --- a/src/graphql-aspnet/Interfaces/Configuration/ISchemaExtension.cs +++ /dev/null @@ -1,26 +0,0 @@ -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - -namespace GraphQL.AspNet.Interfaces.Configuration -{ - using GraphQL.AspNet.Interfaces.Schema; - - /// - /// An object that needs to extend or apply some changes to the schema - /// before its considered "complete" and ready to serve. - /// - public interface ISchemaExtension - { - /// - /// Instructs this configuration mechanism to apply itself to the supplied schema. - /// - /// The schema to extend. - void Extend(ISchema schema); - } -} \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Engine/IGraphQLSchemaFactory{TSchema}.cs b/src/graphql-aspnet/Interfaces/Engine/IGraphQLSchemaFactory{TSchema}.cs index cba60b70e..dc5d6ed27 100644 --- a/src/graphql-aspnet/Interfaces/Engine/IGraphQLSchemaFactory{TSchema}.cs +++ b/src/graphql-aspnet/Interfaces/Engine/IGraphQLSchemaFactory{TSchema}.cs @@ -34,13 +34,13 @@ public interface IGraphQLSchemaFactory /// The explicit types register /// on the schema. /// The runtime field and type definitions (i.e. minimal api) to add to the schema. - /// The schema extensions to apply to the schema. + /// The schema extensions to apply to the schema. /// The completed schema instance. TSchema CreateInstance( IServiceScope serviceScope, ISchemaConfiguration configuration, IEnumerable typesToRegister = null, IEnumerable runtimeItemDefinitions = null, - IEnumerable schemaExtensions = null); + IEnumerable extensionsToExecute = null); } } \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Engine/IQueryExecutionPlanCacheProvider.cs b/src/graphql-aspnet/Interfaces/Engine/IQueryExecutionPlanCacheProvider.cs index 80c123c1c..86004a922 100644 --- a/src/graphql-aspnet/Interfaces/Engine/IQueryExecutionPlanCacheProvider.cs +++ b/src/graphql-aspnet/Interfaces/Engine/IQueryExecutionPlanCacheProvider.cs @@ -15,7 +15,7 @@ namespace GraphQL.AspNet.Interfaces.Engine /// /// An interface describing the query plan cache. Build your own cache against any technology you wish - /// and subsitute it in the at start up. This cache instance is a singleton reference + /// and subsitute it in the at start up. This cache instance is a singleton reference /// per server instance. /// public interface IQueryExecutionPlanCacheProvider diff --git a/src/graphql-aspnet/Interfaces/Schema/ISchemaItemValidator.cs b/src/graphql-aspnet/Interfaces/Schema/ISchemaItemValidator.cs index 87eb7a34f..4f47ee452 100644 --- a/src/graphql-aspnet/Interfaces/Schema/ISchemaItemValidator.cs +++ b/src/graphql-aspnet/Interfaces/Schema/ISchemaItemValidator.cs @@ -10,17 +10,18 @@ namespace GraphQL.AspNet.Interfaces.Schema { /// - /// A runtime validator to check instances to ensure they are + /// A runtime validator to check that an instance and ensure that it is /// usable at runtime. /// internal interface ISchemaItemValidator { /// /// Validates that the given is valid and internally consistant - /// with the provided schema instance. + /// with the provided schema instance. If the is invalid in anyway an + /// exception must be thrown. /// - /// The schema item to check. - /// The schema to check against. + /// The schema item to validate. + /// The schema instance that owns . void ValidateOrThrow(ISchemaItem schemaItem, ISchema schema); } } \ No newline at end of file diff --git a/src/graphql-aspnet/Internal/TypeTemplates/GraphFieldTemplateBase.cs b/src/graphql-aspnet/Internal/TypeTemplates/GraphFieldTemplateBase.cs index ef82500e5..f4b7900c5 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/GraphFieldTemplateBase.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/GraphFieldTemplateBase.cs @@ -28,6 +28,7 @@ namespace GraphQL.AspNet.Internal.TypeTemplates using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Schemas.TypeSystem.Scalars; using GraphQL.AspNet.Security; /// @@ -411,7 +412,7 @@ private void BuildUnionProxyInstance() { var proxyType = fieldAttribute.Types.FirstOrDefault(); if (proxyType != null) - proxy = GraphQLProviders.CreateUnionProxyFromType(proxyType); + proxy = GlobalTypes.CreateUnionProxyFromType(proxyType); } // when no proxy type is declared attempt to construct the proxy from types supplied diff --git a/src/graphql-aspnet/Internal/TypeTemplates/ScalarGraphTypeTemplate.cs b/src/graphql-aspnet/Internal/TypeTemplates/ScalarGraphTypeTemplate.cs index f6bf9a1c4..da3d9ac23 100644 --- a/src/graphql-aspnet/Internal/TypeTemplates/ScalarGraphTypeTemplate.cs +++ b/src/graphql-aspnet/Internal/TypeTemplates/ScalarGraphTypeTemplate.cs @@ -32,10 +32,10 @@ public class ScalarGraphTypeTemplate : GraphTypeTemplateBase, IScalarGraphTypeTe /// /// The type to template. public ScalarGraphTypeTemplate(Type typeToTemplate) - : base(GlobalScalars.FindBuiltInScalarType(typeToTemplate) ?? typeToTemplate) + : base(GlobalTypes.FindBuiltInScalarType(typeToTemplate) ?? typeToTemplate) { Validation.ThrowIfNull(typeToTemplate, nameof(typeToTemplate)); - _scalarType = GlobalScalars.FindBuiltInScalarType(typeToTemplate) ?? typeToTemplate; + _scalarType = GlobalTypes.FindBuiltInScalarType(typeToTemplate) ?? typeToTemplate; } /// @@ -43,7 +43,7 @@ protected override void ParseTemplateDefinition() { base.ParseTemplateDefinition(); - var instance = GlobalScalars.CreateScalarInstance(this.ScalarType); + var instance = GlobalTypes.CreateScalarInstance(this.ScalarType); if (instance != null) { @@ -56,7 +56,7 @@ protected override void ParseTemplateDefinition() public override void ValidateOrThrow() { base.ValidateOrThrow(); - GlobalScalars.ValidateScalarTypeOrThrow(this.ScalarType); + GlobalTypes.ValidateScalarTypeOrThrow(this.ScalarType); } /// diff --git a/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphArgumentMaker.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphArgumentMaker.cs index a50907e5d..0e2e8817e 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphArgumentMaker.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphArgumentMaker.cs @@ -65,7 +65,7 @@ public GraphArgumentCreationResult CreateArgument(ISchemaItem owner, IGraphArgum // enforce non-renaming standards in the maker since the // directly controls the formatter - if (GlobalScalars.CanBeRenamed(schemaTypeName)) + if (GlobalTypes.CanBeRenamed(schemaTypeName)) schemaTypeName = formatter.FormatGraphTypeName(schemaTypeName); var typeExpression = template.TypeExpression.CloneTo(schemaTypeName); diff --git a/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphFieldMaker.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphFieldMaker.cs index e4ca231eb..362f72427 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphFieldMaker.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphFieldMaker.cs @@ -147,7 +147,7 @@ protected virtual string PrepareTypeName(IGraphFieldTemplate template) // enforce non-renaming standards in the maker since the // directly controls the formatter - if (GlobalScalars.CanBeRenamed(schemaTypeName)) + if (GlobalTypes.CanBeRenamed(schemaTypeName)) schemaTypeName = _schema.Configuration.DeclarationOptions.GraphNamingFormatter.FormatGraphTypeName(schemaTypeName); return schemaTypeName; diff --git a/src/graphql-aspnet/Schemas/Generation/TypeMakers/ScalarGraphTypeMaker.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/ScalarGraphTypeMaker.cs index 94a36150a..2e7631df9 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeMakers/ScalarGraphTypeMaker.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/ScalarGraphTypeMaker.cs @@ -43,7 +43,7 @@ public GraphTypeCreationResult CreateGraphType(IGraphTypeTemplate typeTemplate) return null; - var scalarType = GlobalScalars.CreateScalarInstanceOrThrow(scalarTemplate.ScalarType); + var scalarType = GlobalTypes.CreateScalarInstanceOrThrow(scalarTemplate.ScalarType); scalarType = scalarType.Clone(_config.DeclarationOptions.GraphNamingFormatter.FormatGraphTypeName(scalarType.Name)); var result = new GraphTypeCreationResult() diff --git a/src/graphql-aspnet/Schemas/Generation/TypeMakers/UnionGraphTypeMaker.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/UnionGraphTypeMaker.cs index 7c2af79fe..1125c89f4 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeMakers/UnionGraphTypeMaker.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/UnionGraphTypeMaker.cs @@ -26,6 +26,7 @@ namespace GraphQL.AspNet.Schemas.Generation.TypeMakers using GraphQL.AspNet.Internal.TypeTemplates; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Schemas.TypeSystem.Scalars; /// /// An object responsible for generating a union graph type from a proxy. @@ -50,7 +51,7 @@ public GraphTypeCreationResult CreateGraphType(IGraphTypeTemplate typeTemplate) if (!(typeTemplate is IUnionGraphTypeTemplate template)) return null; - var proxy = GraphQLProviders.CreateUnionProxyFromType(template.ProxyType); + var proxy = GlobalTypes.CreateUnionProxyFromType(template.ProxyType); return this.CreateUnionFromProxy(proxy); } diff --git a/src/graphql-aspnet/Schemas/GraphTypeNames.cs b/src/graphql-aspnet/Schemas/GraphTypeNames.cs index 762569144..9a1dc18c9 100644 --- a/src/graphql-aspnet/Schemas/GraphTypeNames.cs +++ b/src/graphql-aspnet/Schemas/GraphTypeNames.cs @@ -98,9 +98,9 @@ public static string ParseName(Type type, TypeKind kind) return typeName; type = GraphValidation.EliminateWrappersFromCoreType(type); - if (GlobalScalars.IsBuiltInScalar(type)) + if (GlobalTypes.IsBuiltInScalar(type)) { - typeName = GlobalScalars.CreateScalarInstanceOrThrow(type).Name; + typeName = GlobalTypes.CreateScalarInstanceOrThrow(type).Name; } else if (type.IsEnum) { diff --git a/src/graphql-aspnet/Schemas/SchemaItemValidators/GraphArgumentValidator.cs b/src/graphql-aspnet/Schemas/SchemaItemValidators/GraphArgumentValidator.cs index d6e80c563..af9ed1dd3 100644 --- a/src/graphql-aspnet/Schemas/SchemaItemValidators/GraphArgumentValidator.cs +++ b/src/graphql-aspnet/Schemas/SchemaItemValidators/GraphArgumentValidator.cs @@ -13,7 +13,6 @@ namespace GraphQL.AspNet.Schemas.SchemaItemValidators using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Schemas.TypeSystem; /// /// A validator of a completed and schema-attached graph argument that ensures it can function as diff --git a/src/graphql-aspnet/Schemas/SchemaItemValidators/GraphFieldValidator.cs b/src/graphql-aspnet/Schemas/SchemaItemValidators/GraphFieldValidator.cs index 270a39c6d..49a1e5daf 100644 --- a/src/graphql-aspnet/Schemas/SchemaItemValidators/GraphFieldValidator.cs +++ b/src/graphql-aspnet/Schemas/SchemaItemValidators/GraphFieldValidator.cs @@ -16,7 +16,6 @@ internal class GraphFieldValidator : BaseSchemaItemValidator { public override void ValidateOrThrow(ISchemaItem schemaItem, ISchema schema) { - } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/GlobalScalars.cs b/src/graphql-aspnet/Schemas/TypeSystem/GlobalTypes.cs similarity index 89% rename from src/graphql-aspnet/Schemas/TypeSystem/Scalars/GlobalScalars.cs rename to src/graphql-aspnet/Schemas/TypeSystem/GlobalTypes.cs index a172f2bda..68d848d0f 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/GlobalScalars.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/GlobalTypes.cs @@ -11,6 +11,7 @@ namespace GraphQL.AspNet.Schemas.TypeSystem.Scalars { using System; using System.Collections.Generic; + using System.Reflection; using GraphQL.AspNet.Common; using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Common.Generics; @@ -19,40 +20,50 @@ namespace GraphQL.AspNet.Schemas.TypeSystem.Scalars using GraphQL.AspNet.Internal; /// - /// A map of .NET types and their related built in scalar types. + /// A map of .NET types and their related built in scalar types and unions. /// - public static class GlobalScalars + public static class GlobalTypes { private static readonly Dictionary _scalarGraphTypeTypesByConcreteType; private static readonly Dictionary _scalarsByName; private static readonly HashSet _fixedNamedScalars; - static GlobalScalars() + static GlobalTypes() { _scalarGraphTypeTypesByConcreteType = new Dictionary(); _scalarsByName = new Dictionary(StringComparer.OrdinalIgnoreCase); _fixedNamedScalars = new HashSet(); + // specification defined scalars (cannot be altered) ValidateAndRegisterBuiltInScalar(true); + ValidateAndRegisterBuiltInScalar(true); + ValidateAndRegisterBuiltInScalar(true); + ValidateAndRegisterBuiltInScalar(true); + ValidateAndRegisterBuiltInScalar(true); + + // other helpful scalars added to the library for + // convience with .NET ValidateAndRegisterBuiltInScalar(); + ValidateAndRegisterBuiltInScalar(); ValidateAndRegisterBuiltInScalar(); - ValidateAndRegisterBuiltInScalar(true); + ValidateAndRegisterBuiltInScalar(); ValidateAndRegisterBuiltInScalar(); - ValidateAndRegisterBuiltInScalar(true); - ValidateAndRegisterBuiltInScalar(true); + + ValidateAndRegisterBuiltInScalar(); ValidateAndRegisterBuiltInScalar(); ValidateAndRegisterBuiltInScalar(); + ValidateAndRegisterBuiltInScalar(); + ValidateAndRegisterBuiltInScalar(); ValidateAndRegisterBuiltInScalar(); - ValidateAndRegisterBuiltInScalar(); - ValidateAndRegisterBuiltInScalar(); - ValidateAndRegisterBuiltInScalar(true); + ValidateAndRegisterBuiltInScalar(); ValidateAndRegisterBuiltInScalar(); - ValidateAndRegisterBuiltInScalar(); - ValidateAndRegisterBuiltInScalar(); + + ValidateAndRegisterBuiltInScalar(); + ValidateAndRegisterBuiltInScalar(); } private static void ValidateAndRegisterBuiltInScalar(bool isFixedName = false) @@ -299,13 +310,40 @@ public static IScalarGraphType CreateScalarInstance(Type scalarType) } /// - /// Gets the list of concrete types that represent all known scalars. + /// attempts to instnatiate the provided type as a union proxy. + /// + /// Type of the proxy to create. + /// IGraphUnionProxy. + public static IGraphUnionProxy CreateUnionProxyFromType(Type proxyType) + { + if (proxyType == null) + return null; + + IGraphUnionProxy proxy = null; + if (Validation.IsCastable(proxyType)) + { + var paramlessConstructor = proxyType.GetConstructor(BindingFlags.Instance | BindingFlags.Public, null, Type.EmptyTypes, null); + if (paramlessConstructor == null) + { + throw new GraphTypeDeclarationException( + $"The union proxy type '{proxyType.FriendlyName()}' could not be instantiated. " + + "All union proxy types must declare a parameterless constructor."); + } + + proxy = InstanceFactory.CreateInstance(proxyType) as IGraphUnionProxy; + } + + return proxy; + } + + /// + /// Gets the list of concrete types that represent all internally defined, global scalars. /// /// The set of concrete types for all the global scalars. - public static IEnumerable ConcreteTypes => _scalarGraphTypeTypesByConcreteType.Keys; + public static IEnumerable ScalarConcreteTypes => _scalarGraphTypeTypesByConcreteType.Keys; /// - /// Gets the types that represent the object for all known scalars. + /// Gets the types that represent the objects for all internally defined, global scalars. /// /// The set of scalar instance types for all global scalars. public static IEnumerable ScalarInstanceTypes => _scalarGraphTypeTypesByConcreteType.Values; diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedDirective.cs b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedDirective.cs index 740c2eaa9..34e01c5e4 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedDirective.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedDirective.cs @@ -41,10 +41,6 @@ public override void Initialize(IntrospectedSchema introspectedSchema) foreach (var arg in directiveArguments) { var introspectedType = introspectedSchema.FindIntrospectedType(arg.TypeExpression.TypeName); - if(introspectedType == null) - { - var str = ""; - } introspectedType = Introspection.WrapBaseTypeWithModifiers(introspectedType, arg.TypeExpression); var inputValue = new IntrospectedInputValueType(arg, introspectedType); list.Add(inputValue); diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedField.cs b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedField.cs index be0dadaf6..55c4e3f87 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedField.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedField.cs @@ -44,11 +44,6 @@ public override void Initialize(IntrospectedSchema introspectedSchema) { var introspectedType = introspectedSchema.FindIntrospectedType(arg.TypeExpression.TypeName); introspectedType = Introspection.WrapBaseTypeWithModifiers(introspectedType, arg.TypeExpression); - if(introspectedType == null) - { - var str = ""; - } - var inputValue = new IntrospectedInputValueType(arg, introspectedType); inputValue.Initialize(introspectedSchema); list.Add(inputValue); diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedType.cs b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedType.cs index 1b235336b..8ce45b326 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedType.cs @@ -115,16 +115,7 @@ private void LoadFields(IntrospectedSchema schema) foreach (var field in fieldContainer.Fields.Where(x => x.Publish)) { IntrospectedType introspectedType = schema.FindIntrospectedType(field.TypeExpression.TypeName); - if (introspectedType == null) - { - string str = ""; - } - introspectedType = Introspection.WrapBaseTypeWithModifiers(introspectedType, field.TypeExpression); - if(introspectedType == null) - { - string str = ""; - } var introField = new IntrospectedField(field, introspectedType); fields.Add(introField); introField.Initialize(schema); diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/Introspection.cs b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/Introspection.cs index d36adf383..c5ac10da1 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/Introspection.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/Introspection.cs @@ -41,11 +41,6 @@ public static IntrospectedType WrapBaseTypeWithModifiers(IntrospectedType baseTy { for (var i = wrappers.Count - 1; i >= 0; i--) { - if(baseType == null) - { - string str = ""; - } - switch (wrappers[i]) { case MetaGraphTypes.IsNotNull: diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/ScalarGraphTypeBase.cs b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/ScalarGraphTypeBase.cs index d8685a12b..371f09726 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/ScalarGraphTypeBase.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/ScalarGraphTypeBase.cs @@ -103,11 +103,11 @@ public virtual string SerializeToQueryLanguage(object item) public virtual IScalarGraphType Clone(string newName) { newName = Validation.ThrowIfNullWhiteSpaceOrReturn(newName, nameof(newName)); - var newInstance = GlobalScalars.CreateScalarInstanceOrThrow(this.GetType()) as ScalarGraphTypeBase; + var newInstance = GlobalTypes.CreateScalarInstanceOrThrow(this.GetType()) as ScalarGraphTypeBase; // some built in scalars (defined against this class) // should never be renameable (string, int, float, id, boolean) - if (GlobalScalars.CanBeRenamed(this.Name)) + if (GlobalTypes.CanBeRenamed(this.Name)) newInstance.Name = newName; return newInstance; diff --git a/src/graphql-aspnet/Schemas/TypeSystem/TypeCollections/SchemaTypeCollection.cs b/src/graphql-aspnet/Schemas/TypeSystem/TypeCollections/SchemaTypeCollection.cs index 3585b6600..026ad609e 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/TypeCollections/SchemaTypeCollection.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/TypeCollections/SchemaTypeCollection.cs @@ -95,7 +95,6 @@ public bool EnsureGraphType(IGraphType graphType, Type associatedType = null) // they can now be safely included if (associatedType != null) { - var unregisteredFields = _typeQueue.DequeueFields(associatedType); if (graphType is IExtendableGraphType objType) { diff --git a/src/graphql-aspnet/Schemas/TypeSystem/VirtualGraphField.cs b/src/graphql-aspnet/Schemas/TypeSystem/VirtualGraphField.cs index b88233e19..93fc096c3 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/VirtualGraphField.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/VirtualGraphField.cs @@ -155,9 +155,6 @@ public virtual bool CanResolveForGraphType(IGraphType graphType) /// The depreciation reason. public string DepreciationReason { get; set; } - /// - public bool IsLeaf => false; - /// public bool IsDeprecated { get; set; } diff --git a/src/unit-tests/graphql-aspnet-testframework/GraphQLTemplateHelper.cs b/src/unit-tests/graphql-aspnet-testframework/GraphQLTemplateHelper.cs index d14a8e0c4..cc1b965b8 100644 --- a/src/unit-tests/graphql-aspnet-testframework/GraphQLTemplateHelper.cs +++ b/src/unit-tests/graphql-aspnet-testframework/GraphQLTemplateHelper.cs @@ -106,7 +106,7 @@ public static IGraphTypeTemplate CreateGraphTypeTemplate(TypeKind? kind = /// IGraphItemTemplate. public static IGraphTypeTemplate CreateGraphTypeTemplate(Type objectType, TypeKind? kind = null, bool autoParse = true) { - objectType = GlobalScalars.FindBuiltInScalarType(objectType) ?? objectType; + objectType = GlobalTypes.FindBuiltInScalarType(objectType) ?? objectType; IGraphTypeTemplate template; if (Validation.IsCastable(objectType)) diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/DirectiveApplicatorTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/DirectiveApplicatorTests.cs index 2db6aa678..f71f9b57c 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/DirectiveApplicatorTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/DirectiveApplicatorTests.cs @@ -47,7 +47,7 @@ object[] CreateArgs(ISchemaItem item) .WithArguments(CreateArgs) .ToItems(x => x is IGraphField); - ((ISchemaExtension)applicator).Extend(schema); + ((IGraphQLServerExtension)applicator).EnsureSchema(schema); for (var i = 0; i < matchedSchemaItems.Count; i++) { @@ -86,7 +86,7 @@ object[] CreateArgsOther(ISchemaItem item) .WithArguments(CreateArgsOther) .ToItems(x => x is IGraphField); - ((ISchemaExtension)applicator).Extend(schema); + ((IGraphQLServerExtension)applicator).EnsureSchema(schema); // count would be greater than zero fi and only if the last // supplied function was executed and any fields were found @@ -108,7 +108,7 @@ public void ConstantSuppliedArgumentsAreUsed_ForAllMatchedItems() .WithArguments(argSet) .ToItems(x => x is IGraphField); - ((ISchemaExtension)applicator).Extend(schema); + ((IGraphQLServerExtension)applicator).EnsureSchema(schema); foreach (var item in schema.AllSchemaItems()) { diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultScalarTypeProviderTestData/ScalarTestBase.cs b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultScalarTypeProviderTestData/ScalarTestBase.cs index c6ac4c6df..aa17c1188 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultScalarTypeProviderTestData/ScalarTestBase.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultScalarTypeProviderTestData/ScalarTestBase.cs @@ -41,7 +41,7 @@ protected ScalarTestBase() public virtual IScalarGraphType Clone(string newName) { newName = Validation.ThrowIfNullWhiteSpaceOrReturn(newName, nameof(newName)); - var newInstance = GlobalScalars.CreateScalarInstanceOrThrow(this.GetType()) as ScalarTestBase; + var newInstance = GlobalTypes.CreateScalarInstanceOrThrow(this.GetType()) as ScalarTestBase; newInstance.Name = newName; return newInstance; } diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/DirectiveProcessorTypeSystemTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/DirectiveProcessorTypeSystemTests.cs index de3660fcc..df9d41f1e 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/DirectiveProcessorTypeSystemTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/DirectiveProcessorTypeSystemTests.cs @@ -303,7 +303,7 @@ public void UncaughtExceptionDuringPipelineExecution_IsCaughtAndPackagedByProces Assert.AreEqual(thrownException, ex.InnerException); Assert.IsNull(ex.InnerException.InnerException); } - catch(Exception ex) + catch { Assert.Fail("Unexpected exception was thrown"); } diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/RulesEngine/EnsureValidationRuleUrls.cs b/src/unit-tests/graphql-aspnet-tests/Execution/RulesEngine/EnsureValidationRuleUrls.cs index 08f0ea3d4..46715f2bb 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/RulesEngine/EnsureValidationRuleUrls.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/RulesEngine/EnsureValidationRuleUrls.cs @@ -16,6 +16,7 @@ namespace GraphQL.AspNet.Tests.Execution.RulesEngine using GraphQL.AspNet.Common; using GraphQL.AspNet.Common.Generics; using GraphQL.AspNet.Interfaces.Execution.RulesEngine; + using GraphQL.AspNet.Schemas.TypeSystem.Scalars; using NUnit.Framework; [TestFixture] @@ -27,7 +28,7 @@ public void EnsureAllUrlsUniquePerRule() // for all links to specification rules ensure that // each rule number has a valid link and that it is // unique - var ruleTypes = typeof(GraphQLProviders) + var ruleTypes = typeof(GlobalTypes) .Assembly .GetTypes() .Where(Validation.IsCastable) diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/InputResolverGeneratorTests.cs b/src/unit-tests/graphql-aspnet-tests/Internal/InputResolverGeneratorTests.cs index 15a4bc90c..676efaca5 100644 --- a/src/unit-tests/graphql-aspnet-tests/Internal/InputResolverGeneratorTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Internal/InputResolverGeneratorTests.cs @@ -48,7 +48,7 @@ private ISchema CreateSchema() { var builder = new TestServerBuilder(); - foreach (var scalarConcreteType in GlobalScalars.ScalarInstanceTypes) + foreach (var scalarConcreteType in GlobalTypes.ScalarInstanceTypes) builder.AddType(scalarConcreteType); builder.AddType(typeof(TestEnum)); diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/GraphTypeNamesTests.cs b/src/unit-tests/graphql-aspnet-tests/Internal/Templating/GraphTypeNamesTests.cs index 10beeaa29..4fe8c75a7 100644 --- a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/GraphTypeNamesTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Internal/Templating/GraphTypeNamesTests.cs @@ -66,13 +66,13 @@ public void Item_WithAttribute_ReturnsAttributeDefinedName() public void ScalarNames_AreUnique() { var nameSet = new HashSet(); - foreach (var scalarType in GlobalScalars.ScalarInstanceTypes) + foreach (var scalarType in GlobalTypes.ScalarInstanceTypes) { var scalar = InstanceFactory.CreateInstance(scalarType) as IScalarGraphType; nameSet.Add(scalar.Name.ToLowerInvariant()); } - Assert.AreEqual(GlobalScalars.ScalarInstanceTypes.Count(), nameSet.Count); + Assert.AreEqual(GlobalTypes.ScalarInstanceTypes.Count(), nameSet.Count); } [Test] diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/DefaultTypeTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/DefaultTypeTests.cs index 3b71311e0..7f644bf7f 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/DefaultTypeTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/DefaultTypeTests.cs @@ -28,8 +28,8 @@ public void Scalars_EnsureAllGlobalScalarNamesHaveAnAssociatedType() foreach (FieldInfo fi in fields) { Assert.IsTrue( - GlobalScalars.IsBuiltInScalar(fi.GetRawConstantValue()?.ToString()), - $"The scalar name '{fi.GetRawConstantValue()}' does not exist in the {{{nameof(GlobalScalars)}}} collection."); + GlobalTypes.IsBuiltInScalar(fi.GetRawConstantValue()?.ToString()), + $"The scalar name '{fi.GetRawConstantValue()}' does not exist in the {{{nameof(GlobalTypes)}}} collection."); } } } diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/IExternalArgumentChecker.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/IExternalArgumentChecker.cs deleted file mode 100644 index ba2ca2c77..000000000 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/IExternalArgumentChecker.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace GraphQL.AspNet.Tests.Schemas -{ - using System; - using System.Collections.Generic; - using System.Linq; - using System.Text; - using System.Threading.Tasks; - - internal interface IExternalArgumentChecker - { - } -} diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaLanguageGeneratorTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaLanguageGeneratorTests.cs index c81eb3179..21688fb59 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaLanguageGeneratorTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaLanguageGeneratorTests.cs @@ -235,7 +235,7 @@ public SchemaLanguageGeneratorTests() // ensure all scalars represented _unUsedScalarTypes = new List(); - foreach (var type in GlobalScalars.ConcreteTypes) + foreach (var type in GlobalTypes.ScalarConcreteTypes) { if (Validation.IsNullableOfT(type)) continue; From 6e0c0d6162346a12660c5654e9124500adc6b5f8 Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Wed, 12 Jul 2023 17:20:55 -0700 Subject: [PATCH 30/63] WIP, clean up and file reorg --- src/graphql-aspnet/Common/TypeCollection.cs | 96 ------------------ ...faultGraphQLSchemaFactory_Introspection.cs | 1 - .../Engine/DefaultGraphQLTypeMakerFactory.cs | 39 +------- .../Execution/DirectiveProcessorTypeSystem.cs | 2 +- .../Configuration/IGraphQLServerExtension.cs | 6 +- .../Interfaces/Schema/IScalarGraphType.cs | 9 -- .../Generation/TypeMakers/DirectiveMaker.cs | 1 - .../TypeMakers/ScalarGraphTypeMaker.cs | 1 - .../TypeTemplates/AppliedDirectiveTemplate.cs | 0 .../ApplyDirectiveAttributeExtensions.cs | 0 .../ControllerActionGraphFieldTemplate.cs | 0 .../TypeTemplates/DependentType.cs | 0 .../TypeTemplates/EnumGraphTypeTemplate.cs | 0 .../TypeTemplates/EnumValueTemplate.cs | 0 .../TypeTemplates/GraphArgumentTemplate.cs | 0 .../TypeTemplates/GraphControllerTemplate.cs | 0 .../GraphDirectiveMethodTemplate.cs | 0 .../GraphDirectiveMethodTemplateContainer.cs | 0 .../TypeTemplates/GraphDirectiveTemplate.cs | 0 .../TypeTemplates/GraphFieldTemplateBase.cs | 0 .../TypeTemplates/GraphFieldTemplateSource.cs | 0 .../GraphTypeExtensionFieldTemplate.cs | 0 .../TypeTemplates/GraphTypeTemplateBase.cs | 0 .../TypeTemplates/GraphTypeTemplates.cs | 73 ++++++++++++++ .../TypeTemplates/InputGraphFieldTemplate.cs | 0 .../InputObjectGraphTypeTemplate.cs | 0 .../InterfaceGraphTypeTemplate.cs | 0 .../TypeTemplates/MemberInfoProvider.cs | 0 .../TypeTemplates/MethodGraphFieldTemplate.cs | 0 .../MethodGraphFieldTemplateBase.cs | 0 .../NonLeafGraphTypeTemplateBase.cs | 0 .../TypeTemplates/ObjectGraphTypeTemplate.cs | 0 .../PropertyGraphFieldTemplate.cs | 0 .../RuntimeGraphControllerTemplate.cs | 0 .../RuntimeSchemaItemAttributeProvider.cs | 0 .../TypeTemplates/ScalarGraphTypeTemplate.cs | 0 .../TypeTemplates/SchemaItemTemplateBase.cs | 0 .../TypeTemplates/UnionGraphTypeTemplate.cs | 0 .../Schemas/TypeSystem/GlobalTypes.cs | 98 +++++++++++++------ .../TypeSystem/Scalars/BooleanScalarType.cs | 4 - .../TypeSystem/Scalars/ByteScalarType.cs | 4 - .../TypeSystem/Scalars/DateOnlyScalarType.cs | 4 - .../Scalars/DateTimeOffsetScalarType.cs | 4 - .../TypeSystem/Scalars/DateTimeScalarType.cs | 4 - .../TypeSystem/Scalars/DecimalScalarType.cs | 4 - .../TypeSystem/Scalars/DoubleScalarType.cs | 4 - .../TypeSystem/Scalars/FloatScalarType.cs | 4 - .../TypeSystem/Scalars/GraphIdScalarType.cs | 4 - .../TypeSystem/Scalars/GuidScalarType.cs | 4 - .../TypeSystem/Scalars/IntScalarType.cs | 4 - .../TypeSystem/Scalars/LongScalarType.cs | 4 - .../TypeSystem/Scalars/SByteScalarType.cs | 4 - .../TypeSystem/Scalars/ScalarGraphTypeBase.cs | 5 +- .../TypeSystem/Scalars/ScalarReference.cs | 12 --- .../TypeSystem/Scalars/ShortScalarType.cs | 4 - .../TypeSystem/Scalars/StringScalarType.cs | 4 - .../TypeSystem/Scalars/TimeOnlyScalarType.cs | 4 - .../TypeSystem/Scalars/UIntScalarType.cs | 4 - .../TypeSystem/Scalars/ULongScalarType.cs | 4 - .../TypeSystem/Scalars/UShortScalarType.cs | 4 - .../TypeSystem/Scalars/UriScalarType.cs | 4 - .../TypeCollections/ConcreteTypeCollection.cs | 3 +- .../Schema/FileUploadScalarGraphType.cs | 3 - src/graphql-aspnet/graphql-aspnet.csproj | 4 - .../GraphQLTemplateHelper.cs | 2 + .../TestServer.cs | 3 +- .../CommonHelpers/TestServerExtensions.cs | 35 +++++++ .../ScalarNullOtherTypeCollection.cs | 1 - .../ScalarOtherTypeInUse.cs | 1 - .../ScalarTestBase.cs | 3 - .../TwoPropertyObjectAsScalar.cs | 3 - .../Engine/DefaultSchemaFactoryTests.cs | 40 ++++---- .../TypeMakers/DirectiveTypeMakerTests.cs | 7 +- .../TypeMakers/FieldMaker_InputFieldTests.cs | 26 ++--- .../FieldMaker_StandardFieldTests.cs | 10 +- .../TypeMakers/GraphTypeMakerTestBase.cs | 8 +- .../TypeMakers/InterfaceTypeMakerTests.cs | 16 ++- .../TypeMakers/ObjectGraphTypeMakerTests.cs | 5 +- .../TestData/CustomScalarWithDirectives.cs | 2 - .../Resolvers}/InputResolverGeneratorTests.cs | 0 .../InputValueNodeTestData/CoffeeCan.cs | 0 .../InputValueNodeTestData/Telephone.cs | 0 .../Resolvers}/ObjectMethodResolverTests.cs | 0 .../Resolvers}/ObjectPropertyResolverTests.cs | 0 .../IResolverInterface.cs | 0 .../ValueResolversTestData/ResolvableEnum.cs | 0 .../ValueResolversTestData/ResolverObject.cs | 0 .../ValueResolversTestData/ResolverStructA.cs | 0 .../ValueResolversTestData/ResolverStructB.cs | 0 .../CustomSpecifiedScalar.cs | 2 - .../MarkedScalarByAttribute.cs | 2 - .../Templating/ActionMethodTemplateTests.cs | 0 .../ActionMethodWithDirectiveController.cs | 0 .../ActionResultReturnTypeController.cs | 0 .../ArrayInputMethodController.cs | 0 .../ComplexityValueCheckController.cs | 0 .../ActionTestData/ContainerController.cs | 0 .../ActionTestData/CustomNamedItem.cs | 0 .../Templating/ActionTestData/ITestItem.cs | 0 .../ActionTestData/IUnionTestDataItem.cs | 0 .../InterfaceReturnTypeController.cs | 0 .../ActionTestData/OneMethodController.cs | 0 .../ActionTestData/ScalarInUnionController.cs | 0 .../Templating/ActionTestData/TestItemA.cs | 0 .../Templating/ActionTestData/TestItemB.cs | 0 .../Templating/ActionTestData/UnionDataA.cs | 0 .../Templating/ActionTestData/UnionDataB.cs | 0 .../ActionTestData/UnionTestController.cs | 0 .../ActionTestData/UnionTestProxy.cs | 0 .../AppliedDirectiveTemplateTests.cs | 0 .../Templating/ArgumentTemplateTests.cs | 0 .../Templating/ControllerTemplateTests.cs | 0 .../ArrayInputParamController.cs | 0 .../ArrayReturnController.cs | 0 .../ControllerWithDirective.cs | 0 .../ControllerWithStaticMethod.cs | 0 .../DeclaredGraphRootController.cs | 0 .../InvalidRouteController.cs | 0 .../NoInheritanceFromBaseController.cs | 0 .../NoRouteSpecifierController.cs | 0 .../ControllerTestData/OneMethodController.cs | 0 .../SimpleControllerNoMethods.cs | 0 .../TwoMethodClashController.cs | 0 .../TwoMethodNoClashController.cs | 0 .../TwoMethodsDifferentRootsController.cs | 0 .../DirectiveMethodTemplateTests.cs | 0 .../Templating/DirectiveTemplateTests.cs | 0 .../DirectiveTestData/DirectiveWithArgs.cs | 0 .../DirectiveWithDeclaredDirectiveOnMethod.cs | 0 .../DirectiveWithDeclaredDirectives.cs | 0 .../DirectiveWithRequirements.cs | 0 .../DirectiveWithSecurityRequirements.cs | 0 .../MismatchedSignaturesDirective.cs | 0 .../NoLocationAttributeDirective.cs | 0 .../DirectiveTestData/NoLocationsDirective.cs | 0 .../OverlappingLocationsDirective.cs | 0 .../DirectiveTestData/RepeatableDirective.cs | 0 .../SimpleExecutableDirective.cs | 0 .../TestDirectiveMethodTemplateContainer.cs | 0 .../TestDirectiveMethodTemplateContainer2.cs | 0 .../Templating/EnumGraphTypeTemplateTests.cs | 0 .../EnumTestData/DeprecatedValueEnum.cs | 0 .../EnumTestData/EnumCompleteByte.cs | 0 .../EnumTestData/EnumCompleteSByte.cs | 0 .../Templating/EnumTestData/EnumFromByte.cs | 0 .../Templating/EnumTestData/EnumFromInt.cs | 0 .../Templating/EnumTestData/EnumFromLong.cs | 0 .../Templating/EnumTestData/EnumFromSByte.cs | 0 .../Templating/EnumTestData/EnumFromShort.cs | 0 .../Templating/EnumTestData/EnumFromUInt.cs | 0 .../Templating/EnumTestData/EnumFromULong.cs | 0 .../Templating/EnumTestData/EnumFromUShort.cs | 0 .../EnumTestData/EnumWithDescription.cs | 0 .../EnumTestData/EnumWithDescriptions.cs | 0 .../EnumTestData/EnumWithDirective.cs | 0 .../EnumTestData/EnumWithDirectiveOnOption.cs | 0 .../EnumTestData/EnumWithDuplicateValues.cs | 0 .../EnumWithDuplicateValuesFromComposite.cs | 0 .../EnumTestData/EnumWithGraphName.cs | 0 .../EnumTestData/EnumWithInvalidValueName.cs | 0 .../EnumWithValueWithGraphName.cs | 0 ...ValueWithGraphNameButGraphNameIsInvalid.cs | 0 .../Templating/EnumTestData/SimpleEnum.cs | 0 .../ExtensionMethodController.cs | 0 .../GraphTypeNameTestData/AttributedClass.cs | 0 .../AttributedClassInvalidName.cs | 0 .../GraphTypeNameTestData/EnumNameTest.cs | 0 .../EnumNameTestWithTypeName.cs | 0 .../GraphTypeNameTestData/GenericClass.cs | 0 .../GenericClassWithAttribute.cs | 0 .../GraphTypeNameTestData/NoAttributeClass.cs | 0 .../NoAttributeClassForNewName.cs | 0 .../Templating/GraphTypeNamesTests.cs | 0 .../InputGraphFieldTemplateTests.cs | 0 .../Templating/InputObjectTemplateTests.cs | 0 .../InterfaceGraphTypeTemplateTests.cs | 0 .../InterfaceTestData/IInterface1.cs | 0 .../InterfaceTestData/IInterface2.cs | 0 .../InterfaceTestData/IInterface3.cs | 0 .../IInterfaceWithDirective.cs | 0 .../InterfaceTestData/INestedInterface1.cs | 0 .../InterfaceTestData/INestedInterface2.cs | 0 .../InterfaceTestData/ISimpleInterface.cs | 0 .../ITestableInterfaceImplementation.cs | 0 ...nterfaceThatInheritsDeclaredMethodField.cs | 0 ...erfaceThatInheritsUndeclaredMethodField.cs | 0 .../InterfaceWithDeclaredInterfaceField.cs | 0 .../InterfaceWithUndeclaredInterfaceField.cs | 0 .../MethodGraphFieldTemplateTests.cs | 0 .../MethodTestData/ArrayMethodObject.cs | 0 .../Templating/MethodTestData/MethodClass.cs | 0 .../MethodClassWithDirective.cs | 0 .../ObjectGraphTypeTemplateTests.cs | 0 .../ObjectTypeTests/CustomStruct.cs | 0 .../ObjectTypeTests/DescriptionObject.cs | 0 .../ObjectTypeTests/DescriptionStruct.cs | 0 .../ObjectTypeTests/ForceSkippedStruct.cs | 0 .../ObjectTypeTests/ForcedSkippedObject.cs | 0 .../ObjectTypeTests/IInputObject.cs | 0 .../ObjectTypeTests/InputNameObject.cs | 0 .../InputObjectIWithTaskProperty.cs | 0 .../InputObjectWithDirective.cs | 0 .../InputObjectWithDuplicateProperty.cs | 0 .../InputObjectWithGraphActionProperty.cs | 0 .../InputObjectWithInterfaceProperty.cs | 0 .../InputObjectWithUnionProxyProperty.cs | 0 .../ObjectThatInheritsExplicitMethodField.cs | 0 ...bjectThatInheritsNonExplicitMethodField.cs | 0 .../ObjectWithDeconstructor.cs | 0 .../ObjectTypeTests/ObjectWithDirective.cs | 0 .../ObjectWithExplicitMethodField.cs | 0 .../ObjectWithInvalidNonDeclaredMethods.cs | 0 .../ObjectWithMutationOperation.cs | 0 .../ObjectTypeTests/ObjectWithNoSetters.cs | 0 .../ObjectWithNonExplicitMethodField.cs | 0 .../ObjectTypeTests/ObjectWithStatics.cs | 0 .../ObjectTypeTests/OneMarkedMethod.cs | 0 .../ObjectTypeTests/OneMarkedProperty.cs | 0 .../ObjectTypeTests/RequiredConstructor.cs | 0 .../ObjectTypeTests/SimpleObjectNoMethods.cs | 0 .../ObjectTypeTests/SimpleObjectScalar.cs | 0 .../SimpleScalarObjectGraphType.cs | 2 - .../ObjectTypeTests/SimpleScalarStruct.cs | 0 .../SimpleScalarStructGraphType.cs | 2 - .../ObjectTypeTests/SimpleStructNoMethods.cs | 0 .../ObjectTypeTests/StructOneMarkedMethod.cs | 0 .../StructOneMarkedProperty.cs | 0 .../StructTwoMethodsWithSameName.cs | 0 ...TwoMethodsWithSameNameWithAttributeDiff.cs | 0 .../StructWithInvalidNonDeclaredMethods.cs | 0 .../ObjectTypeTests/StructWithNoSetters.cs | 0 .../ObjectTypeTests/TwoMethodsWithSameName.cs | 0 ...TwoMethodsWithSameNameWithAttributeDiff.cs | 0 .../ObjectTypeTests/TypeWithArrayProperty.cs | 0 .../ParameterTestData/ParameterTestClass.cs | 0 .../PropertyGraphFieldTemplateTests.cs | 0 .../ArrayKeyValuePairObject.cs | 0 .../PropertyTestData/ArrayPropertyObject.cs | 0 .../PropertyTestData/IPropInterface.cs | 0 .../PropertyTestData/NoGetterOnProperty.cs | 0 .../PropAuthorizeAttribute.cs | 0 .../PropertyClassWithDirective.cs | 0 .../PropertyTestData/PropertyProxy.cs | 0 .../PropertyTestData/SimplePropertyObject.cs | 0 .../TypeExtensionFieldTemplateTests.cs | 0 .../ControllerWithNoSecurityPolicies.cs | 0 .../ControllerWithSecurityPolicies.cs | 0 .../GraphValidationTests.cs | 0 .../TestEnum.cs | 0 .../TestEnumNoDefaultValue.cs | 0 .../TestEnumNotIncludedDefault.cs | 0 ...ntrospectionDefaultValueValidationTests.cs | 0 ...CollectionInterefaceImplementationTests.cs | 8 +- .../Schemas/SchemaTypeCollectionTests.cs | 8 +- .../FileUploadScalarGraphTypeTests.cs | 7 -- 255 files changed, 247 insertions(+), 379 deletions(-) delete mode 100644 src/graphql-aspnet/Common/TypeCollection.cs rename src/graphql-aspnet/{Internal => Schemas/Generation}/TypeTemplates/AppliedDirectiveTemplate.cs (100%) rename src/graphql-aspnet/{Internal => Schemas/Generation}/TypeTemplates/ApplyDirectiveAttributeExtensions.cs (100%) rename src/graphql-aspnet/{Internal => Schemas/Generation}/TypeTemplates/ControllerActionGraphFieldTemplate.cs (100%) rename src/graphql-aspnet/{Internal => Schemas/Generation}/TypeTemplates/DependentType.cs (100%) rename src/graphql-aspnet/{Internal => Schemas/Generation}/TypeTemplates/EnumGraphTypeTemplate.cs (100%) rename src/graphql-aspnet/{Internal => Schemas/Generation}/TypeTemplates/EnumValueTemplate.cs (100%) rename src/graphql-aspnet/{Internal => Schemas/Generation}/TypeTemplates/GraphArgumentTemplate.cs (100%) rename src/graphql-aspnet/{Internal => Schemas/Generation}/TypeTemplates/GraphControllerTemplate.cs (100%) rename src/graphql-aspnet/{Internal => Schemas/Generation}/TypeTemplates/GraphDirectiveMethodTemplate.cs (100%) rename src/graphql-aspnet/{Internal => Schemas/Generation}/TypeTemplates/GraphDirectiveMethodTemplateContainer.cs (100%) rename src/graphql-aspnet/{Internal => Schemas/Generation}/TypeTemplates/GraphDirectiveTemplate.cs (100%) rename src/graphql-aspnet/{Internal => Schemas/Generation}/TypeTemplates/GraphFieldTemplateBase.cs (100%) rename src/graphql-aspnet/{Internal => Schemas/Generation}/TypeTemplates/GraphFieldTemplateSource.cs (100%) rename src/graphql-aspnet/{Internal => Schemas/Generation}/TypeTemplates/GraphTypeExtensionFieldTemplate.cs (100%) rename src/graphql-aspnet/{Internal => Schemas/Generation}/TypeTemplates/GraphTypeTemplateBase.cs (100%) create mode 100644 src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphTypeTemplates.cs rename src/graphql-aspnet/{Internal => Schemas/Generation}/TypeTemplates/InputGraphFieldTemplate.cs (100%) rename src/graphql-aspnet/{Internal => Schemas/Generation}/TypeTemplates/InputObjectGraphTypeTemplate.cs (100%) rename src/graphql-aspnet/{Internal => Schemas/Generation}/TypeTemplates/InterfaceGraphTypeTemplate.cs (100%) rename src/graphql-aspnet/{Internal => Schemas/Generation}/TypeTemplates/MemberInfoProvider.cs (100%) rename src/graphql-aspnet/{Internal => Schemas/Generation}/TypeTemplates/MethodGraphFieldTemplate.cs (100%) rename src/graphql-aspnet/{Internal => Schemas/Generation}/TypeTemplates/MethodGraphFieldTemplateBase.cs (100%) rename src/graphql-aspnet/{Internal => Schemas/Generation}/TypeTemplates/NonLeafGraphTypeTemplateBase.cs (100%) rename src/graphql-aspnet/{Internal => Schemas/Generation}/TypeTemplates/ObjectGraphTypeTemplate.cs (100%) rename src/graphql-aspnet/{Internal => Schemas/Generation}/TypeTemplates/PropertyGraphFieldTemplate.cs (100%) rename src/graphql-aspnet/{Internal => Schemas/Generation}/TypeTemplates/RuntimeGraphControllerTemplate.cs (100%) rename src/graphql-aspnet/{Internal => Schemas/Generation}/TypeTemplates/RuntimeSchemaItemAttributeProvider.cs (100%) rename src/graphql-aspnet/{Internal => Schemas/Generation}/TypeTemplates/ScalarGraphTypeTemplate.cs (100%) rename src/graphql-aspnet/{Internal => Schemas/Generation}/TypeTemplates/SchemaItemTemplateBase.cs (100%) rename src/graphql-aspnet/{Internal => Schemas/Generation}/TypeTemplates/UnionGraphTypeTemplate.cs (100%) create mode 100644 src/unit-tests/graphql-aspnet-tests/CommonHelpers/TestServerExtensions.cs rename src/unit-tests/graphql-aspnet-tests/{Internal => Execution/Resolvers}/InputResolverGeneratorTests.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Execution/Resolvers}/InputValueNodeTestData/CoffeeCan.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Execution/Resolvers}/InputValueNodeTestData/Telephone.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Execution/Resolvers}/ObjectMethodResolverTests.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Execution/Resolvers}/ObjectPropertyResolverTests.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Execution/Resolvers}/ValueResolversTestData/IResolverInterface.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Execution/Resolvers}/ValueResolversTestData/ResolvableEnum.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Execution/Resolvers}/ValueResolversTestData/ResolverObject.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Execution/Resolvers}/ValueResolversTestData/ResolverStructA.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Execution/Resolvers}/ValueResolversTestData/ResolverStructB.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ActionMethodTemplateTests.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ActionTestData/ActionMethodWithDirectiveController.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ActionTestData/ActionResultReturnTypeController.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ActionTestData/ArrayInputMethodController.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ActionTestData/ComplexityValueCheckController.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ActionTestData/ContainerController.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ActionTestData/CustomNamedItem.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ActionTestData/ITestItem.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ActionTestData/IUnionTestDataItem.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ActionTestData/InterfaceReturnTypeController.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ActionTestData/OneMethodController.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ActionTestData/ScalarInUnionController.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ActionTestData/TestItemA.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ActionTestData/TestItemB.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ActionTestData/UnionDataA.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ActionTestData/UnionDataB.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ActionTestData/UnionTestController.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ActionTestData/UnionTestProxy.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/AppliedDirectiveTemplateTests.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ArgumentTemplateTests.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ControllerTemplateTests.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ControllerTestData/ArrayInputParamController.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ControllerTestData/ArrayReturnController.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ControllerTestData/ControllerWithDirective.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ControllerTestData/ControllerWithStaticMethod.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ControllerTestData/DeclaredGraphRootController.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ControllerTestData/InvalidRouteController.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ControllerTestData/NoInheritanceFromBaseController.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ControllerTestData/NoRouteSpecifierController.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ControllerTestData/OneMethodController.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ControllerTestData/SimpleControllerNoMethods.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ControllerTestData/TwoMethodClashController.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ControllerTestData/TwoMethodNoClashController.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ControllerTestData/TwoMethodsDifferentRootsController.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/DirectiveMethodTemplateTests.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/DirectiveTemplateTests.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/DirectiveTestData/DirectiveWithArgs.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/DirectiveTestData/DirectiveWithDeclaredDirectiveOnMethod.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/DirectiveTestData/DirectiveWithDeclaredDirectives.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/DirectiveTestData/DirectiveWithRequirements.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/DirectiveTestData/DirectiveWithSecurityRequirements.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/DirectiveTestData/MismatchedSignaturesDirective.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/DirectiveTestData/NoLocationAttributeDirective.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/DirectiveTestData/NoLocationsDirective.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/DirectiveTestData/OverlappingLocationsDirective.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/DirectiveTestData/RepeatableDirective.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/DirectiveTestData/SimpleExecutableDirective.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/DirectiveTestData/TestDirectiveMethodTemplateContainer.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/DirectiveTestData/TestDirectiveMethodTemplateContainer2.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/EnumGraphTypeTemplateTests.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/EnumTestData/DeprecatedValueEnum.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/EnumTestData/EnumCompleteByte.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/EnumTestData/EnumCompleteSByte.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/EnumTestData/EnumFromByte.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/EnumTestData/EnumFromInt.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/EnumTestData/EnumFromLong.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/EnumTestData/EnumFromSByte.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/EnumTestData/EnumFromShort.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/EnumTestData/EnumFromUInt.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/EnumTestData/EnumFromULong.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/EnumTestData/EnumFromUShort.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/EnumTestData/EnumWithDescription.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/EnumTestData/EnumWithDescriptions.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/EnumTestData/EnumWithDirective.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/EnumTestData/EnumWithDirectiveOnOption.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/EnumTestData/EnumWithDuplicateValues.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/EnumTestData/EnumWithDuplicateValuesFromComposite.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/EnumTestData/EnumWithGraphName.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/EnumTestData/EnumWithInvalidValueName.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/EnumTestData/EnumWithValueWithGraphName.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/EnumTestData/EnumWithValueWithGraphNameButGraphNameIsInvalid.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/EnumTestData/SimpleEnum.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ExtensionMethodTestData/ExtensionMethodController.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/GraphTypeNameTestData/AttributedClass.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/GraphTypeNameTestData/AttributedClassInvalidName.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/GraphTypeNameTestData/EnumNameTest.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/GraphTypeNameTestData/EnumNameTestWithTypeName.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/GraphTypeNameTestData/GenericClass.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/GraphTypeNameTestData/GenericClassWithAttribute.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/GraphTypeNameTestData/NoAttributeClass.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/GraphTypeNameTestData/NoAttributeClassForNewName.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/GraphTypeNamesTests.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/InputGraphFieldTemplateTests.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/InputObjectTemplateTests.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/InterfaceGraphTypeTemplateTests.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/InterfaceTestData/IInterface1.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/InterfaceTestData/IInterface2.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/InterfaceTestData/IInterface3.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/InterfaceTestData/IInterfaceWithDirective.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/InterfaceTestData/INestedInterface1.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/InterfaceTestData/INestedInterface2.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/InterfaceTestData/ISimpleInterface.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/InterfaceTestData/ITestableInterfaceImplementation.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/InterfaceTestData/InterfaceThatInheritsDeclaredMethodField.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/InterfaceTestData/InterfaceThatInheritsUndeclaredMethodField.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/InterfaceTestData/InterfaceWithDeclaredInterfaceField.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/InterfaceTestData/InterfaceWithUndeclaredInterfaceField.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/MethodGraphFieldTemplateTests.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/MethodTestData/ArrayMethodObject.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/MethodTestData/MethodClass.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/MethodTestData/MethodClassWithDirective.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ObjectGraphTypeTemplateTests.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ObjectTypeTests/CustomStruct.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ObjectTypeTests/DescriptionObject.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ObjectTypeTests/DescriptionStruct.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ObjectTypeTests/ForceSkippedStruct.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ObjectTypeTests/ForcedSkippedObject.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ObjectTypeTests/IInputObject.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ObjectTypeTests/InputNameObject.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ObjectTypeTests/InputObjectIWithTaskProperty.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ObjectTypeTests/InputObjectWithDirective.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ObjectTypeTests/InputObjectWithDuplicateProperty.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ObjectTypeTests/InputObjectWithGraphActionProperty.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ObjectTypeTests/InputObjectWithInterfaceProperty.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ObjectTypeTests/InputObjectWithUnionProxyProperty.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ObjectTypeTests/ObjectThatInheritsExplicitMethodField.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ObjectTypeTests/ObjectThatInheritsNonExplicitMethodField.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ObjectTypeTests/ObjectWithDeconstructor.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ObjectTypeTests/ObjectWithDirective.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ObjectTypeTests/ObjectWithExplicitMethodField.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ObjectTypeTests/ObjectWithInvalidNonDeclaredMethods.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ObjectTypeTests/ObjectWithMutationOperation.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ObjectTypeTests/ObjectWithNoSetters.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ObjectTypeTests/ObjectWithNonExplicitMethodField.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ObjectTypeTests/ObjectWithStatics.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ObjectTypeTests/OneMarkedMethod.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ObjectTypeTests/OneMarkedProperty.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ObjectTypeTests/RequiredConstructor.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ObjectTypeTests/SimpleObjectNoMethods.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ObjectTypeTests/SimpleObjectScalar.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ObjectTypeTests/SimpleScalarObjectGraphType.cs (91%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ObjectTypeTests/SimpleScalarStruct.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ObjectTypeTests/SimpleScalarStructGraphType.cs (91%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ObjectTypeTests/SimpleStructNoMethods.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ObjectTypeTests/StructOneMarkedMethod.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ObjectTypeTests/StructOneMarkedProperty.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ObjectTypeTests/StructTwoMethodsWithSameName.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ObjectTypeTests/StructTwoMethodsWithSameNameWithAttributeDiff.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ObjectTypeTests/StructWithInvalidNonDeclaredMethods.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ObjectTypeTests/StructWithNoSetters.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ObjectTypeTests/TwoMethodsWithSameName.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ObjectTypeTests/TwoMethodsWithSameNameWithAttributeDiff.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ObjectTypeTests/TypeWithArrayProperty.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/ParameterTestData/ParameterTestClass.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/PropertyGraphFieldTemplateTests.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/PropertyTestData/ArrayKeyValuePairObject.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/PropertyTestData/ArrayPropertyObject.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/PropertyTestData/IPropInterface.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/PropertyTestData/NoGetterOnProperty.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/PropertyTestData/PropAuthorizeAttribute.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/PropertyTestData/PropertyClassWithDirective.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/PropertyTestData/PropertyProxy.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/PropertyTestData/SimplePropertyObject.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas/Generation/TypeTemplates}/Templating/TypeExtensionFieldTemplateTests.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas}/GraphValidationTestData/ControllerWithNoSecurityPolicies.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas}/GraphValidationTestData/ControllerWithSecurityPolicies.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas}/GraphValidationTests.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas}/IntrospectionDefaultValueTestData/TestEnum.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas}/IntrospectionDefaultValueTestData/TestEnumNoDefaultValue.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas}/IntrospectionDefaultValueTestData/TestEnumNotIncludedDefault.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal => Schemas}/IntrospectionDefaultValueValidationTests.cs (100%) diff --git a/src/graphql-aspnet/Common/TypeCollection.cs b/src/graphql-aspnet/Common/TypeCollection.cs deleted file mode 100644 index e2cf34b5d..000000000 --- a/src/graphql-aspnet/Common/TypeCollection.cs +++ /dev/null @@ -1,96 +0,0 @@ -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - -namespace GraphQL.AspNet.Common -{ - using System; - using System.Collections; - using System.Collections.Generic; - using System.Collections.Immutable; - - /// - /// A collection of unique types. This collection is guaranteed to contain unique items - /// and is read-only once created. - /// - public class TypeCollection : IEnumerable - { - /// - /// Gets a collection representing no additional types. - /// - /// The none. - public static TypeCollection Empty { get; } - - /// - /// Initializes static members of the class. - /// - static TypeCollection() - { - Empty = new TypeCollection(); - } - - /// - /// Prevents a default instance of the class from being created. - /// - private TypeCollection() - { - this.TypeSet = ImmutableHashSet.Create(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The types. - public TypeCollection(params Type[] types) - : this() - { - if (types != null) - this.TypeSet = ImmutableHashSet.Create(types); - } - - /// - /// Determines whether this instance contains the specified type. - /// - /// The type. - /// true if the type is found; otherwise, false. - public bool Contains(Type type) - { - return this.TypeSet.Contains(type); - } - - /// - /// Gets the count of types in this set. - /// - /// The count of types. - public int Count => this.TypeSet.Count; - - /// - /// Gets the set of s that represent the scalar. - /// - /// The type set. - public IImmutableSet TypeSet { get; } - - /// - /// Returns an enumerator that iterates through the collection. - /// - /// An enumerator that can be used to iterate through the collection. - public IEnumerator GetEnumerator() - { - return this.TypeSet.GetEnumerator(); - } - - /// - /// Returns an enumerator that iterates through a collection. - /// - /// An object that can be used to iterate through the collection. - IEnumerator IEnumerable.GetEnumerator() - { - return this.GetEnumerator(); - } - } -} \ No newline at end of file diff --git a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Introspection.cs b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Introspection.cs index 1742fd1a7..bbab53314 100644 --- a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Introspection.cs +++ b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Introspection.cs @@ -22,7 +22,6 @@ namespace GraphQL.AspNet.Engine /// public partial class DefaultGraphQLSchemaFactory { - /// /// Clears, builds and caches the introspection metadata used to describe this schema. If introspection /// fields have not been added to the schema this method does nothing. No changes to the schema diff --git a/src/graphql-aspnet/Engine/DefaultGraphQLTypeMakerFactory.cs b/src/graphql-aspnet/Engine/DefaultGraphQLTypeMakerFactory.cs index ea0346f2f..0a4172d90 100644 --- a/src/graphql-aspnet/Engine/DefaultGraphQLTypeMakerFactory.cs +++ b/src/graphql-aspnet/Engine/DefaultGraphQLTypeMakerFactory.cs @@ -10,15 +10,14 @@ namespace GraphQL.AspNet.Schemas.Generation { using System; - using System.Data; using GraphQL.AspNet.Common; using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Directives; using GraphQL.AspNet.Interfaces.Engine; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal.TypeTemplates; using GraphQL.AspNet.Schemas.Generation.TypeMakers; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Schemas.TypeSystem.Scalars; @@ -30,44 +29,10 @@ namespace GraphQL.AspNet.Schemas.Generation public class DefaultGraphQLTypeMakerFactory : IGraphQLTypeMakerFactory where TSchema : class, ISchema { - /// - /// Initializes a new instance of the class. - /// - public DefaultGraphQLTypeMakerFactory() - { - } - /// public virtual IGraphTypeTemplate MakeTemplate(Type objectType, TypeKind? kind = null) { - if (objectType == null) - return null; - - // attempt to turn "int" into "IntScalarType" when necessary - objectType = GlobalTypes.FindBuiltInScalarType(objectType) ?? objectType; - - IGraphTypeTemplate template; - if (Validation.IsCastable(objectType)) - template = new ScalarGraphTypeTemplate(objectType); - else if (Validation.IsCastable(objectType)) - template = new UnionGraphTypeTemplate(objectType); - else if (objectType.IsEnum) - template = new EnumGraphTypeTemplate(objectType); - else if (objectType.IsInterface) - template = new InterfaceGraphTypeTemplate(objectType); - else if (Validation.IsCastable(objectType)) - template = new GraphDirectiveTemplate(objectType); - else if (Validation.IsCastable(objectType)) - template = new GraphControllerTemplate(objectType); - else if (kind.HasValue && kind.Value == TypeKind.INPUT_OBJECT) - template = new InputObjectGraphTypeTemplate(objectType); - else - template = new ObjectGraphTypeTemplate(objectType); - - template.Parse(); - template.ValidateOrThrow(); - - return template; + return GraphTypeTemplates.CreateTemplate(objectType, kind); } /// diff --git a/src/graphql-aspnet/Execution/DirectiveProcessorTypeSystem.cs b/src/graphql-aspnet/Execution/DirectiveProcessorTypeSystem.cs index e6248e054..0bdded28d 100644 --- a/src/graphql-aspnet/Execution/DirectiveProcessorTypeSystem.cs +++ b/src/graphql-aspnet/Execution/DirectiveProcessorTypeSystem.cs @@ -61,7 +61,7 @@ public DirectiveProcessorTypeSystem(IServiceProvider serviceProvider, IQuerySess /// The schema to apply directives too. public void ApplyDirectives(TSchema schema) { - Validation.ThrowIfNull(schema, nameof(schema)); + Validation.ThrowIfNull(schema, nameof(schema)); // all schema items var anyDirectivesApplied = false; diff --git a/src/graphql-aspnet/Interfaces/Configuration/IGraphQLServerExtension.cs b/src/graphql-aspnet/Interfaces/Configuration/IGraphQLServerExtension.cs index c79e69601..2fd69ce5f 100644 --- a/src/graphql-aspnet/Interfaces/Configuration/IGraphQLServerExtension.cs +++ b/src/graphql-aspnet/Interfaces/Configuration/IGraphQLServerExtension.cs @@ -67,9 +67,7 @@ public void UseExtension(IApplicationBuilder app) /// When this method is called, construction of the DI container is complete. The schema has not been /// generated yet. /// - /// The configured service provider completed during setup. In - /// most instances, this will be the instances - /// from . + /// The configured service provider created during setup. public void UseExtension(IServiceProvider serviceProvider) { this.UseExtension(null, serviceProvider); @@ -86,7 +84,7 @@ public void UseExtension(IServiceProvider serviceProvider) /// /// The application builder to register against. May be null in some rare instances /// where the middleware pipeline is not being setup. Usually during some unit testing edge cases. - /// The configured service provider completed during setup. In + /// The configured service provider created during setup. In /// most instances, this will be the instances /// from . public void UseExtension(IApplicationBuilder app = null, IServiceProvider serviceProvider = null) diff --git a/src/graphql-aspnet/Interfaces/Schema/IScalarGraphType.cs b/src/graphql-aspnet/Interfaces/Schema/IScalarGraphType.cs index 6561b235d..6b984d864 100644 --- a/src/graphql-aspnet/Interfaces/Schema/IScalarGraphType.cs +++ b/src/graphql-aspnet/Interfaces/Schema/IScalarGraphType.cs @@ -19,15 +19,6 @@ namespace GraphQL.AspNet.Interfaces.Schema /// public interface IScalarGraphType : IGraphType, ITypedSchemaItem { - /// - /// Gets a collection of other types that this scalar may be declared as. Scalars maybe - /// represented in C# in multiple formats (e.g. int and int?) but these - /// formats are still the same datatype from the perspective of graphql. This field captures the other known - /// types of this scalar so they can be grouped and processed in a similar manner. - /// - /// The other known types. - TypeCollection OtherKnownTypes { get; } - /// /// Gets the type of the value as it should be supplied on an input argument. Scalar values, from a standpoint of "raw data" can be submitted as /// strings, numbers or a boolean value. A source value resolver would then convert this raw value into its formal scalar representation. diff --git a/src/graphql-aspnet/Schemas/Generation/TypeMakers/DirectiveMaker.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/DirectiveMaker.cs index f32fc85d7..95dabfdcd 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeMakers/DirectiveMaker.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/DirectiveMaker.cs @@ -38,7 +38,6 @@ public DirectiveMaker(ISchemaConfiguration config, IGraphArgumentMaker argumentM { _config = Validation.ThrowIfNullOrReturn(config, nameof(config)); _argMaker = Validation.ThrowIfNullOrReturn(argumentMaker, nameof(argumentMaker)); - } /// diff --git a/src/graphql-aspnet/Schemas/Generation/TypeMakers/ScalarGraphTypeMaker.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/ScalarGraphTypeMaker.cs index 2e7631df9..217b8eb05 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeMakers/ScalarGraphTypeMaker.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/ScalarGraphTypeMaker.cs @@ -42,7 +42,6 @@ public GraphTypeCreationResult CreateGraphType(IGraphTypeTemplate typeTemplate) if (!(typeTemplate is IScalarGraphTypeTemplate scalarTemplate)) return null; - var scalarType = GlobalTypes.CreateScalarInstanceOrThrow(scalarTemplate.ScalarType); scalarType = scalarType.Clone(_config.DeclarationOptions.GraphNamingFormatter.FormatGraphTypeName(scalarType.Name)); diff --git a/src/graphql-aspnet/Internal/TypeTemplates/AppliedDirectiveTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/AppliedDirectiveTemplate.cs similarity index 100% rename from src/graphql-aspnet/Internal/TypeTemplates/AppliedDirectiveTemplate.cs rename to src/graphql-aspnet/Schemas/Generation/TypeTemplates/AppliedDirectiveTemplate.cs diff --git a/src/graphql-aspnet/Internal/TypeTemplates/ApplyDirectiveAttributeExtensions.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/ApplyDirectiveAttributeExtensions.cs similarity index 100% rename from src/graphql-aspnet/Internal/TypeTemplates/ApplyDirectiveAttributeExtensions.cs rename to src/graphql-aspnet/Schemas/Generation/TypeTemplates/ApplyDirectiveAttributeExtensions.cs diff --git a/src/graphql-aspnet/Internal/TypeTemplates/ControllerActionGraphFieldTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/ControllerActionGraphFieldTemplate.cs similarity index 100% rename from src/graphql-aspnet/Internal/TypeTemplates/ControllerActionGraphFieldTemplate.cs rename to src/graphql-aspnet/Schemas/Generation/TypeTemplates/ControllerActionGraphFieldTemplate.cs diff --git a/src/graphql-aspnet/Internal/TypeTemplates/DependentType.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/DependentType.cs similarity index 100% rename from src/graphql-aspnet/Internal/TypeTemplates/DependentType.cs rename to src/graphql-aspnet/Schemas/Generation/TypeTemplates/DependentType.cs diff --git a/src/graphql-aspnet/Internal/TypeTemplates/EnumGraphTypeTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/EnumGraphTypeTemplate.cs similarity index 100% rename from src/graphql-aspnet/Internal/TypeTemplates/EnumGraphTypeTemplate.cs rename to src/graphql-aspnet/Schemas/Generation/TypeTemplates/EnumGraphTypeTemplate.cs diff --git a/src/graphql-aspnet/Internal/TypeTemplates/EnumValueTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/EnumValueTemplate.cs similarity index 100% rename from src/graphql-aspnet/Internal/TypeTemplates/EnumValueTemplate.cs rename to src/graphql-aspnet/Schemas/Generation/TypeTemplates/EnumValueTemplate.cs diff --git a/src/graphql-aspnet/Internal/TypeTemplates/GraphArgumentTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphArgumentTemplate.cs similarity index 100% rename from src/graphql-aspnet/Internal/TypeTemplates/GraphArgumentTemplate.cs rename to src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphArgumentTemplate.cs diff --git a/src/graphql-aspnet/Internal/TypeTemplates/GraphControllerTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphControllerTemplate.cs similarity index 100% rename from src/graphql-aspnet/Internal/TypeTemplates/GraphControllerTemplate.cs rename to src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphControllerTemplate.cs diff --git a/src/graphql-aspnet/Internal/TypeTemplates/GraphDirectiveMethodTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveMethodTemplate.cs similarity index 100% rename from src/graphql-aspnet/Internal/TypeTemplates/GraphDirectiveMethodTemplate.cs rename to src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveMethodTemplate.cs diff --git a/src/graphql-aspnet/Internal/TypeTemplates/GraphDirectiveMethodTemplateContainer.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveMethodTemplateContainer.cs similarity index 100% rename from src/graphql-aspnet/Internal/TypeTemplates/GraphDirectiveMethodTemplateContainer.cs rename to src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveMethodTemplateContainer.cs diff --git a/src/graphql-aspnet/Internal/TypeTemplates/GraphDirectiveTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveTemplate.cs similarity index 100% rename from src/graphql-aspnet/Internal/TypeTemplates/GraphDirectiveTemplate.cs rename to src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveTemplate.cs diff --git a/src/graphql-aspnet/Internal/TypeTemplates/GraphFieldTemplateBase.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphFieldTemplateBase.cs similarity index 100% rename from src/graphql-aspnet/Internal/TypeTemplates/GraphFieldTemplateBase.cs rename to src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphFieldTemplateBase.cs diff --git a/src/graphql-aspnet/Internal/TypeTemplates/GraphFieldTemplateSource.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphFieldTemplateSource.cs similarity index 100% rename from src/graphql-aspnet/Internal/TypeTemplates/GraphFieldTemplateSource.cs rename to src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphFieldTemplateSource.cs diff --git a/src/graphql-aspnet/Internal/TypeTemplates/GraphTypeExtensionFieldTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphTypeExtensionFieldTemplate.cs similarity index 100% rename from src/graphql-aspnet/Internal/TypeTemplates/GraphTypeExtensionFieldTemplate.cs rename to src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphTypeExtensionFieldTemplate.cs diff --git a/src/graphql-aspnet/Internal/TypeTemplates/GraphTypeTemplateBase.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphTypeTemplateBase.cs similarity index 100% rename from src/graphql-aspnet/Internal/TypeTemplates/GraphTypeTemplateBase.cs rename to src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphTypeTemplateBase.cs diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphTypeTemplates.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphTypeTemplates.cs new file mode 100644 index 000000000..f401f2dd0 --- /dev/null +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphTypeTemplates.cs @@ -0,0 +1,73 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates +{ + using System; + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Controllers; + using GraphQL.AspNet.Directives; + using GraphQL.AspNet.Interfaces.Internal; + using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Schemas.TypeSystem.Scalars; + + /// + /// A helper class for creating graph type templates from info classes. + /// + public static class GraphTypeTemplates + { + /// + /// A default implementation that will create an appropriate + /// for the given and . + /// + /// The type info representing the object. + /// The kind of template to make. Only used to differentiate INPUT_OBJECT from + /// OBJECT. Ignored otherwise. + /// if set to true the template will be parsed and validated. + /// When false, the template will just be instantiated and returned, unparsed. Many data fields will not be + /// populated. + /// IGraphTypeTemplate. + public static IGraphTypeTemplate CreateTemplate(Type objectType, TypeKind? kind = null, bool parseTemplate = true) + { + if (objectType == null) + return null; + + // attempt to turn "int" into "IntScalarType" when necessary + objectType = GlobalTypes.FindBuiltInScalarType(objectType) ?? objectType; + + IGraphTypeTemplate template; + if (Validation.IsCastable(objectType)) + template = new ScalarGraphTypeTemplate(objectType); + else if (Validation.IsCastable(objectType)) + template = new UnionGraphTypeTemplate(objectType); + else if (objectType.IsEnum) + template = new EnumGraphTypeTemplate(objectType); + else if (objectType.IsInterface) + template = new InterfaceGraphTypeTemplate(objectType); + else if (Validation.IsCastable(objectType)) + template = new GraphDirectiveTemplate(objectType); + else if (Validation.IsCastable(objectType)) + template = new GraphControllerTemplate(objectType); + else if (kind.HasValue && kind.Value == TypeKind.INPUT_OBJECT) + template = new InputObjectGraphTypeTemplate(objectType); + else + template = new ObjectGraphTypeTemplate(objectType); + + if (parseTemplate) + { + template.Parse(); + template.ValidateOrThrow(); + } + + return template; + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Internal/TypeTemplates/InputGraphFieldTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/InputGraphFieldTemplate.cs similarity index 100% rename from src/graphql-aspnet/Internal/TypeTemplates/InputGraphFieldTemplate.cs rename to src/graphql-aspnet/Schemas/Generation/TypeTemplates/InputGraphFieldTemplate.cs diff --git a/src/graphql-aspnet/Internal/TypeTemplates/InputObjectGraphTypeTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/InputObjectGraphTypeTemplate.cs similarity index 100% rename from src/graphql-aspnet/Internal/TypeTemplates/InputObjectGraphTypeTemplate.cs rename to src/graphql-aspnet/Schemas/Generation/TypeTemplates/InputObjectGraphTypeTemplate.cs diff --git a/src/graphql-aspnet/Internal/TypeTemplates/InterfaceGraphTypeTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/InterfaceGraphTypeTemplate.cs similarity index 100% rename from src/graphql-aspnet/Internal/TypeTemplates/InterfaceGraphTypeTemplate.cs rename to src/graphql-aspnet/Schemas/Generation/TypeTemplates/InterfaceGraphTypeTemplate.cs diff --git a/src/graphql-aspnet/Internal/TypeTemplates/MemberInfoProvider.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/MemberInfoProvider.cs similarity index 100% rename from src/graphql-aspnet/Internal/TypeTemplates/MemberInfoProvider.cs rename to src/graphql-aspnet/Schemas/Generation/TypeTemplates/MemberInfoProvider.cs diff --git a/src/graphql-aspnet/Internal/TypeTemplates/MethodGraphFieldTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplate.cs similarity index 100% rename from src/graphql-aspnet/Internal/TypeTemplates/MethodGraphFieldTemplate.cs rename to src/graphql-aspnet/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplate.cs diff --git a/src/graphql-aspnet/Internal/TypeTemplates/MethodGraphFieldTemplateBase.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplateBase.cs similarity index 100% rename from src/graphql-aspnet/Internal/TypeTemplates/MethodGraphFieldTemplateBase.cs rename to src/graphql-aspnet/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplateBase.cs diff --git a/src/graphql-aspnet/Internal/TypeTemplates/NonLeafGraphTypeTemplateBase.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/NonLeafGraphTypeTemplateBase.cs similarity index 100% rename from src/graphql-aspnet/Internal/TypeTemplates/NonLeafGraphTypeTemplateBase.cs rename to src/graphql-aspnet/Schemas/Generation/TypeTemplates/NonLeafGraphTypeTemplateBase.cs diff --git a/src/graphql-aspnet/Internal/TypeTemplates/ObjectGraphTypeTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/ObjectGraphTypeTemplate.cs similarity index 100% rename from src/graphql-aspnet/Internal/TypeTemplates/ObjectGraphTypeTemplate.cs rename to src/graphql-aspnet/Schemas/Generation/TypeTemplates/ObjectGraphTypeTemplate.cs diff --git a/src/graphql-aspnet/Internal/TypeTemplates/PropertyGraphFieldTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/PropertyGraphFieldTemplate.cs similarity index 100% rename from src/graphql-aspnet/Internal/TypeTemplates/PropertyGraphFieldTemplate.cs rename to src/graphql-aspnet/Schemas/Generation/TypeTemplates/PropertyGraphFieldTemplate.cs diff --git a/src/graphql-aspnet/Internal/TypeTemplates/RuntimeGraphControllerTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/RuntimeGraphControllerTemplate.cs similarity index 100% rename from src/graphql-aspnet/Internal/TypeTemplates/RuntimeGraphControllerTemplate.cs rename to src/graphql-aspnet/Schemas/Generation/TypeTemplates/RuntimeGraphControllerTemplate.cs diff --git a/src/graphql-aspnet/Internal/TypeTemplates/RuntimeSchemaItemAttributeProvider.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/RuntimeSchemaItemAttributeProvider.cs similarity index 100% rename from src/graphql-aspnet/Internal/TypeTemplates/RuntimeSchemaItemAttributeProvider.cs rename to src/graphql-aspnet/Schemas/Generation/TypeTemplates/RuntimeSchemaItemAttributeProvider.cs diff --git a/src/graphql-aspnet/Internal/TypeTemplates/ScalarGraphTypeTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/ScalarGraphTypeTemplate.cs similarity index 100% rename from src/graphql-aspnet/Internal/TypeTemplates/ScalarGraphTypeTemplate.cs rename to src/graphql-aspnet/Schemas/Generation/TypeTemplates/ScalarGraphTypeTemplate.cs diff --git a/src/graphql-aspnet/Internal/TypeTemplates/SchemaItemTemplateBase.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/SchemaItemTemplateBase.cs similarity index 100% rename from src/graphql-aspnet/Internal/TypeTemplates/SchemaItemTemplateBase.cs rename to src/graphql-aspnet/Schemas/Generation/TypeTemplates/SchemaItemTemplateBase.cs diff --git a/src/graphql-aspnet/Internal/TypeTemplates/UnionGraphTypeTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/UnionGraphTypeTemplate.cs similarity index 100% rename from src/graphql-aspnet/Internal/TypeTemplates/UnionGraphTypeTemplate.cs rename to src/graphql-aspnet/Schemas/Generation/TypeTemplates/UnionGraphTypeTemplate.cs diff --git a/src/graphql-aspnet/Schemas/TypeSystem/GlobalTypes.cs b/src/graphql-aspnet/Schemas/TypeSystem/GlobalTypes.cs index 68d848d0f..d6b704536 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/GlobalTypes.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/GlobalTypes.cs @@ -44,24 +44,18 @@ static GlobalTypes() // other helpful scalars added to the library for // convience with .NET ValidateAndRegisterBuiltInScalar(); - ValidateAndRegisterBuiltInScalar(); ValidateAndRegisterBuiltInScalar(); - ValidateAndRegisterBuiltInScalar(); ValidateAndRegisterBuiltInScalar(); - - ValidateAndRegisterBuiltInScalar(); - ValidateAndRegisterBuiltInScalar(); ValidateAndRegisterBuiltInScalar(); + ValidateAndRegisterBuiltInScalar(); + ValidateAndRegisterBuiltInScalar(); ValidateAndRegisterBuiltInScalar(); - ValidateAndRegisterBuiltInScalar(); ValidateAndRegisterBuiltInScalar(); - ValidateAndRegisterBuiltInScalar(); ValidateAndRegisterBuiltInScalar(); - ValidateAndRegisterBuiltInScalar(); ValidateAndRegisterBuiltInScalar(); } @@ -155,7 +149,7 @@ internal static bool IsBuiltInScalar(string scalarName) /// /// /// The five specification-defined scalars (Int, Float, String, Boolean, ID) cannot be renamed and are used - /// as part of the introspection system. All other internal scalars can be renamed to match any casing rules + /// as part of the introspection system. All other internal scalars can be renamed or "re-cased" to match any rules /// for a target schema. /// /// Name of the scalar. @@ -184,11 +178,37 @@ public static bool CanBeRenamed(string scalarName) /// /// The type representing an . public static void ValidateScalarTypeOrThrow(Type scalarType) + { + CreateAndValidateScalarType(scalarType, true); + } + + /// + /// Validates that the supplied scalar instance is valid and could be used by a schema + /// instance. + /// + /// The graph type instance to check. + public static void ValidateScalarTypeOrThrow(IScalarGraphType graphType) + { + ValidateScalarType(graphType, true); + } + + /// + /// Validates that the supplied type can be used to build a scalar instance + /// that is usable by a schema. + /// + /// The type representing an . + /// if set to true this method will throw a + /// if the sclar is not valid. + /// System.ValueTuple<System.Boolean, IScalarGraphType>. + private static (bool IsValid, IScalarGraphType Instance) CreateAndValidateScalarType(Type scalarType, bool shouldThrow = true) { Validation.ThrowIfNull(scalarType, nameof(scalarType)); if (!Validation.IsCastable(scalarType)) { + if (!shouldThrow) + return (false, null); + throw new GraphTypeDeclarationException( $"The scalar must implement the interface '{typeof(IScalarGraphType).FriendlyName()}'."); } @@ -196,12 +216,15 @@ public static void ValidateScalarTypeOrThrow(Type scalarType) var paramlessConstructor = scalarType.GetConstructor(new Type[0]); if (paramlessConstructor == null) { + if (!shouldThrow) + return (false, null); + throw new GraphTypeDeclarationException( "The scalar must declare a public, parameterless constructor."); } var graphType = InstanceFactory.CreateInstance(scalarType) as IScalarGraphType; - ValidateScalarTypeOrThrow(graphType); + return ValidateScalarType(graphType, shouldThrow); } /// @@ -209,34 +232,46 @@ public static void ValidateScalarTypeOrThrow(Type scalarType) /// instance. /// /// The graph type instance to check. - public static void ValidateScalarTypeOrThrow(IScalarGraphType graphType) + /// if set to true this method will throw a + /// if the sclar is not valid. + private static (bool IsValid, IScalarGraphType Instance) ValidateScalarType(IScalarGraphType graphType, bool shouldThrow) { if (string.IsNullOrWhiteSpace(graphType.Name)) { + if (!shouldThrow) + return (false, null); throw new GraphTypeDeclarationException( "The scalar must supply a name that is not null or whitespace."); } if (!GraphValidation.IsValidGraphName(graphType.Name)) { + if (!shouldThrow) + return (false, null); throw new GraphTypeDeclarationException( $"The scalar must supply a name that that conforms to the standard rules for GraphQL. (Regex: {Constants.RegExPatterns.NameRegex})"); } if (graphType.Kind != TypeKind.SCALAR) { + if (!shouldThrow) + return (false, null); throw new GraphTypeDeclarationException( $"The '{graphType.Name}' scalar's type kind must be set to '{nameof(TypeKind.SCALAR)}'."); } if (graphType.ObjectType == null) { + if (!shouldThrow) + return (false, null); throw new GraphTypeDeclarationException( $"The scalar '{graphType.Name}' must supply a value for '{nameof(graphType.ObjectType)}', is cannot be null."); } if (Validation.IsNullableOfT(graphType.ObjectType)) { + if (!shouldThrow) + return (false, null); throw new GraphTypeDeclarationException( $"The scalar '{graphType.Name}' must supply the root,non-nullable type derivation for '{nameof(graphType.ObjectType)}' (e.g. 'int' not 'int?'). " + $" The current value of {nameof(IScalarGraphType.ObjectType)} is a nullable type derivation."); @@ -244,6 +279,8 @@ public static void ValidateScalarTypeOrThrow(IScalarGraphType graphType) if (graphType.SourceResolver == null) { + if (!shouldThrow) + return (false, null); throw new GraphTypeDeclarationException( $"The scalar must supply a value for '{nameof(graphType.SourceResolver)}' that can convert data from a " + $"query into the primary object type of '{graphType.ObjectType.FriendlyName()}'."); @@ -251,24 +288,33 @@ public static void ValidateScalarTypeOrThrow(IScalarGraphType graphType) if (graphType.ValueType == ScalarValueType.Unknown) { + if (!shouldThrow) + return (false, null); throw new GraphTypeDeclarationException( $"The scalar must supply a value for '{nameof(graphType.ValueType)}'. This lets the validation engine " + "know what data types submitted on a user query could be parsed into a value for this scale."); } - if (graphType.OtherKnownTypes == null) - { - throw new GraphTypeDeclarationException( - $"Custom scalars must supply a value for '{nameof(graphType.OtherKnownTypes)}', it cannot be null. " + - $"Use '{nameof(TypeCollection)}.{nameof(TypeCollection.Empty)}' if there are no other known types."); - } - if (graphType.AppliedDirectives == null || graphType.AppliedDirectives.Parent != graphType) { + if (!shouldThrow) + return (false, null); throw new GraphTypeDeclarationException( $"Custom scalars must supply a value for '{nameof(graphType.AppliedDirectives)}', it cannot be null. " + $"The '{nameof(IAppliedDirectiveCollection.Parent)}' property of the directive collection must also be set to the scalar itself."); } + + return (true, graphType); + } + + /// + /// Determines whether the provided type represents an object that is a properly constructed scalar graph type. + /// + /// The type to check. + /// true if the type represents a valid scalar; otherwise, false. + public static bool IsValidScalarType(Type typeToCheck) + { + return CreateAndValidateScalarType(typeToCheck, false).IsValid; } /// @@ -282,8 +328,8 @@ public static IScalarGraphType CreateScalarInstanceOrThrow(Type scalarType) scalarType = GraphValidation.EliminateNextWrapperFromCoreType(scalarType); scalarType = FindBuiltInScalarType(scalarType) ?? scalarType; - ValidateScalarTypeOrThrow(scalarType); - return InstanceFactory.CreateInstance(scalarType) as IScalarGraphType; + var (isValid, instance) = CreateAndValidateScalarType(scalarType, true); + return isValid ? instance : null; } /// @@ -297,16 +343,8 @@ public static IScalarGraphType CreateScalarInstance(Type scalarType) scalarType = GraphValidation.EliminateNextWrapperFromCoreType(scalarType); scalarType = FindBuiltInScalarType(scalarType) ?? scalarType; - try - { - ValidateScalarTypeOrThrow(scalarType); - } - catch - { - return null; - } - - return InstanceFactory.CreateInstance(scalarType) as IScalarGraphType; + var (isValid, instance) = CreateAndValidateScalarType(scalarType, false); + return isValid ? instance : null; } /// diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/BooleanScalarType.cs b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/BooleanScalarType.cs index 73cd3db72..54f8e0c3f 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/BooleanScalarType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/BooleanScalarType.cs @@ -27,7 +27,6 @@ public BooleanScalarType() : base(Constants.ScalarNames.BOOLEAN, typeof(bool)) { this.Description = "A boolean value (Expressed as: true | false)"; - this.OtherKnownTypes = new TypeCollection(typeof(bool?)); } /// @@ -55,9 +54,6 @@ public override string SerializeToQueryLanguage(object item) return Constants.QueryLanguage.NULL; } - /// - public override TypeCollection OtherKnownTypes { get; } - /// public override ScalarValueType ValueType => ScalarValueType.Boolean; } diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/ByteScalarType.cs b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/ByteScalarType.cs index c4e271a28..625ad0ee7 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/ByteScalarType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/ByteScalarType.cs @@ -27,7 +27,6 @@ public ByteScalarType() : base(Constants.ScalarNames.BYTE, typeof(byte)) { this.Description = $"A unsigned byte. (Min: {byte.MinValue}, Max: {byte.MaxValue})"; - this.OtherKnownTypes = new TypeCollection(typeof(byte?)); } /// @@ -39,9 +38,6 @@ public override object Resolve(ReadOnlySpan data) throw new UnresolvedValueException(data, typeof(byte)); } - /// - public override TypeCollection OtherKnownTypes { get; } - /// public override ScalarValueType ValueType => ScalarValueType.Number; } diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/DateOnlyScalarType.cs b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/DateOnlyScalarType.cs index be828a665..546d4ca1b 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/DateOnlyScalarType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/DateOnlyScalarType.cs @@ -31,7 +31,6 @@ public DateOnlyScalarType() : base(Constants.ScalarNames.DATEONLY, typeof(DateOnly)) { this.Description = "A calendar date that does not include a time component."; - this.OtherKnownTypes = new TypeCollection(typeof(DateOnly?)); } /// @@ -60,9 +59,6 @@ public override string SerializeToQueryLanguage(object item) return Constants.QueryLanguage.NULL; } - /// - public override TypeCollection OtherKnownTypes { get; } - /// public override ScalarValueType ValueType => ScalarValueType.StringOrNumber; } diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/DateTimeOffsetScalarType.cs b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/DateTimeOffsetScalarType.cs index be1ae97a6..0a60c51f6 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/DateTimeOffsetScalarType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/DateTimeOffsetScalarType.cs @@ -28,7 +28,6 @@ public DateTimeOffsetScalarType() : base(Constants.ScalarNames.DATETIMEOFFSET, typeof(DateTimeOffset)) { this.Description = "A point in time relative to Coordinated Universal Time (UTC)."; - this.OtherKnownTypes = new TypeCollection(typeof(DateTimeOffset?)); } /// @@ -60,9 +59,6 @@ public override string SerializeToQueryLanguage(object item) return Constants.QueryLanguage.NULL; } - /// - public override TypeCollection OtherKnownTypes { get; } - /// public override ScalarValueType ValueType => ScalarValueType.StringOrNumber; diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/DateTimeScalarType.cs b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/DateTimeScalarType.cs index b9a9c3744..43d8d9ebd 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/DateTimeScalarType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/DateTimeScalarType.cs @@ -28,7 +28,6 @@ public DateTimeScalarType() : base(Constants.ScalarNames.DATETIME, typeof(DateTime)) { this.Description = "A calendar date that does include a time component."; - this.OtherKnownTypes = new TypeCollection(typeof(DateTime?)); } /// @@ -60,9 +59,6 @@ public override string SerializeToQueryLanguage(object item) return Constants.QueryLanguage.NULL; } - /// - public override TypeCollection OtherKnownTypes { get; } - /// public override ScalarValueType ValueType => ScalarValueType.StringOrNumber; diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/DecimalScalarType.cs b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/DecimalScalarType.cs index ad863c064..c588b36c9 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/DecimalScalarType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/DecimalScalarType.cs @@ -30,7 +30,6 @@ public DecimalScalarType() this.Description = "A 128-bit, floating point value that offers greater local " + "precision, with a smaller range, than other floating-point types. " + $"(Min: {decimal.MinValue}, Max: {decimal.MaxValue})"; - this.OtherKnownTypes = new TypeCollection(typeof(decimal?)); } /// @@ -42,9 +41,6 @@ public override object Resolve(ReadOnlySpan data) throw new UnresolvedValueException(data, typeof(decimal)); } - /// - public override TypeCollection OtherKnownTypes { get; } - /// public override ScalarValueType ValueType => ScalarValueType.Number; } diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/DoubleScalarType.cs b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/DoubleScalarType.cs index 7dd030430..8e9711f32 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/DoubleScalarType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/DoubleScalarType.cs @@ -28,7 +28,6 @@ public DoubleScalarType() : base(Constants.ScalarNames.DOUBLE, typeof(double)) { this.Description = $"A 64-bit, floating-point value. (Min: {double.MinValue}, Max: {double.MaxValue})"; - this.OtherKnownTypes = new TypeCollection(typeof(double?)); } /// @@ -40,9 +39,6 @@ public override object Resolve(ReadOnlySpan data) throw new UnresolvedValueException(data, typeof(double)); } - /// - public override TypeCollection OtherKnownTypes { get; } - /// public override ScalarValueType ValueType => ScalarValueType.Number; } diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/FloatScalarType.cs b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/FloatScalarType.cs index a758f6a19..549d1a86e 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/FloatScalarType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/FloatScalarType.cs @@ -28,7 +28,6 @@ public FloatScalarType() : base(Constants.ScalarNames.FLOAT, typeof(float)) { this.Description = $"A 32-bit, floating-point value. (Min: {float.MinValue}, Max: {float.MaxValue})"; - this.OtherKnownTypes = new TypeCollection(typeof(float?)); } /// @@ -40,9 +39,6 @@ public override object Resolve(ReadOnlySpan data) throw new UnresolvedValueException(data, typeof(float)); } - /// - public override TypeCollection OtherKnownTypes { get; } - /// public override ScalarValueType ValueType => ScalarValueType.Number; } diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/GraphIdScalarType.cs b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/GraphIdScalarType.cs index 30968981c..b73b1d59c 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/GraphIdScalarType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/GraphIdScalarType.cs @@ -28,7 +28,6 @@ public GraphIdScalarType() : base(Constants.ScalarNames.ID, typeof(GraphId)) { this.Description = "The id scalar type represents a unique identifier in graphql."; - this.OtherKnownTypes = TypeCollection.Empty; } /// @@ -78,9 +77,6 @@ public override string SerializeToQueryLanguage(object item) return Constants.QueryLanguage.NULL; } - /// - public override TypeCollection OtherKnownTypes { get; } - /// public override ScalarValueType ValueType => ScalarValueType.StringOrNumber; } diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/GuidScalarType.cs b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/GuidScalarType.cs index 5e7df9a14..2e78a6d12 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/GuidScalarType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/GuidScalarType.cs @@ -27,7 +27,6 @@ public GuidScalarType() : base(Constants.ScalarNames.GUID, typeof(Guid)) { this.Description = "A standard guid (e.g. '6dd43342-ffe6-4964-bb6f-e31c8e50ec86')."; - this.OtherKnownTypes = TypeCollection.Empty; } /// @@ -48,9 +47,6 @@ public override object Serialize(object item) return ((Guid)item).ToString(); } - /// - public override TypeCollection OtherKnownTypes { get; } - /// public override ScalarValueType ValueType => ScalarValueType.String; } diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/IntScalarType.cs b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/IntScalarType.cs index 9f6a027c7..f2510335b 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/IntScalarType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/IntScalarType.cs @@ -27,12 +27,8 @@ public IntScalarType() : base(Constants.ScalarNames.INT, typeof(int)) { this.Description = $"A 32-bit integer. (Min: {int.MinValue}, Max: {int.MaxValue})"; - this.OtherKnownTypes = new TypeCollection(typeof(int?)); } - /// - public override TypeCollection OtherKnownTypes { get; } - /// public override ScalarValueType ValueType => ScalarValueType.Number; diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/LongScalarType.cs b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/LongScalarType.cs index 5ee6a2239..020ade3ad 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/LongScalarType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/LongScalarType.cs @@ -27,7 +27,6 @@ public LongScalarType() : base(Constants.ScalarNames.LONG, typeof(long)) { this.Description = $"A 64-bit integer. (Min: {long.MinValue}, Max: {long.MaxValue})"; - this.OtherKnownTypes = new TypeCollection(typeof(long?)); } /// @@ -39,9 +38,6 @@ public override object Resolve(ReadOnlySpan data) throw new UnresolvedValueException(data, typeof(long)); } - /// - public override TypeCollection OtherKnownTypes { get; } - /// public override ScalarValueType ValueType => ScalarValueType.Number; } diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/SByteScalarType.cs b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/SByteScalarType.cs index 9ffdb33b1..a18177689 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/SByteScalarType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/SByteScalarType.cs @@ -27,7 +27,6 @@ public SByteScalarType() : base(Constants.ScalarNames.SIGNED_BYTE, typeof(sbyte)) { this.Description = $"A signed byte. (Min: {sbyte.MinValue}, Max: {sbyte.MaxValue})"; - this.OtherKnownTypes = new TypeCollection(typeof(sbyte?)); } /// @@ -39,9 +38,6 @@ public override object Resolve(ReadOnlySpan data) throw new UnresolvedValueException(data, typeof(sbyte)); } - /// - public override TypeCollection OtherKnownTypes { get; } - /// public override ScalarValueType ValueType => ScalarValueType.Number; } diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/ScalarGraphTypeBase.cs b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/ScalarGraphTypeBase.cs index 371f09726..6a2959b2c 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/ScalarGraphTypeBase.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/ScalarGraphTypeBase.cs @@ -77,7 +77,7 @@ public virtual bool ValidateObject(object item) return true; var itemType = item.GetType(); - return itemType == this.ObjectType || this.OtherKnownTypes.Contains(itemType); + return itemType == this.ObjectType; } /// @@ -137,9 +137,6 @@ public virtual IScalarGraphType Clone(string newName) /// public virtual ILeafValueResolver SourceResolver { get; set; } - /// - public abstract TypeCollection OtherKnownTypes { get; } - /// public virtual bool IsVirtual => false; diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/ScalarReference.cs b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/ScalarReference.cs index 9388c62fa..6414f79f5 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/ScalarReference.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/ScalarReference.cs @@ -41,11 +41,6 @@ public static ScalarReference Create(IScalarGraphType graphType, Type instanceTy reference.InstanceType = instanceType; reference.PrimaryType = graphType.ObjectType; - if (graphType.OtherKnownTypes.Count > 0) - reference.OtherKnownTypes = graphType.OtherKnownTypes.ToList(); - else - reference.OtherKnownTypes = new List(); - reference.Name = graphType.Name; return reference; } @@ -70,13 +65,6 @@ private ScalarReference() /// The type of the primary. public Type PrimaryType { get; private set; } - /// - /// Gets a list of known alternate .NET types that can be - /// handled by this scalar (e.g. int?, long? etc.) - /// - /// The other known types. - public IReadOnlyList OtherKnownTypes { get; private set; } - /// /// Gets the name of this scalar as it has been declared. /// diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/ShortScalarType.cs b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/ShortScalarType.cs index 184a24bc1..3c30a3c05 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/ShortScalarType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/ShortScalarType.cs @@ -27,12 +27,8 @@ public ShortScalarType() : base(Constants.ScalarNames.SHORT, typeof(short)) { this.Description = $"A 16-bit integer. (Min: {short.MinValue}, Max: {short.MaxValue})"; - this.OtherKnownTypes = new TypeCollection(typeof(short?)); } - /// - public override TypeCollection OtherKnownTypes { get; } - /// public override ScalarValueType ValueType => ScalarValueType.Number; diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/StringScalarType.cs b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/StringScalarType.cs index 1978954ed..728dde6e0 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/StringScalarType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/StringScalarType.cs @@ -28,7 +28,6 @@ public StringScalarType() : base(Constants.ScalarNames.STRING, typeof(string)) { this.Description = "A UTF-8 encoded string of characters."; - this.OtherKnownTypes = TypeCollection.Empty; } /// @@ -52,9 +51,6 @@ public override string SerializeToQueryLanguage(object item) return GraphQLStrings.Escape(item.ToString()).AsQuotedString(); } - /// - public override TypeCollection OtherKnownTypes { get; } - /// public override ScalarValueType ValueType => ScalarValueType.String; } diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/TimeOnlyScalarType.cs b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/TimeOnlyScalarType.cs index aad30b0be..4e3719b22 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/TimeOnlyScalarType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/TimeOnlyScalarType.cs @@ -31,7 +31,6 @@ public TimeOnlyScalarType() : base(Constants.ScalarNames.TIMEONLY, typeof(TimeOnly)) { this.Description = "A time of day that does not include a date component."; - this.OtherKnownTypes = new TypeCollection(typeof(TimeOnly?)); } /// @@ -60,9 +59,6 @@ public override string SerializeToQueryLanguage(object item) return Constants.QueryLanguage.NULL; } - /// - public override TypeCollection OtherKnownTypes { get; } - /// public override ScalarValueType ValueType => ScalarValueType.String; } diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/UIntScalarType.cs b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/UIntScalarType.cs index 29313e441..8421cd2d6 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/UIntScalarType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/UIntScalarType.cs @@ -27,7 +27,6 @@ public UIntScalarType() : base(Constants.ScalarNames.UINT, typeof(uint)) { this.Description = $"A 32-bit, unsigned integer. (Min: {uint.MinValue}, Max: {uint.MaxValue})"; - this.OtherKnownTypes = new TypeCollection(typeof(uint?)); } /// @@ -39,9 +38,6 @@ public override object Resolve(ReadOnlySpan data) throw new UnresolvedValueException(data, typeof(uint)); } - /// - public override TypeCollection OtherKnownTypes { get; } - /// public override ScalarValueType ValueType => ScalarValueType.Number; } diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/ULongScalarType.cs b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/ULongScalarType.cs index 6730194b9..f00413c75 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/ULongScalarType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/ULongScalarType.cs @@ -27,7 +27,6 @@ public ULongScalarType() : base(Constants.ScalarNames.ULONG, typeof(ulong)) { this.Description = $"A 64-bit, unsigned integer. (Min: {ulong.MinValue}, Max: {ulong.MaxValue})"; - this.OtherKnownTypes = new TypeCollection(typeof(ulong?)); } /// @@ -39,9 +38,6 @@ public override object Resolve(ReadOnlySpan data) throw new UnresolvedValueException(data, typeof(ulong)); } - /// - public override TypeCollection OtherKnownTypes { get; } - /// public override ScalarValueType ValueType => ScalarValueType.Number; } diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/UShortScalarType.cs b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/UShortScalarType.cs index 6dc0557f5..76c81a2b1 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/UShortScalarType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/UShortScalarType.cs @@ -27,12 +27,8 @@ public UShortScalarType() : base(Constants.ScalarNames.USHORT, typeof(ushort)) { this.Description = $"A 16-bit unsigned integer. (Min: {ushort.MinValue}, Max: {ushort.MaxValue})"; - this.OtherKnownTypes = new TypeCollection(typeof(ushort?)); } - /// - public override TypeCollection OtherKnownTypes { get; } - /// public override ScalarValueType ValueType => ScalarValueType.Number; diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/UriScalarType.cs b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/UriScalarType.cs index ea9641319..1c8f716e2 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/UriScalarType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/UriScalarType.cs @@ -28,7 +28,6 @@ public UriScalarType() : base(Constants.ScalarNames.URI, typeof(Uri)) { this.Description = "A uri pointing to a location on the web (a.k.a. URL)."; - this.OtherKnownTypes = TypeCollection.Empty; } /// @@ -67,9 +66,6 @@ public override string SerializeToQueryLanguage(object item) return Constants.QueryLanguage.NULL; } - /// - public override TypeCollection OtherKnownTypes { get; } - /// public override ScalarValueType ValueType => ScalarValueType.String; } diff --git a/src/graphql-aspnet/Schemas/TypeSystem/TypeCollections/ConcreteTypeCollection.cs b/src/graphql-aspnet/Schemas/TypeSystem/TypeCollections/ConcreteTypeCollection.cs index 07bf1c62f..f6a77ba5c 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/TypeCollections/ConcreteTypeCollection.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/TypeCollections/ConcreteTypeCollection.cs @@ -177,8 +177,7 @@ private void EnsureGraphTypeToConcreteTypeAssociationOrThrow(IGraphType graphTyp if (graphType is IScalarGraphType scalarType) { if (associatedType == null || - (associatedType != scalarType.ObjectType && - !scalarType.OtherKnownTypes.Contains(associatedType))) + (associatedType != scalarType.ObjectType)) { throw new GraphTypeDeclarationException( $"The scalar type '{graphType.Name}' cannot be associated to the concrete type '{associatedType?.FriendlyName() ?? "-null-"}' " + diff --git a/src/graphql-aspnet/ServerExtensions/MultipartRequests/Schema/FileUploadScalarGraphType.cs b/src/graphql-aspnet/ServerExtensions/MultipartRequests/Schema/FileUploadScalarGraphType.cs index 52079ad0f..59c0ec4fd 100644 --- a/src/graphql-aspnet/ServerExtensions/MultipartRequests/Schema/FileUploadScalarGraphType.cs +++ b/src/graphql-aspnet/ServerExtensions/MultipartRequests/Schema/FileUploadScalarGraphType.cs @@ -55,9 +55,6 @@ public override string SerializeToQueryLanguage(object item) /// public override ScalarValueType ValueType => ScalarValueType.Boolean | ScalarValueType.String | ScalarValueType.Number; - /// - public override TypeCollection OtherKnownTypes => TypeCollection.Empty; - /// public override object Resolve(ReadOnlySpan data) { diff --git a/src/graphql-aspnet/graphql-aspnet.csproj b/src/graphql-aspnet/graphql-aspnet.csproj index 8683b4e38..5260e555c 100644 --- a/src/graphql-aspnet/graphql-aspnet.csproj +++ b/src/graphql-aspnet/graphql-aspnet.csproj @@ -12,8 +12,4 @@ - - - - \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-testframework/GraphQLTemplateHelper.cs b/src/unit-tests/graphql-aspnet-testframework/GraphQLTemplateHelper.cs index cc1b965b8..bc1244264 100644 --- a/src/unit-tests/graphql-aspnet-testframework/GraphQLTemplateHelper.cs +++ b/src/unit-tests/graphql-aspnet-testframework/GraphQLTemplateHelper.cs @@ -19,6 +19,8 @@ namespace GraphQL.AspNet.Tests.Framework using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Schemas.Generation; using GraphQL.AspNet.Schemas.Generation.TypeMakers; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Schemas.TypeSystem.Scalars; diff --git a/src/unit-tests/graphql-aspnet-testframework/TestServer.cs b/src/unit-tests/graphql-aspnet-testframework/TestServer.cs index 6ca9167da..e13c8222a 100644 --- a/src/unit-tests/graphql-aspnet-testframework/TestServer.cs +++ b/src/unit-tests/graphql-aspnet-testframework/TestServer.cs @@ -182,8 +182,8 @@ public virtual GraphTypeCreationResult CreateGraphType(Type concreteType, TypeKi { var factory = new DefaultGraphQLTypeMakerFactory(); factory.Initialize(this.Schema); - var maker = factory.CreateTypeMaker(concreteType, kind); + var maker = factory.CreateTypeMaker(concreteType, kind); var template = factory.MakeTemplate(concreteType); return maker.CreateGraphType(template); } @@ -203,6 +203,7 @@ public virtual FieldContextBuilder CreateGraphTypeFieldContextBuilder(); factory.Initialize(this.Schema); + var fieldMaker = new GraphFieldMaker(this.Schema, factory); var fieldResult = fieldMaker.CreateField(template); diff --git a/src/unit-tests/graphql-aspnet-tests/CommonHelpers/TestServerExtensions.cs b/src/unit-tests/graphql-aspnet-tests/CommonHelpers/TestServerExtensions.cs new file mode 100644 index 000000000..1b701a260 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/CommonHelpers/TestServerExtensions.cs @@ -0,0 +1,35 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.CommonHelpers +{ + using GraphQL.AspNet.Engine; + using GraphQL.AspNet.Interfaces.Engine; + using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Schemas.Generation; + using GraphQL.AspNet.Tests.Framework; + + public static class TestServerExtensions + { + /// + /// Creates a new maker factory that the test server can use. + /// + /// The type of the schema to render the factory for. + /// The server instance. + /// GraphQL.AspNet.Interfaces.Engine.IGraphQLTypeMakerFactory<TSchema>. + public static IGraphQLTypeMakerFactory CreateMakerFactory(this TestServer serverInstance) + where TSchema : class, ISchema + { + var factory = new DefaultGraphQLTypeMakerFactory(); + factory.Initialize(serverInstance.Schema); + + return factory; + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultScalarTypeProviderTestData/ScalarNullOtherTypeCollection.cs b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultScalarTypeProviderTestData/ScalarNullOtherTypeCollection.cs index db7c73b46..2f06d2709 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultScalarTypeProviderTestData/ScalarNullOtherTypeCollection.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultScalarTypeProviderTestData/ScalarNullOtherTypeCollection.cs @@ -12,7 +12,6 @@ public class ScalarNullOtherTypeCollection : ScalarTestBase { public ScalarNullOtherTypeCollection() { - this.OtherKnownTypes = null; } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultScalarTypeProviderTestData/ScalarOtherTypeInUse.cs b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultScalarTypeProviderTestData/ScalarOtherTypeInUse.cs index af8476562..3a989fa0f 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultScalarTypeProviderTestData/ScalarOtherTypeInUse.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultScalarTypeProviderTestData/ScalarOtherTypeInUse.cs @@ -14,7 +14,6 @@ public class ScalarOtherTypeInUse : ScalarTestBase { public ScalarOtherTypeInUse() { - this.OtherKnownTypes = new TypeCollection(typeof(int)); } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultScalarTypeProviderTestData/ScalarTestBase.cs b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultScalarTypeProviderTestData/ScalarTestBase.cs index aa17c1188..7be9102bc 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultScalarTypeProviderTestData/ScalarTestBase.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultScalarTypeProviderTestData/ScalarTestBase.cs @@ -22,7 +22,6 @@ public abstract class ScalarTestBase : IScalarGraphType { protected ScalarTestBase() { - this.OtherKnownTypes = new TypeCollection(); this.Kind = TypeKind.SCALAR; this.ValueType = ScalarValueType.Number; this.Publish = true; @@ -46,8 +45,6 @@ public virtual IScalarGraphType Clone(string newName) return newInstance; } - public TypeCollection OtherKnownTypes { get; set; } - public ScalarValueType ValueType { get; set; } public ILeafValueResolver SourceResolver { get; set; } diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/TwoPropertyObjectAsScalar.cs b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/TwoPropertyObjectAsScalar.cs index c9a31c57e..bbc0d2c30 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/TwoPropertyObjectAsScalar.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/TwoPropertyObjectAsScalar.cs @@ -19,7 +19,6 @@ public class TwoPropertyObjectAsScalar : ScalarGraphTypeBase public TwoPropertyObjectAsScalar() : base(nameof(TwoPropertyObjectAsScalar), typeof(TwoPropertyObject)) { - this.OtherKnownTypes = TypeCollection.Empty; } public override object Resolve(ReadOnlySpan data) @@ -27,8 +26,6 @@ public override object Resolve(ReadOnlySpan data) return null; } - public override TypeCollection OtherKnownTypes { get; } - public override ScalarValueType ValueType => ScalarValueType.String; } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTests.cs b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTests.cs index e893a801b..3f293cc35 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTests.cs @@ -28,11 +28,17 @@ namespace GraphQL.AspNet.Tests.Engine [TestFixture] public class DefaultSchemaFactoryTests { - [Test] - public void OneScalarType_GeneratesCorrectly() + private IServiceCollection SetupCollection() { var collection = new ServiceCollection(); collection.AddTransient, DefaultGraphQLTypeMakerFactory>(); + return collection; + } + + [Test] + public void OneScalarType_GeneratesCorrectly() + { + var collection = this.SetupCollection(); var factory = new DefaultGraphQLSchemaFactory(includeBuiltInDirectives: false); var options = new SchemaOptions(collection); @@ -66,8 +72,7 @@ public void OneScalarType_GeneratesCorrectly() [Test] public void CustomScalar_AllAssociatedTypesAreRegistered() { - var collection = new ServiceCollection(); - collection.AddTransient, DefaultGraphQLTypeMakerFactory>(); + var collection = this.SetupCollection(); var factory = new DefaultGraphQLSchemaFactory(includeBuiltInDirectives: false); var options = new SchemaOptions(collection); @@ -101,8 +106,7 @@ public void CustomScalar_AllAssociatedTypesAreRegistered() [Test] public void OneEnum_AllAssociatedTypesAreRegistered() { - var collection = new ServiceCollection(); - collection.AddTransient, DefaultGraphQLTypeMakerFactory>(); + var collection = this.SetupCollection(); var factory = new DefaultGraphQLSchemaFactory(includeBuiltInDirectives: false); var options = new SchemaOptions(collection); @@ -140,8 +144,7 @@ public void OneEnum_AllAssociatedTypesAreRegistered() [Test] public void OneObjectType_NoArgumentsOnFields_GeneratesCorrectly() { - var collection = new ServiceCollection(); - collection.AddTransient, DefaultGraphQLTypeMakerFactory>(); + var collection = this.SetupCollection(); var factory = new DefaultGraphQLSchemaFactory(includeBuiltInDirectives: false); var options = new SchemaOptions(collection); @@ -181,8 +184,7 @@ public void OneObjectType_NoArgumentsOnFields_GeneratesCorrectly() [Test] public void OneInputObjectType_GeneratesCorrectly() { - var collection = new ServiceCollection(); - collection.AddTransient, DefaultGraphQLTypeMakerFactory>(); + var collection = this.SetupCollection(); var factory = new DefaultGraphQLSchemaFactory(includeBuiltInDirectives: false); var options = new SchemaOptions(collection); @@ -220,8 +222,7 @@ public void OneInputObjectType_GeneratesCorrectly() [Test] public void OneInterfaceType_NoArgumentsOnFields_GeneratesCorrectly() { - var collection = new ServiceCollection(); - collection.AddTransient, DefaultGraphQLTypeMakerFactory>(); + var collection = this.SetupCollection(); var factory = new DefaultGraphQLSchemaFactory(includeBuiltInDirectives: false); var options = new SchemaOptions(collection); @@ -259,8 +260,7 @@ public void OneInterfaceType_NoArgumentsOnFields_GeneratesCorrectly() [Test] public void OneObjectType_ArgumentsOnField_GeneratesCorrectly() { - var collection = new ServiceCollection(); - collection.AddTransient, DefaultGraphQLTypeMakerFactory>(); + var collection = this.SetupCollection(); var factory = new DefaultGraphQLSchemaFactory(includeBuiltInDirectives: false); var options = new SchemaOptions(collection); @@ -306,8 +306,7 @@ public void OneObjectType_ArgumentsOnField_GeneratesCorrectly() [Test] public void OneDirective_GeneratesCorrectly() { - var collection = new ServiceCollection(); - collection.AddTransient, DefaultGraphQLTypeMakerFactory>(); + var collection = this.SetupCollection(); var factory = new DefaultGraphQLSchemaFactory(includeBuiltInDirectives: false); var options = new SchemaOptions(collection); @@ -347,8 +346,7 @@ public void OneDirective_GeneratesCorrectly() [Test] public void OneController_GeneratesCorrectly() { - var collection = new ServiceCollection(); - collection.AddTransient, DefaultGraphQLTypeMakerFactory>(); + var collection = this.SetupCollection(); var factory = new DefaultGraphQLSchemaFactory(includeBuiltInDirectives: false); var options = new SchemaOptions(collection); @@ -380,8 +378,7 @@ public void OneController_GeneratesCorrectly() [Test] public void ClassArgumentToAField_ThatIsRegisteredAsAScalar_IsNamedProperly() { - var collection = new ServiceCollection(); - collection.AddTransient, DefaultGraphQLTypeMakerFactory>(); + var collection = this.SetupCollection(); var factory = new DefaultGraphQLSchemaFactory(includeBuiltInDirectives: false); var options = new SchemaOptions(collection); @@ -419,8 +416,7 @@ public void ClassArgumentToAField_ThatIsRegisteredAsAScalar_IsNamedProperly() [Test] public void ReturnValueOfAField_ThatIsRegisteredAsAScalar_IsNamedProperly() { - var collection = new ServiceCollection(); - collection.AddTransient, DefaultGraphQLTypeMakerFactory>(); + var collection = this.SetupCollection(); var factory = new DefaultGraphQLSchemaFactory(includeBuiltInDirectives: false); var options = new SchemaOptions(collection); diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/DirectiveTypeMakerTests.cs b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/DirectiveTypeMakerTests.cs index d5d0da9f4..78cf8b482 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/DirectiveTypeMakerTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/DirectiveTypeMakerTests.cs @@ -16,6 +16,7 @@ namespace GraphQL.AspNet.Tests.Engine.TypeMakers using GraphQL.AspNet.Schemas.Generation; using GraphQL.AspNet.Schemas.Generation.TypeMakers; using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Tests.CommonHelpers; using GraphQL.AspNet.Tests.Engine.TypeMakers.TestData; using GraphQL.AspNet.Tests.Framework; using GraphQL.AspNet.Tests.Framework.CommonHelpers; @@ -30,8 +31,7 @@ public void Directive_BasicPropertyCheck() var builder = new TestServerBuilder(); var server = builder.Build(); - var factory = new DefaultGraphQLTypeMakerFactory(); - factory.Initialize(server.Schema); + var factory = server.CreateMakerFactory(); var template = factory.MakeTemplate(typeof(MultiMethodDirective), TypeKind.DIRECTIVE); var typeMaker = new DirectiveMaker(server.Schema.Configuration, factory.CreateArgumentMaker()); @@ -65,8 +65,7 @@ public void Directive_RepeatableAttributeIsSetWhenPresent() var builder = new TestServerBuilder(); var server = builder.Build(); - var factory = new DefaultGraphQLTypeMakerFactory(); - factory.Initialize(server.Schema); + var factory = server.CreateMakerFactory(); var template = factory.MakeTemplate(typeof(RepeatableDirective), TypeKind.DIRECTIVE); var typeMaker = new DirectiveMaker(server.Schema.Configuration, factory.CreateArgumentMaker()); diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/FieldMaker_InputFieldTests.cs b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/FieldMaker_InputFieldTests.cs index 87e3ac484..c51081630 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/FieldMaker_InputFieldTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/FieldMaker_InputFieldTests.cs @@ -14,6 +14,7 @@ namespace GraphQL.AspNet.Tests.Engine.TypeMakers using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Schemas.Generation; using GraphQL.AspNet.Schemas.Generation.TypeMakers; + using GraphQL.AspNet.Tests.CommonHelpers; using GraphQL.AspNet.Tests.Engine.TypeMakers.TestData; using GraphQL.AspNet.Tests.Framework; using GraphQL.AspNet.Tests.Framework.CommonHelpers; @@ -32,8 +33,7 @@ public void Parse_NotRequiredValueTypePropertyCheck() .Values .Single(x => x.Name == nameof(InputTestObject.NotRequiredValueTypeField)); - var factory = new DefaultGraphQLTypeMakerFactory(); - factory.Initialize(server.Schema); + var factory = server.CreateMakerFactory(); var graphField = new GraphFieldMaker(server.Schema, factory).CreateField(fieldTemplate).Field; @@ -62,8 +62,7 @@ public void Parse_RequiredValueTypePropertyCheck() .Values .Single(x => x.Name == nameof(InputTestObject.RequiredValueTypeField)); - var factory = new DefaultGraphQLTypeMakerFactory(); - factory.Initialize(server.Schema); + var factory = server.CreateMakerFactory(); var graphField = new GraphFieldMaker(server.Schema, factory).CreateField(fieldTemplate).Field; @@ -89,8 +88,7 @@ public void Parse_NotRequiredReferenceTypePropertyCheck() .Values .Single(x => x.Name == nameof(InputTestObject.NotRequiredReferenceTypeField)); - var factory = new DefaultGraphQLTypeMakerFactory(); - factory.Initialize(server.Schema); + var factory = server.CreateMakerFactory(); var graphField = new GraphFieldMaker(server.Schema, factory).CreateField(fieldTemplate).Field; @@ -118,8 +116,7 @@ public void Parse_RequiredReferenceTypePropertyCheck() .Values .Single(x => x.Name == nameof(InputTestObject.RequiredReferenceTypeField)); - var factory = new DefaultGraphQLTypeMakerFactory(); - factory.Initialize(server.Schema); + var factory = server.CreateMakerFactory(); var graphField = new GraphFieldMaker(server.Schema, factory).CreateField(fieldTemplate).Field; @@ -149,9 +146,7 @@ public void Parse_RequiredNonNullableReferenceTypePropertyCheck() .Values .Single(x => x.Name == nameof(InputTestObject.RequiredReferenceExplicitNonNullTypeField)); - var factory = new DefaultGraphQLTypeMakerFactory(); - factory.Initialize(server.Schema); - + var factory = server.CreateMakerFactory(); var graphField = new GraphFieldMaker(server.Schema, factory).CreateField(fieldTemplate).Field; Assert.AreEqual("requiredReferenceExplicitNonNullTypeField", graphField.Name); @@ -178,8 +173,7 @@ public void Parse_RequiredGraphIdPropertyCheck() .Values .Single(x => x.Name == nameof(InputTestObject.GraphIdRequired)); - var factory = new DefaultGraphQLTypeMakerFactory(); - factory.Initialize(server.Schema); + var factory = server.CreateMakerFactory(); var graphField = new GraphFieldMaker(server.Schema, factory).CreateField(fieldTemplate).Field; @@ -206,8 +200,7 @@ public void Parse_NotRequiredGraphIdPropertyCheck() .Values .Single(x => x.Name == nameof(InputTestObject.GraphIdNotRequired)); - var factory = new DefaultGraphQLTypeMakerFactory(); - factory.Initialize(server.Schema); + var factory = server.CreateMakerFactory(); var graphField = new GraphFieldMaker(server.Schema, factory).CreateField(fieldTemplate).Field; @@ -233,8 +226,7 @@ public void Parse_NotRequiredNullableGraphIdPropertyCheck() .Values .Single(x => x.Name == nameof(InputTestObject.GraphIdNullable)); - var factory = new DefaultGraphQLTypeMakerFactory(); - factory.Initialize(server.Schema); + var factory = server.CreateMakerFactory(); var graphField = new GraphFieldMaker(server.Schema, factory).CreateField(fieldTemplate).Field; diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/FieldMaker_StandardFieldTests.cs b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/FieldMaker_StandardFieldTests.cs index f9e8c0a4f..797ee3978 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/FieldMaker_StandardFieldTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/FieldMaker_StandardFieldTests.cs @@ -18,6 +18,7 @@ namespace GraphQL.AspNet.Tests.Engine.TypeMakers using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Security; + using GraphQL.AspNet.Tests.CommonHelpers; using GraphQL.AspNet.Tests.Engine.TypeMakers.TestData; using GraphQL.AspNet.Tests.Framework; using Moq; @@ -63,8 +64,7 @@ public void Parse_PolicyOnController_IsInheritedByField() Assert.AreEqual(1, template.SecurityPolicies.Count()); Assert.AreEqual(0, actionMethod.SecurityPolicies.Count()); - var factory = new DefaultGraphQLTypeMakerFactory(); - factory.Initialize(server.Schema); + var factory = server.CreateMakerFactory(); var graphField = new GraphFieldMaker(server.Schema, factory).CreateField(actionMethod).Field; Assert.AreEqual(1, Enumerable.Count(graphField.SecurityGroups)); @@ -86,8 +86,7 @@ public void Parse_PolicyOnController_AndOnMethod_IsInheritedByField_InCorrectOrd Assert.AreEqual(1, template.SecurityPolicies.Count()); Assert.AreEqual(1, actionMethod.SecurityPolicies.Count()); - var factory = new DefaultGraphQLTypeMakerFactory(); - factory.Initialize(server.Schema); + var factory = server.CreateMakerFactory(); var graphField = new GraphFieldMaker(server.Schema, factory).CreateField(actionMethod).Field; @@ -116,8 +115,7 @@ public void Parse_MethodWithNullableEnum_ParsesCorrectly() Assert.AreEqual(typeof(NullableEnumController.LengthType), arg.ObjectType); Assert.AreEqual(NullableEnumController.LengthType.Yards, arg.DefaultValue); - var factory = new DefaultGraphQLTypeMakerFactory(); - factory.Initialize(server.Schema); + var factory = server.CreateMakerFactory(); var graphField = new GraphFieldMaker(server.Schema, factory).CreateField(field).Field; Assert.IsNotNull(graphField); diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/GraphTypeMakerTestBase.cs b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/GraphTypeMakerTestBase.cs index 5889d4bbd..f909bdb68 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/GraphTypeMakerTestBase.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/GraphTypeMakerTestBase.cs @@ -19,6 +19,8 @@ namespace GraphQL.AspNet.Tests.Engine.TypeMakers using GraphQL.AspNet.Tests.Framework; using GraphQL.AspNet.Schemas.Generation; using GraphQL.AspNet.Schemas; + using Microsoft.AspNetCore.Hosting.Server; + using GraphQL.AspNet.Tests.CommonHelpers; public abstract class GraphTypeMakerTestBase { @@ -38,8 +40,7 @@ protected GraphTypeCreationResult MakeGraphType( var testServer = builder.Build(); - var factory = new DefaultGraphQLTypeMakerFactory(); - factory.Initialize(testServer.Schema); + var factory = testServer.CreateMakerFactory(); var template = factory.MakeTemplate(type, kind); var maker = factory.CreateTypeMaker(type, kind); @@ -51,8 +52,7 @@ protected IGraphField MakeGraphField(IGraphFieldTemplate fieldTemplate) { var testServer = new TestServerBuilder().Build(); - var factory = new DefaultGraphQLTypeMakerFactory(); - factory.Initialize(testServer.Schema); + var factory = testServer.CreateMakerFactory(); var maker = factory.CreateFieldMaker(); diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/InterfaceTypeMakerTests.cs b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/InterfaceTypeMakerTests.cs index ed76fb8eb..ba85da5ec 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/InterfaceTypeMakerTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/InterfaceTypeMakerTests.cs @@ -6,16 +6,23 @@ // -- // License: MIT // ************************************************************* + +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* namespace GraphQL.AspNet.Tests.Engine.TypeMakers { using System.Linq; using GraphQL.AspNet.Configuration; - using GraphQL.AspNet.Engine; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Schemas; - using GraphQL.AspNet.Schemas.Generation; using GraphQL.AspNet.Schemas.Generation.TypeMakers; using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Tests.CommonHelpers; using GraphQL.AspNet.Tests.Engine.TypeMakers.TestData; using GraphQL.AspNet.Tests.Framework; using NUnit.Framework; @@ -29,8 +36,7 @@ public void CreateGraphType_PropertyCheck() var server = new TestServerBuilder().Build(); var template = GraphQLTemplateHelper.CreateInterfaceTemplate(); - var factory = new DefaultGraphQLTypeMakerFactory(); - factory.Initialize(server.Schema); + var factory = server.CreateMakerFactory(); var typeMaker = new InterfaceGraphTypeMaker(server.Schema.Configuration, factory.CreateFieldMaker()); diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/ObjectGraphTypeMakerTests.cs b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/ObjectGraphTypeMakerTests.cs index e002a084b..e1f41fa2c 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/ObjectGraphTypeMakerTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/ObjectGraphTypeMakerTests.cs @@ -16,6 +16,7 @@ namespace GraphQL.AspNet.Tests.Engine.TypeMakers using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Schemas.Generation; using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Tests.CommonHelpers; using GraphQL.AspNet.Tests.Engine.TypeMakers.TestData; using GraphQL.AspNet.Tests.Framework; using GraphQL.AspNet.Tests.Framework.CommonHelpers; @@ -45,8 +46,8 @@ public void Object_CreateGraphType_ParsesCorrectly() { var server = new TestServerBuilder(TestOptions.UseCodeDeclaredNames).Build(); var template = GraphQLTemplateHelper.CreateGraphTypeTemplate(TypeKind.OBJECT); - var factory = new DefaultGraphQLTypeMakerFactory(); - factory.Initialize(server.Schema); + + var factory = server.CreateMakerFactory(); var objectGraphType = factory .CreateTypeMaker(typeof(TypeCreationItem)) diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/CustomScalarWithDirectives.cs b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/CustomScalarWithDirectives.cs index 19fe71b53..4df497d82 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/CustomScalarWithDirectives.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/CustomScalarWithDirectives.cs @@ -37,7 +37,5 @@ public override object Serialize(object item) } public override ScalarValueType ValueType => ScalarValueType.String; - - public override TypeCollection OtherKnownTypes { get; } = new TypeCollection(); } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/InputResolverGeneratorTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/InputResolverGeneratorTests.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/InputResolverGeneratorTests.cs rename to src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/InputResolverGeneratorTests.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/InputValueNodeTestData/CoffeeCan.cs b/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/InputValueNodeTestData/CoffeeCan.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/InputValueNodeTestData/CoffeeCan.cs rename to src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/InputValueNodeTestData/CoffeeCan.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/InputValueNodeTestData/Telephone.cs b/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/InputValueNodeTestData/Telephone.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/InputValueNodeTestData/Telephone.cs rename to src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/InputValueNodeTestData/Telephone.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/ObjectMethodResolverTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ObjectMethodResolverTests.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/ObjectMethodResolverTests.cs rename to src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ObjectMethodResolverTests.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/ObjectPropertyResolverTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ObjectPropertyResolverTests.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/ObjectPropertyResolverTests.cs rename to src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ObjectPropertyResolverTests.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/ValueResolversTestData/IResolverInterface.cs b/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ValueResolversTestData/IResolverInterface.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/ValueResolversTestData/IResolverInterface.cs rename to src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ValueResolversTestData/IResolverInterface.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/ValueResolversTestData/ResolvableEnum.cs b/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ValueResolversTestData/ResolvableEnum.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/ValueResolversTestData/ResolvableEnum.cs rename to src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ValueResolversTestData/ResolvableEnum.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/ValueResolversTestData/ResolverObject.cs b/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ValueResolversTestData/ResolverObject.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/ValueResolversTestData/ResolverObject.cs rename to src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ValueResolversTestData/ResolverObject.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/ValueResolversTestData/ResolverStructA.cs b/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ValueResolversTestData/ResolverStructA.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/ValueResolversTestData/ResolverStructA.cs rename to src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ValueResolversTestData/ResolverStructA.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/ValueResolversTestData/ResolverStructB.cs b/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ValueResolversTestData/ResolverStructB.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/ValueResolversTestData/ResolverStructB.cs rename to src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ValueResolversTestData/ResolverStructB.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospectionTestData/CustomSpecifiedScalar.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospectionTestData/CustomSpecifiedScalar.cs index 27242b297..20e621bc8 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospectionTestData/CustomSpecifiedScalar.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospectionTestData/CustomSpecifiedScalar.cs @@ -24,8 +24,6 @@ public CustomSpecifiedScalar() public override ScalarValueType ValueType => ScalarValueType.String; - public override TypeCollection OtherKnownTypes { get; } = TypeCollection.Empty; - public override object Resolve(ReadOnlySpan data) { return null; diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/TypeSystemDirectiveTestData/MarkedScalarByAttribute.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/TypeSystemDirectiveTestData/MarkedScalarByAttribute.cs index 758da8dc9..21feada77 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/TypeSystemDirectiveTestData/MarkedScalarByAttribute.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/TypeSystemDirectiveTestData/MarkedScalarByAttribute.cs @@ -33,7 +33,5 @@ public override object Serialize(object item) } public override ScalarValueType ValueType => ScalarValueType.Boolean; - - public override TypeCollection OtherKnownTypes => TypeCollection.Empty; } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ActionMethodTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionMethodTemplateTests.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ActionMethodTemplateTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionMethodTemplateTests.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ActionTestData/ActionMethodWithDirectiveController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/ActionMethodWithDirectiveController.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ActionTestData/ActionMethodWithDirectiveController.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/ActionMethodWithDirectiveController.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ActionTestData/ActionResultReturnTypeController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/ActionResultReturnTypeController.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ActionTestData/ActionResultReturnTypeController.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/ActionResultReturnTypeController.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ActionTestData/ArrayInputMethodController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/ArrayInputMethodController.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ActionTestData/ArrayInputMethodController.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/ArrayInputMethodController.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ActionTestData/ComplexityValueCheckController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/ComplexityValueCheckController.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ActionTestData/ComplexityValueCheckController.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/ComplexityValueCheckController.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ActionTestData/ContainerController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/ContainerController.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ActionTestData/ContainerController.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/ContainerController.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ActionTestData/CustomNamedItem.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/CustomNamedItem.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ActionTestData/CustomNamedItem.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/CustomNamedItem.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ActionTestData/ITestItem.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/ITestItem.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ActionTestData/ITestItem.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/ITestItem.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ActionTestData/IUnionTestDataItem.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/IUnionTestDataItem.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ActionTestData/IUnionTestDataItem.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/IUnionTestDataItem.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ActionTestData/InterfaceReturnTypeController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/InterfaceReturnTypeController.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ActionTestData/InterfaceReturnTypeController.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/InterfaceReturnTypeController.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ActionTestData/OneMethodController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/OneMethodController.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ActionTestData/OneMethodController.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/OneMethodController.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ActionTestData/ScalarInUnionController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/ScalarInUnionController.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ActionTestData/ScalarInUnionController.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/ScalarInUnionController.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ActionTestData/TestItemA.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/TestItemA.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ActionTestData/TestItemA.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/TestItemA.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ActionTestData/TestItemB.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/TestItemB.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ActionTestData/TestItemB.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/TestItemB.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ActionTestData/UnionDataA.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/UnionDataA.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ActionTestData/UnionDataA.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/UnionDataA.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ActionTestData/UnionDataB.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/UnionDataB.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ActionTestData/UnionDataB.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/UnionDataB.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ActionTestData/UnionTestController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/UnionTestController.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ActionTestData/UnionTestController.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/UnionTestController.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ActionTestData/UnionTestProxy.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/UnionTestProxy.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ActionTestData/UnionTestProxy.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/UnionTestProxy.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/AppliedDirectiveTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/AppliedDirectiveTemplateTests.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/AppliedDirectiveTemplateTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/AppliedDirectiveTemplateTests.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ArgumentTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ArgumentTemplateTests.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ArgumentTemplateTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ArgumentTemplateTests.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ControllerTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTemplateTests.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ControllerTemplateTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTemplateTests.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ControllerTestData/ArrayInputParamController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/ArrayInputParamController.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ControllerTestData/ArrayInputParamController.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/ArrayInputParamController.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ControllerTestData/ArrayReturnController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/ArrayReturnController.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ControllerTestData/ArrayReturnController.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/ArrayReturnController.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ControllerTestData/ControllerWithDirective.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/ControllerWithDirective.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ControllerTestData/ControllerWithDirective.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/ControllerWithDirective.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ControllerTestData/ControllerWithStaticMethod.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/ControllerWithStaticMethod.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ControllerTestData/ControllerWithStaticMethod.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/ControllerWithStaticMethod.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ControllerTestData/DeclaredGraphRootController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/DeclaredGraphRootController.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ControllerTestData/DeclaredGraphRootController.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/DeclaredGraphRootController.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ControllerTestData/InvalidRouteController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/InvalidRouteController.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ControllerTestData/InvalidRouteController.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/InvalidRouteController.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ControllerTestData/NoInheritanceFromBaseController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/NoInheritanceFromBaseController.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ControllerTestData/NoInheritanceFromBaseController.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/NoInheritanceFromBaseController.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ControllerTestData/NoRouteSpecifierController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/NoRouteSpecifierController.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ControllerTestData/NoRouteSpecifierController.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/NoRouteSpecifierController.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ControllerTestData/OneMethodController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/OneMethodController.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ControllerTestData/OneMethodController.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/OneMethodController.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ControllerTestData/SimpleControllerNoMethods.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/SimpleControllerNoMethods.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ControllerTestData/SimpleControllerNoMethods.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/SimpleControllerNoMethods.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ControllerTestData/TwoMethodClashController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/TwoMethodClashController.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ControllerTestData/TwoMethodClashController.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/TwoMethodClashController.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ControllerTestData/TwoMethodNoClashController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/TwoMethodNoClashController.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ControllerTestData/TwoMethodNoClashController.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/TwoMethodNoClashController.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ControllerTestData/TwoMethodsDifferentRootsController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/TwoMethodsDifferentRootsController.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ControllerTestData/TwoMethodsDifferentRootsController.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/TwoMethodsDifferentRootsController.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/DirectiveMethodTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveMethodTemplateTests.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/DirectiveMethodTemplateTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveMethodTemplateTests.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/DirectiveTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTemplateTests.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/DirectiveTemplateTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTemplateTests.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/DirectiveTestData/DirectiveWithArgs.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/DirectiveWithArgs.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/DirectiveTestData/DirectiveWithArgs.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/DirectiveWithArgs.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/DirectiveTestData/DirectiveWithDeclaredDirectiveOnMethod.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/DirectiveWithDeclaredDirectiveOnMethod.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/DirectiveTestData/DirectiveWithDeclaredDirectiveOnMethod.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/DirectiveWithDeclaredDirectiveOnMethod.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/DirectiveTestData/DirectiveWithDeclaredDirectives.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/DirectiveWithDeclaredDirectives.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/DirectiveTestData/DirectiveWithDeclaredDirectives.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/DirectiveWithDeclaredDirectives.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/DirectiveTestData/DirectiveWithRequirements.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/DirectiveWithRequirements.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/DirectiveTestData/DirectiveWithRequirements.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/DirectiveWithRequirements.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/DirectiveTestData/DirectiveWithSecurityRequirements.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/DirectiveWithSecurityRequirements.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/DirectiveTestData/DirectiveWithSecurityRequirements.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/DirectiveWithSecurityRequirements.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/DirectiveTestData/MismatchedSignaturesDirective.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/MismatchedSignaturesDirective.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/DirectiveTestData/MismatchedSignaturesDirective.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/MismatchedSignaturesDirective.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/DirectiveTestData/NoLocationAttributeDirective.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/NoLocationAttributeDirective.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/DirectiveTestData/NoLocationAttributeDirective.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/NoLocationAttributeDirective.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/DirectiveTestData/NoLocationsDirective.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/NoLocationsDirective.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/DirectiveTestData/NoLocationsDirective.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/NoLocationsDirective.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/DirectiveTestData/OverlappingLocationsDirective.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/OverlappingLocationsDirective.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/DirectiveTestData/OverlappingLocationsDirective.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/OverlappingLocationsDirective.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/DirectiveTestData/RepeatableDirective.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/RepeatableDirective.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/DirectiveTestData/RepeatableDirective.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/RepeatableDirective.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/DirectiveTestData/SimpleExecutableDirective.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/SimpleExecutableDirective.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/DirectiveTestData/SimpleExecutableDirective.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/SimpleExecutableDirective.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/DirectiveTestData/TestDirectiveMethodTemplateContainer.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/TestDirectiveMethodTemplateContainer.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/DirectiveTestData/TestDirectiveMethodTemplateContainer.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/TestDirectiveMethodTemplateContainer.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/DirectiveTestData/TestDirectiveMethodTemplateContainer2.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/TestDirectiveMethodTemplateContainer2.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/DirectiveTestData/TestDirectiveMethodTemplateContainer2.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/TestDirectiveMethodTemplateContainer2.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumGraphTypeTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumGraphTypeTemplateTests.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumGraphTypeTemplateTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumGraphTypeTemplateTests.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumTestData/DeprecatedValueEnum.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/DeprecatedValueEnum.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumTestData/DeprecatedValueEnum.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/DeprecatedValueEnum.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumTestData/EnumCompleteByte.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumCompleteByte.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumTestData/EnumCompleteByte.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumCompleteByte.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumTestData/EnumCompleteSByte.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumCompleteSByte.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumTestData/EnumCompleteSByte.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumCompleteSByte.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumTestData/EnumFromByte.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumFromByte.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumTestData/EnumFromByte.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumFromByte.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumTestData/EnumFromInt.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumFromInt.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumTestData/EnumFromInt.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumFromInt.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumTestData/EnumFromLong.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumFromLong.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumTestData/EnumFromLong.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumFromLong.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumTestData/EnumFromSByte.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumFromSByte.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumTestData/EnumFromSByte.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumFromSByte.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumTestData/EnumFromShort.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumFromShort.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumTestData/EnumFromShort.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumFromShort.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumTestData/EnumFromUInt.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumFromUInt.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumTestData/EnumFromUInt.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumFromUInt.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumTestData/EnumFromULong.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumFromULong.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumTestData/EnumFromULong.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumFromULong.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumTestData/EnumFromUShort.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumFromUShort.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumTestData/EnumFromUShort.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumFromUShort.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumTestData/EnumWithDescription.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithDescription.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumTestData/EnumWithDescription.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithDescription.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumTestData/EnumWithDescriptions.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithDescriptions.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumTestData/EnumWithDescriptions.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithDescriptions.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumTestData/EnumWithDirective.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithDirective.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumTestData/EnumWithDirective.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithDirective.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumTestData/EnumWithDirectiveOnOption.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithDirectiveOnOption.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumTestData/EnumWithDirectiveOnOption.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithDirectiveOnOption.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumTestData/EnumWithDuplicateValues.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithDuplicateValues.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumTestData/EnumWithDuplicateValues.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithDuplicateValues.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumTestData/EnumWithDuplicateValuesFromComposite.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithDuplicateValuesFromComposite.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumTestData/EnumWithDuplicateValuesFromComposite.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithDuplicateValuesFromComposite.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumTestData/EnumWithGraphName.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithGraphName.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumTestData/EnumWithGraphName.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithGraphName.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumTestData/EnumWithInvalidValueName.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithInvalidValueName.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumTestData/EnumWithInvalidValueName.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithInvalidValueName.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumTestData/EnumWithValueWithGraphName.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithValueWithGraphName.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumTestData/EnumWithValueWithGraphName.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithValueWithGraphName.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumTestData/EnumWithValueWithGraphNameButGraphNameIsInvalid.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithValueWithGraphNameButGraphNameIsInvalid.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumTestData/EnumWithValueWithGraphNameButGraphNameIsInvalid.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithValueWithGraphNameButGraphNameIsInvalid.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumTestData/SimpleEnum.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/SimpleEnum.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/EnumTestData/SimpleEnum.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/SimpleEnum.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ExtensionMethodTestData/ExtensionMethodController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ExtensionMethodTestData/ExtensionMethodController.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ExtensionMethodTestData/ExtensionMethodController.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ExtensionMethodTestData/ExtensionMethodController.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/GraphTypeNameTestData/AttributedClass.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNameTestData/AttributedClass.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/GraphTypeNameTestData/AttributedClass.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNameTestData/AttributedClass.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/GraphTypeNameTestData/AttributedClassInvalidName.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNameTestData/AttributedClassInvalidName.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/GraphTypeNameTestData/AttributedClassInvalidName.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNameTestData/AttributedClassInvalidName.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/GraphTypeNameTestData/EnumNameTest.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNameTestData/EnumNameTest.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/GraphTypeNameTestData/EnumNameTest.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNameTestData/EnumNameTest.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/GraphTypeNameTestData/EnumNameTestWithTypeName.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNameTestData/EnumNameTestWithTypeName.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/GraphTypeNameTestData/EnumNameTestWithTypeName.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNameTestData/EnumNameTestWithTypeName.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/GraphTypeNameTestData/GenericClass.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNameTestData/GenericClass.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/GraphTypeNameTestData/GenericClass.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNameTestData/GenericClass.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/GraphTypeNameTestData/GenericClassWithAttribute.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNameTestData/GenericClassWithAttribute.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/GraphTypeNameTestData/GenericClassWithAttribute.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNameTestData/GenericClassWithAttribute.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/GraphTypeNameTestData/NoAttributeClass.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNameTestData/NoAttributeClass.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/GraphTypeNameTestData/NoAttributeClass.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNameTestData/NoAttributeClass.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/GraphTypeNameTestData/NoAttributeClassForNewName.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNameTestData/NoAttributeClassForNewName.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/GraphTypeNameTestData/NoAttributeClassForNewName.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNameTestData/NoAttributeClassForNewName.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/GraphTypeNamesTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNamesTests.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/GraphTypeNamesTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNamesTests.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/InputGraphFieldTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InputGraphFieldTemplateTests.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/InputGraphFieldTemplateTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InputGraphFieldTemplateTests.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/InputObjectTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InputObjectTemplateTests.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/InputObjectTemplateTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InputObjectTemplateTests.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/InterfaceGraphTypeTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceGraphTypeTemplateTests.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/InterfaceGraphTypeTemplateTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceGraphTypeTemplateTests.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/InterfaceTestData/IInterface1.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/IInterface1.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/InterfaceTestData/IInterface1.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/IInterface1.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/InterfaceTestData/IInterface2.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/IInterface2.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/InterfaceTestData/IInterface2.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/IInterface2.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/InterfaceTestData/IInterface3.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/IInterface3.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/InterfaceTestData/IInterface3.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/IInterface3.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/InterfaceTestData/IInterfaceWithDirective.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/IInterfaceWithDirective.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/InterfaceTestData/IInterfaceWithDirective.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/IInterfaceWithDirective.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/InterfaceTestData/INestedInterface1.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/INestedInterface1.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/InterfaceTestData/INestedInterface1.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/INestedInterface1.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/InterfaceTestData/INestedInterface2.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/INestedInterface2.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/InterfaceTestData/INestedInterface2.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/INestedInterface2.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/InterfaceTestData/ISimpleInterface.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/ISimpleInterface.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/InterfaceTestData/ISimpleInterface.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/ISimpleInterface.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/InterfaceTestData/ITestableInterfaceImplementation.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/ITestableInterfaceImplementation.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/InterfaceTestData/ITestableInterfaceImplementation.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/ITestableInterfaceImplementation.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/InterfaceTestData/InterfaceThatInheritsDeclaredMethodField.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/InterfaceThatInheritsDeclaredMethodField.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/InterfaceTestData/InterfaceThatInheritsDeclaredMethodField.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/InterfaceThatInheritsDeclaredMethodField.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/InterfaceTestData/InterfaceThatInheritsUndeclaredMethodField.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/InterfaceThatInheritsUndeclaredMethodField.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/InterfaceTestData/InterfaceThatInheritsUndeclaredMethodField.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/InterfaceThatInheritsUndeclaredMethodField.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/InterfaceTestData/InterfaceWithDeclaredInterfaceField.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/InterfaceWithDeclaredInterfaceField.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/InterfaceTestData/InterfaceWithDeclaredInterfaceField.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/InterfaceWithDeclaredInterfaceField.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/InterfaceTestData/InterfaceWithUndeclaredInterfaceField.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/InterfaceWithUndeclaredInterfaceField.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/InterfaceTestData/InterfaceWithUndeclaredInterfaceField.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/InterfaceWithUndeclaredInterfaceField.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/MethodGraphFieldTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/MethodGraphFieldTemplateTests.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/MethodGraphFieldTemplateTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/MethodGraphFieldTemplateTests.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/MethodTestData/ArrayMethodObject.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/MethodTestData/ArrayMethodObject.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/MethodTestData/ArrayMethodObject.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/MethodTestData/ArrayMethodObject.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/MethodTestData/MethodClass.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/MethodTestData/MethodClass.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/MethodTestData/MethodClass.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/MethodTestData/MethodClass.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/MethodTestData/MethodClassWithDirective.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/MethodTestData/MethodClassWithDirective.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/MethodTestData/MethodClassWithDirective.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/MethodTestData/MethodClassWithDirective.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectGraphTypeTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectGraphTypeTemplateTests.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectGraphTypeTemplateTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectGraphTypeTemplateTests.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/CustomStruct.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/CustomStruct.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/CustomStruct.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/CustomStruct.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/DescriptionObject.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/DescriptionObject.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/DescriptionObject.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/DescriptionObject.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/DescriptionStruct.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/DescriptionStruct.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/DescriptionStruct.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/DescriptionStruct.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/ForceSkippedStruct.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ForceSkippedStruct.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/ForceSkippedStruct.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ForceSkippedStruct.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/ForcedSkippedObject.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ForcedSkippedObject.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/ForcedSkippedObject.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ForcedSkippedObject.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/IInputObject.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/IInputObject.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/IInputObject.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/IInputObject.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/InputNameObject.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/InputNameObject.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/InputNameObject.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/InputNameObject.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/InputObjectIWithTaskProperty.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/InputObjectIWithTaskProperty.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/InputObjectIWithTaskProperty.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/InputObjectIWithTaskProperty.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/InputObjectWithDirective.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/InputObjectWithDirective.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/InputObjectWithDirective.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/InputObjectWithDirective.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/InputObjectWithDuplicateProperty.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/InputObjectWithDuplicateProperty.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/InputObjectWithDuplicateProperty.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/InputObjectWithDuplicateProperty.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/InputObjectWithGraphActionProperty.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/InputObjectWithGraphActionProperty.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/InputObjectWithGraphActionProperty.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/InputObjectWithGraphActionProperty.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/InputObjectWithInterfaceProperty.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/InputObjectWithInterfaceProperty.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/InputObjectWithInterfaceProperty.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/InputObjectWithInterfaceProperty.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/InputObjectWithUnionProxyProperty.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/InputObjectWithUnionProxyProperty.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/InputObjectWithUnionProxyProperty.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/InputObjectWithUnionProxyProperty.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/ObjectThatInheritsExplicitMethodField.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectThatInheritsExplicitMethodField.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/ObjectThatInheritsExplicitMethodField.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectThatInheritsExplicitMethodField.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/ObjectThatInheritsNonExplicitMethodField.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectThatInheritsNonExplicitMethodField.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/ObjectThatInheritsNonExplicitMethodField.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectThatInheritsNonExplicitMethodField.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/ObjectWithDeconstructor.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectWithDeconstructor.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/ObjectWithDeconstructor.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectWithDeconstructor.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/ObjectWithDirective.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectWithDirective.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/ObjectWithDirective.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectWithDirective.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/ObjectWithExplicitMethodField.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectWithExplicitMethodField.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/ObjectWithExplicitMethodField.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectWithExplicitMethodField.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/ObjectWithInvalidNonDeclaredMethods.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectWithInvalidNonDeclaredMethods.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/ObjectWithInvalidNonDeclaredMethods.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectWithInvalidNonDeclaredMethods.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/ObjectWithMutationOperation.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectWithMutationOperation.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/ObjectWithMutationOperation.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectWithMutationOperation.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/ObjectWithNoSetters.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectWithNoSetters.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/ObjectWithNoSetters.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectWithNoSetters.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/ObjectWithNonExplicitMethodField.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectWithNonExplicitMethodField.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/ObjectWithNonExplicitMethodField.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectWithNonExplicitMethodField.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/ObjectWithStatics.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectWithStatics.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/ObjectWithStatics.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectWithStatics.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/OneMarkedMethod.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/OneMarkedMethod.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/OneMarkedMethod.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/OneMarkedMethod.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/OneMarkedProperty.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/OneMarkedProperty.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/OneMarkedProperty.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/OneMarkedProperty.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/RequiredConstructor.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/RequiredConstructor.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/RequiredConstructor.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/RequiredConstructor.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/SimpleObjectNoMethods.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/SimpleObjectNoMethods.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/SimpleObjectNoMethods.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/SimpleObjectNoMethods.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/SimpleObjectScalar.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/SimpleObjectScalar.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/SimpleObjectScalar.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/SimpleObjectScalar.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/SimpleScalarObjectGraphType.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/SimpleScalarObjectGraphType.cs similarity index 91% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/SimpleScalarObjectGraphType.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/SimpleScalarObjectGraphType.cs index 867c2aa79..bf23db971 100644 --- a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/SimpleScalarObjectGraphType.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/SimpleScalarObjectGraphType.cs @@ -23,8 +23,6 @@ public SimpleScalarObjectGraphType() public override ScalarValueType ValueType => ScalarValueType.String; - public override TypeCollection OtherKnownTypes { get; } = new TypeCollection(); - public override object Resolve(ReadOnlySpan data) { return null; diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/SimpleScalarStruct.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/SimpleScalarStruct.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/SimpleScalarStruct.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/SimpleScalarStruct.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/SimpleScalarStructGraphType.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/SimpleScalarStructGraphType.cs similarity index 91% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/SimpleScalarStructGraphType.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/SimpleScalarStructGraphType.cs index 67735a6d9..162f7e03b 100644 --- a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/SimpleScalarStructGraphType.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/SimpleScalarStructGraphType.cs @@ -23,8 +23,6 @@ public SimpleScalarStructGraphType() public override ScalarValueType ValueType => ScalarValueType.String; - public override TypeCollection OtherKnownTypes { get; } = new TypeCollection(); - public override object Resolve(ReadOnlySpan data) { return null; diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/SimpleStructNoMethods.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/SimpleStructNoMethods.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/SimpleStructNoMethods.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/SimpleStructNoMethods.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/StructOneMarkedMethod.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/StructOneMarkedMethod.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/StructOneMarkedMethod.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/StructOneMarkedMethod.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/StructOneMarkedProperty.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/StructOneMarkedProperty.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/StructOneMarkedProperty.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/StructOneMarkedProperty.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/StructTwoMethodsWithSameName.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/StructTwoMethodsWithSameName.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/StructTwoMethodsWithSameName.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/StructTwoMethodsWithSameName.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/StructTwoMethodsWithSameNameWithAttributeDiff.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/StructTwoMethodsWithSameNameWithAttributeDiff.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/StructTwoMethodsWithSameNameWithAttributeDiff.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/StructTwoMethodsWithSameNameWithAttributeDiff.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/StructWithInvalidNonDeclaredMethods.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/StructWithInvalidNonDeclaredMethods.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/StructWithInvalidNonDeclaredMethods.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/StructWithInvalidNonDeclaredMethods.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/StructWithNoSetters.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/StructWithNoSetters.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/StructWithNoSetters.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/StructWithNoSetters.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/TwoMethodsWithSameName.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/TwoMethodsWithSameName.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/TwoMethodsWithSameName.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/TwoMethodsWithSameName.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/TwoMethodsWithSameNameWithAttributeDiff.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/TwoMethodsWithSameNameWithAttributeDiff.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/TwoMethodsWithSameNameWithAttributeDiff.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/TwoMethodsWithSameNameWithAttributeDiff.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/TypeWithArrayProperty.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/TypeWithArrayProperty.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/TypeWithArrayProperty.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/TypeWithArrayProperty.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ParameterTestData/ParameterTestClass.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ParameterTestData/ParameterTestClass.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ParameterTestData/ParameterTestClass.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ParameterTestData/ParameterTestClass.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/PropertyGraphFieldTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyGraphFieldTemplateTests.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/PropertyGraphFieldTemplateTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyGraphFieldTemplateTests.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/PropertyTestData/ArrayKeyValuePairObject.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyTestData/ArrayKeyValuePairObject.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/PropertyTestData/ArrayKeyValuePairObject.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyTestData/ArrayKeyValuePairObject.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/PropertyTestData/ArrayPropertyObject.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyTestData/ArrayPropertyObject.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/PropertyTestData/ArrayPropertyObject.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyTestData/ArrayPropertyObject.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/PropertyTestData/IPropInterface.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyTestData/IPropInterface.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/PropertyTestData/IPropInterface.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyTestData/IPropInterface.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/PropertyTestData/NoGetterOnProperty.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyTestData/NoGetterOnProperty.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/PropertyTestData/NoGetterOnProperty.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyTestData/NoGetterOnProperty.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/PropertyTestData/PropAuthorizeAttribute.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyTestData/PropAuthorizeAttribute.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/PropertyTestData/PropAuthorizeAttribute.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyTestData/PropAuthorizeAttribute.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/PropertyTestData/PropertyClassWithDirective.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyTestData/PropertyClassWithDirective.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/PropertyTestData/PropertyClassWithDirective.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyTestData/PropertyClassWithDirective.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/PropertyTestData/PropertyProxy.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyTestData/PropertyProxy.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/PropertyTestData/PropertyProxy.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyTestData/PropertyProxy.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/PropertyTestData/SimplePropertyObject.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyTestData/SimplePropertyObject.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/PropertyTestData/SimplePropertyObject.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyTestData/SimplePropertyObject.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/TypeExtensionFieldTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/TypeExtensionFieldTemplateTests.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/TypeExtensionFieldTemplateTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/TypeExtensionFieldTemplateTests.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/GraphValidationTestData/ControllerWithNoSecurityPolicies.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GraphValidationTestData/ControllerWithNoSecurityPolicies.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/GraphValidationTestData/ControllerWithNoSecurityPolicies.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/GraphValidationTestData/ControllerWithNoSecurityPolicies.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/GraphValidationTestData/ControllerWithSecurityPolicies.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GraphValidationTestData/ControllerWithSecurityPolicies.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/GraphValidationTestData/ControllerWithSecurityPolicies.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/GraphValidationTestData/ControllerWithSecurityPolicies.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/GraphValidationTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GraphValidationTests.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/GraphValidationTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/GraphValidationTests.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/IntrospectionDefaultValueTestData/TestEnum.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/IntrospectionDefaultValueTestData/TestEnum.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/IntrospectionDefaultValueTestData/TestEnum.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/IntrospectionDefaultValueTestData/TestEnum.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/IntrospectionDefaultValueTestData/TestEnumNoDefaultValue.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/IntrospectionDefaultValueTestData/TestEnumNoDefaultValue.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/IntrospectionDefaultValueTestData/TestEnumNoDefaultValue.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/IntrospectionDefaultValueTestData/TestEnumNoDefaultValue.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/IntrospectionDefaultValueTestData/TestEnumNotIncludedDefault.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/IntrospectionDefaultValueTestData/TestEnumNotIncludedDefault.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/IntrospectionDefaultValueTestData/TestEnumNotIncludedDefault.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/IntrospectionDefaultValueTestData/TestEnumNotIncludedDefault.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/IntrospectionDefaultValueValidationTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/IntrospectionDefaultValueValidationTests.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/IntrospectionDefaultValueValidationTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/IntrospectionDefaultValueValidationTests.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTypeCollectionInterefaceImplementationTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTypeCollectionInterefaceImplementationTests.cs index 0d4b251d1..096859a8d 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTypeCollectionInterefaceImplementationTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTypeCollectionInterefaceImplementationTests.cs @@ -22,6 +22,8 @@ namespace GraphQL.AspNet.Tests.Schemas using GraphQL.AspNet.Schemas.Generation; using GraphQL.AspNet.Internal.TypeTemplates; using GraphQL.AspNet.Schemas; + using Microsoft.AspNetCore.Hosting.Server; + using GraphQL.AspNet.Tests.CommonHelpers; [TestFixture] [FixtureLifeCycle(LifeCycle.InstancePerTestCase)] @@ -100,8 +102,7 @@ private IGraphType MakeGraphType(Type type, TypeKind kind) { var testServer = new TestServerBuilder().Build(); - var factory = new DefaultGraphQLTypeMakerFactory(); - factory.Initialize(testServer.Schema); + var factory = testServer.CreateMakerFactory(); var template = factory.MakeTemplate(type, kind); var maker = factory.CreateTypeMaker(type, kind); @@ -112,8 +113,7 @@ private IGraphField MakeGraphField(IGraphFieldTemplate fieldTemplate) { var testServer = new TestServerBuilder().Build(); - var factory = new DefaultGraphQLTypeMakerFactory(); - factory.Initialize(testServer.Schema); + var factory = testServer.CreateMakerFactory(); var maker = factory.CreateFieldMaker(); return maker.CreateField(fieldTemplate).Field; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTypeCollectionTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTypeCollectionTests.cs index 7def0c236..b3145c9d8 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTypeCollectionTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTypeCollectionTests.cs @@ -29,6 +29,7 @@ namespace GraphQL.AspNet.Tests.Schemas using GraphQL.AspNet.Internal.TypeTemplates; using Microsoft.AspNetCore.Hosting.Server; using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Tests.CommonHelpers; [TestFixture] public class SchemaTypeCollectionTests @@ -43,8 +44,8 @@ public enum RandomEnum private IGraphType MakeGraphType(Type type, TypeKind kind) { var testServer = new TestServerBuilder().Build(); - var factory = new DefaultGraphQLTypeMakerFactory(); - factory.Initialize(testServer.Schema); + + var factory = testServer.CreateMakerFactory(); var template = GraphQLTemplateHelper.CreateGraphTypeTemplate(type, kind); return factory.CreateTypeMaker(type, kind).CreateGraphType(template).GraphType; @@ -53,9 +54,8 @@ private IGraphType MakeGraphType(Type type, TypeKind kind) private IGraphField MakeGraphField(IGraphFieldTemplate fieldTemplate) { var testServer = new TestServerBuilder().Build(); - var factory = new DefaultGraphQLTypeMakerFactory(); - factory.Initialize(testServer.Schema); + var factory = testServer.CreateMakerFactory(); var maker = new GraphFieldMaker(testServer.Schema, factory); return maker.CreateField(fieldTemplate).Field; diff --git a/src/unit-tests/graphql-aspnet-tests/ServerExtensions/MutlipartRequests/FileUploadScalarGraphTypeTests.cs b/src/unit-tests/graphql-aspnet-tests/ServerExtensions/MutlipartRequests/FileUploadScalarGraphTypeTests.cs index ea6b0de89..992515d0b 100644 --- a/src/unit-tests/graphql-aspnet-tests/ServerExtensions/MutlipartRequests/FileUploadScalarGraphTypeTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/ServerExtensions/MutlipartRequests/FileUploadScalarGraphTypeTests.cs @@ -82,12 +82,5 @@ public void ScalarValueType_IsAnyType() Assert.IsTrue(scalar.ValueType.HasFlag(ScalarValueType.String)); Assert.IsTrue(scalar.ValueType.HasFlag(ScalarValueType.Boolean)); } - - [Test] - public void Scalar_HasNoOtherKnownTypes() - { - var scalar = new FileUploadScalarGraphType(); - Assert.AreEqual(0, scalar.OtherKnownTypes.Count); - } } } \ No newline at end of file From f3f3fac1604b82617169b33e8830a34e4f7d65b5 Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Wed, 12 Jul 2023 17:49:40 -0700 Subject: [PATCH 31/63] WIP, internal file reorg, namespace fixes --- .../SubscriptionEnabledGraphFieldMaker.cs | 1 + ...ptionControllerActionGraphFieldTemplate.cs | 1 + .../SubscriptionGraphArgumentTemplate.cs | 1 + .../SubscriptionGraphControllerTemplate.cs | 1 + .../Common/JsonNodes/JsonNodeException.cs | 2 +- .../Common/JsonNodes/JsonNodeExtensions.cs | 2 +- ...hemaItemDefinitionExtensions_Directives.cs | 2 +- ...chemaItemDefinitionExtensions_Internals.cs | 4 +- ...chemaItemDefinitionExtensions_Mutations.cs | 2 +- ...eSchemaItemDefinitionExtensions_Queries.cs | 2 +- ...ItemDefinitionExtensions_ResolvedFields.cs | 2 +- ...ItemDefinitionExtensions_TypeExtensions.cs | 2 +- ...aItemDefinitionExtensions_VirtualFields.cs | 4 +- .../Configuration/ResolverIsolationOptions.cs | 2 +- .../ResolverIsolationOptionsExtensions.cs | 2 +- .../Configuration/SchemaOptions.cs | 2 +- .../Engine/DefaultGraphQLSchemaFactory.cs | 4 +- ...DefaultGraphQLSchemaFactory_Controllers.cs | 2 +- .../DefaultGraphQLSchemaFactory_Directives.cs | 1 - .../DefaultGraphQLSchemaFactory_GraphTypes.cs | 4 +- ...GraphQLSchemaFactory_RuntimeDefinitions.cs | 4 +- .../DefaultGraphQLSchemaFactory_Validation.cs | 1 - .../Engine/DefaultGraphQLTypeMakerFactory.cs | 3 +- ...yOperationComplexityCalculator{TSchema}.cs | 2 +- .../Execution/BatchResultProcessor.cs | 2 +- .../Execution/ExecutionExtensionMethods.cs | 2 +- .../FieldResolution/FieldDataItem.cs | 1 - .../Execution/FieldSourceCollection.cs | 2 +- src/graphql-aspnet/Execution/ListMangler.cs | 2 +- .../InputArguments/ArgumentGenerator.cs | 2 +- .../Resolvers/EnumInputValueResolver.cs | 4 +- .../Resolvers/EnumLeafValueResolver.cs | 2 +- .../Resolvers/ExtendedGraphFieldResolver.cs | 2 +- .../Resolvers/FieldResolverMetaData.cs | 2 +- .../FieldResolverParameterMetaData.cs | 3 +- ...ieldResolverParameterMetaDataCollection.cs | 2 +- ...tionGraphFieldResolver{TSource,TReturn}.cs | 3 +- .../GraphControllerActionResolver.cs | 2 +- .../GraphControllerActionResolverBase.cs | 2 +- .../GraphControllerRouteFieldResolver.cs | 3 +- .../Resolvers/GraphDirectiveActionResolver.cs | 3 +- .../Resolvers/InputObjectValueResolver.cs | 2 +- .../Resolvers/InputValueResolverBase.cs | 2 +- .../InputValueResolverMethodGenerator.cs | 2 +- .../InternalFieldResolverMetaData.cs | 3 +- .../Schema_TypeGraphFieldResolver.cs | 3 +- .../Type_EnumValuesGraphFieldResolver.cs | 3 +- .../Type_TypeGraphFieldResolver.cs | 3 +- .../Resolvers/ListInputValueResolver.cs | 2 +- .../ObjectMethodGraphFieldResolver.cs | 2 +- .../ObjectPropertyGraphFieldResolver.cs | 2 +- .../Resolvers/ScalarInputValueResolver.cs | 2 +- .../Rule_5_7_ArgumentsMustbeValid.cs | 2 +- .../Rule_6_4_3_SchemaValueCompletion.cs | 1 - .../Rule_6_4_3_ServerValueCompletion.cs | 2 +- .../Variables/ResolvedVariableGenerator.cs | 2 +- .../Interfaces/Engine/IGraphArgumentMaker.cs | 2 +- .../Interfaces/Engine/IGraphFieldMaker.cs | 2 +- .../Engine/IGraphQLSchemaFactory{TSchema}.cs | 2 +- .../Interfaces/Engine/IGraphTypeMaker.cs | 2 +- .../IQueryExecutionPlanCacheProvider.cs | 3 +- .../Interfaces/Engine/IUnionGraphTypeMaker.cs | 2 +- .../Internal/IGraphControllerTemplate.cs | 2 +- .../Internal/IGraphFieldTemplateBase.cs | 2 +- .../Internal/IGraphItemDependencies.cs | 2 +- .../Internal/ISchemaItemTemplate.cs | 2 +- .../Interfaces/Schema/IGraphField.cs | 2 +- .../IGraphQLResolvableSchemaItemDefinition.cs | 2 +- ...GraphQLRuntimeDirectiveActionDefinition.cs | 2 +- .../IGraphQLRuntimeFieldDefinition.cs | 6 +- .../IGraphQLRuntimeResolvedFieldDefinition.cs | 7 +- .../IGraphQLRuntimeSchemaItemDefinition.cs | 2 +- .../IGraphQLRuntimeTypeExtensionDefinition.cs | 2 +- .../ProcessChildFieldsMiddleware.cs | 1 - .../ValidateFieldExecutionMiddleware.cs | 2 +- .../TypeMakers/DependentTypeCollection.cs | 4 +- .../Generation/TypeMakers/DirectiveMaker.cs | 2 - .../TypeMakers/EnumGraphTypeMaker.cs | 2 - .../FieldContainerGraphTypeMakerBase.cs | 2 +- .../TypeMakers/GraphArgumentCreationResult.cs | 2 +- .../TypeMakers/GraphArgumentMaker.cs | 2 - .../TypeMakers/GraphFieldCreationResult.cs | 2 +- .../Generation/TypeMakers/GraphFieldMaker.cs | 4 +- .../TypeMakers/GraphMakerExtensions.cs | 2 +- .../TypeMakers/GraphTypeCreationResult.cs | 2 +- .../TypeMakers/InputObjectGraphTypeMaker.cs | 2 - .../TypeMakers/InterfaceGraphTypeMaker.cs | 3 - .../TypeMakers/ObjectGraphTypeMaker.cs | 3 - .../TypeMakers/ScalarGraphTypeMaker.cs | 1 - .../TypeMakers/UnionGraphTypeMaker.cs | 4 +- .../TypeTemplates/AppliedDirectiveTemplate.cs | 2 +- .../ApplyDirectiveAttributeExtensions.cs | 2 +- .../ControllerActionGraphFieldTemplate.cs | 4 +- .../Generation/TypeTemplates/DependentType.cs | 2 +- .../TypeTemplates/EnumGraphTypeTemplate.cs | 2 +- .../TypeTemplates/EnumValueTemplate.cs | 2 +- .../TypeTemplates/GraphArgumentTemplate.cs | 5 +- .../TypeTemplates/GraphControllerTemplate.cs | 2 +- .../GraphDirectiveMethodTemplate.cs | 5 +- .../GraphDirectiveMethodTemplateContainer.cs | 2 +- .../TypeTemplates/GraphDirectiveTemplate.cs | 4 +- .../TypeTemplates/GraphFieldTemplateBase.cs | 5 +- .../TypeTemplates/GraphFieldTemplateSource.cs | 2 +- .../GraphTypeExtensionFieldTemplate.cs | 5 +- .../TypeTemplates/GraphTypeTemplateBase.cs | 2 +- .../TypeTemplates/GraphTypeTemplates.cs | 1 - .../TypeTemplates/InputGraphFieldTemplate.cs | 3 +- .../InputObjectGraphTypeTemplate.cs | 2 +- .../InterfaceGraphTypeTemplate.cs | 2 +- .../TypeTemplates/MemberInfoProvider.cs | 2 +- .../TypeTemplates/MethodGraphFieldTemplate.cs | 3 +- .../MethodGraphFieldTemplateBase.cs | 6 +- .../NonLeafGraphTypeTemplateBase.cs | 3 +- .../TypeTemplates/ObjectGraphTypeTemplate.cs | 2 +- .../PropertyGraphFieldTemplate.cs | 6 +- .../RuntimeGraphControllerTemplate.cs | 4 +- .../RuntimeSchemaItemAttributeProvider.cs | 4 +- .../TypeTemplates/ScalarGraphTypeTemplate.cs | 5 +- .../TypeTemplates/SchemaItemTemplateBase.cs | 2 +- .../TypeTemplates/UnionGraphTypeTemplate.cs | 3 +- src/graphql-aspnet/Schemas/GraphSchema.cs | 1 - .../Schemas/GraphTypeExpression_Statics.cs | 1 - src/graphql-aspnet/Schemas/GraphTypeNames.cs | 3 +- src/graphql-aspnet/Schemas/GraphValidation.cs | 7 +- .../BaseRuntimeControllerActionDefinition.cs | 4 +- .../RuntimeDirectiveActionDefinition.cs | 4 +- .../RuntimeResolvedFieldDefinition.cs | 5 +- .../RuntimeTypeExtensionDefinition.cs | 5 +- .../RuntimeVirtualFieldTemplate.cs | 4 +- .../Schemas/SchemaLanguageGenerator.cs | 1 - .../Structural/GraphFieldCollection.cs | 3 +- .../Schemas/TypeSystem/EnumGraphType.cs | 2 +- .../ExtendableGraphTypeExtensions.cs | 3 +- .../Schemas/TypeSystem/GlobalTypes.cs | 4 +- .../Schemas/TypeSystem/GraphUnionProxy.cs | 1 - .../Fields/Introspection_SchemaField.cs | 2 +- .../Fields/Introspection_TypeGraphField.cs | 2 +- .../Fields/Introspection_TypeNameMetaField.cs | 2 +- .../Introspection/Introspection_TypeType.cs | 2 +- .../Model/IntrospectedInputValueType.cs | 1 - .../Schemas/TypeSystem/MethodGraphField.cs | 3 +- .../TypeSystem/Scalars/ScalarGraphTypeBase.cs | 2 +- .../TypeCollections/ConcreteTypeCollection.cs | 1 - .../TypeCollections/SchemaTypeCollection.cs | 1 - .../Schemas/TypeSystem/VirtualGraphField.cs | 4 +- .../Web/MultiPartHttpFormPayloadParser.cs | 1 + .../MultiPartHttpFormPayloadParser_Json.cs | 1 + .../Controllers/ControllerExtensionTests.cs | 2 +- .../ControllerTestData/InvokableController.cs | 2 +- .../Engine/DefaultEventRouterTests.cs | 2 +- .../DirectiveTestController.cs | 2 +- .../SubQueryController.cs | 2 +- ...ubscriptionQueryExecutionDirectiveTests.cs | 2 +- .../SubscriptionQueryExecutionTests.cs | 2 +- .../OneMethodSubscriptionController.cs | 2 +- .../SubscriptionMethodController.cs | 2 +- .../SimpleSubscriptionController.cs | 2 +- .../Templating/GraphActionTemplateTests.cs | 2 +- .../GraphControllerTemplateTests.cs | 1 + ...RaisedSubscriptionEventsMiddlewareTests.cs | 2 +- .../Mocks/SubscriptionContextBuilder.cs | 1 + .../DuplicateEventNameController.cs | 2 +- .../SchemaTestData/OneFieldMapController.cs | 2 +- .../OneFieldMapWithEventNameController.cs | 2 +- .../SchemaTestData/SimpleMethodController.cs | 2 +- .../ClientSubscriptionTestController.cs | 2 +- .../GraphqlTransportWs/GqltwsClientAsserts.cs | 2 +- .../GqltwsClientProxyTests.cs | 2 +- .../GqltwsConverterTests.cs | 2 +- .../GqltwsDataMessageController.cs | 2 +- .../GqltwsResponseMessageConverter.cs | 2 +- .../GqltwsSubscriptionController.cs | 2 +- .../GraphqlWsLegacyClientAsserts.cs | 2 +- .../GraphqlWsLegacyClientProxyTests.cs | 2 +- .../GraphqlWsLegacyConverterTests.cs | 2 +- .../GraphqlWsLegacyDataMessageController.cs | 2 +- ...GraphqlWsLegacyResponseMessageConverter.cs | 2 +- .../GraphqlWsLegacySubscriptionController.cs | 2 +- .../GraphQLTemplateHelper.cs | 2 +- .../QueryContextBuilder.cs | 3 +- .../SingleMethodGraphControllerTemplate.cs | 2 +- .../TestServer.cs | 1 - .../CommonHelpers/CommonAssertions.cs | 5 +- .../InheritedTwoPropertyObject.cs | 2 +- .../JsonComparing/JsonComparer.cs | 3 +- .../JsonComparing/JsonComparrisonResult.cs | 4 +- .../CommonHelpers/TwoPropertyGenericObject.cs | 2 +- .../CommonHelpers/TwoPropertyObject.cs | 6 +- .../CommonHelpers/TwoPropertyObjectV2.cs | 2 +- .../CommonHelpers/TwoPropertyObjectV3.cs | 4 +- .../CommonHelpers/TwoPropertyStruct.cs | 4 +- .../CommonHelpers/Utf8JsonReaderExtensions.cs | 2 +- .../Interfaces/ISinglePropertyObject.cs | 2 +- .../ApplyDirectiveAttributeExtensionTests.cs | 4 +- .../ApplyDirectiveTestObject.cs | 2 +- .../Common/Extensions/LinqExtensionTests.cs | 3 +- .../Common/Extensions/TypeExtensionTests.cs | 2 +- .../Common/JsonNodeTests.cs | 3 +- .../CommonHelpers/CompletePropertyObject.cs | 2 +- .../CommonHelpers/JsonComparingTests.cs | 2 +- .../ConfigurationFieldNamingTests.cs | 2 +- .../Configuration/DirectiveApplicatorTests.cs | 2 +- .../SchemaItemFilterExtensionTests.cs | 2 +- .../SchemaOptionsAddTypesTests.cs | 2 +- .../SchemaOptionsApplyDirectiveTests.cs | 2 +- .../SchemaTypeToRegisterTests.cs | 2 +- .../Configuration/ServiceToRegisterTests.cs | 3 +- .../Templates/MappedDirectiveTemplateTests.cs | 2 +- .../Templates/MappedMutationTemplateTests.cs | 2 +- .../Templates/MappedQueryGroupTests.cs | 1 - .../Templates/MappedQueryTemplateTests.cs | 2 +- .../MappedTypeExtensionTemplateTests.cs | 4 +- .../Templates/ResolvedFieldTemplateTests.cs | 3 +- .../ActionResults/ActionResultTests.cs | 1 - .../ActionableController.cs | 2 +- .../Controllers/GraphControllerTests.cs | 2 +- .../Controllers/GraphQueryProcessorTests.cs | 2 +- .../Directives/DeprecatedDirectiveTests.cs | 2 +- .../SimpleExecutionController.cs | 2 +- .../DocumentAlterationDirectiveTests.cs | 2 +- .../Directives/IncludeDirectiveTests.cs | 2 +- .../IncludeSkipCombinedDirectiveTests.cs | 2 +- .../Directives/RepeatableDirectiveTests.cs | 2 +- .../Directives/SkipDirectiveTests.cs | 2 +- .../Directives/SpecifiedByDirectiveTests.cs | 2 +- .../CustomObjectWithCustomScalarArgument.cs | 2 +- .../CustomObjectWithCustomScalarField.cs | 2 +- .../TwoPropertyObjectAsScalar.cs | 2 +- .../Engine/DefaultSchemaFactoryTests.cs | 3 +- .../TypeMakers/DirectiveTypeMakerTests.cs | 4 +- .../TypeMakers/EnumGraphTypeMakerTests.cs | 1 - .../TypeMakers/FieldMaker_InputFieldTests.cs | 3 +- .../FieldMaker_StandardFieldTests.cs | 9 +- .../TypeMakers/GraphTypeMakerTestBase.cs | 2 +- .../InputObjectGraphTypeMakerTests.cs | 6 +- .../TypeMakers/ObjectGraphTypeMakerTests.cs | 2 +- .../TypeMakers/ScalarGraphTypeMakerTests.cs | 3 +- .../TestData/CustomScalarWithDirectives.cs | 2 +- .../TypeMakers/TestData/InputTestObject.cs | 2 +- .../InputTestObjectWithDefaultFieldValues.cs | 2 +- .../TestData/MultiMethodDirective.cs | 2 +- .../TestData/RepeatableDirective.cs | 2 +- .../TypeMakers/TestData/TypeCreationItem.cs | 2 +- .../UnionProxyWithInvalidDirective.cs | 2 +- .../TestData/UnionTestController.cs | 2 +- .../Engine/TypeMakers/UnionTypeMakerTests.cs | 1 - .../Execution/ApolloTracingTests.cs | 2 +- .../Execution/AuthenticatedUserTests.cs | 2 +- .../DefaultGraphResponseWriterTests.cs | 2 +- .../Execution/ExecutionDirectiveTests.cs | 2 +- .../Execution/FieldSourceCollectionTests.cs | 2 +- .../Execution/FragmentExecutionTests.cs | 2 +- .../Execution/GeneralExecutionTests_NET60.cs | 2 +- .../GeneralQueryExecutionRuntimeFieldTests.cs | 2 +- .../Execution/GeneralQueryExecutionTests.cs | 2 +- .../Execution/GeneralQueryExecutionTests2.cs | 2 +- .../Execution/InheritanceExecutionTests.cs | 2 +- .../Execution/InterfaceExecutionTests.cs | 2 +- .../Execution/IntrospectionTests.cs | 2 +- .../Execution/ListManglerTests.cs | 2 +- .../InputController.cs | 2 +- .../QueryPlans/ArgumentGeneratorTests.cs | 2 +- .../ExecutionPlanGenerationTests.cs | 5 +- .../SimplePlanGenerationController.cs | 2 +- .../Resolvers/InputResolverGeneratorTests.cs | 8 +- .../InputValueNodeTestData/CoffeeCan.cs | 2 +- .../InputValueNodeTestData/Telephone.cs | 2 +- .../Resolvers/ObjectMethodResolverTests.cs | 8 +- .../Resolvers/ObjectPropertyResolverTests.cs | 8 +- .../IResolverInterface.cs | 2 +- .../ValueResolversTestData/ResolvableEnum.cs | 2 +- .../ValueResolversTestData/ResolverObject.cs | 2 +- .../ValueResolversTestData/ResolverStructA.cs | 2 +- .../ValueResolversTestData/ResolverStructB.cs | 2 +- .../Execution/Response/ResponseWriterTests.cs | 2 +- .../Response/ResponseWriterTests_NET60.cs | 2 +- .../DirectiveValidationRuleCheckTests.cs | 2 +- .../RulesEngine/EnsureValidationRuleUrls.cs | 1 + .../Execution/RuntimeTypeInferenceTests.cs | 2 +- .../BatchInterfaceController.cs | 3 +- .../BatchObjectController.cs | 2 +- .../BatchStructController.cs | 2 +- .../UniontTestObject.cs | 2 +- .../ExecutionDirectiveTestController.cs | 2 +- .../AdjustBatchDataDirective.cs | 2 +- .../DirectiveTestController.cs | 2 +- .../ArrayAsEnumerableController.cs | 2 +- .../ArrayOnReturnObjectMethodController.cs | 2 +- .../ArrayOnReturnObjectPropertyController.cs | 2 +- .../ArrayThroughArrayDeclarationController.cs | 2 +- ...hroughGraphActionAsEnumerableController.cs | 2 +- .../ExternalItemCollectionController.cs | 2 +- .../InputObjectArrayController.cs | 2 +- .../NullableFieldArgumentTestController.cs | 2 +- .../SimpleExecutionController.cs | 2 +- ...eExtensionOnTwoPropertyObjectController.cs | 2 +- .../ExecutionPlanTestData/UnionController.cs | 2 +- .../InputValueController.cs | 2 +- .../NullableVariableObjectController.cs | 2 +- ...NotRequiredNonNullableNotSetClassObject.cs | 2 +- .../NotRequiredNotSetClassObject.cs | 2 +- .../NotRequiredSetClassObject.cs | 2 +- .../RequiredClassObject.cs | 2 +- .../StructNotRequiredNotSetClassObject.cs | 2 +- .../StructNotRequiredSetClassObject.cs | 2 +- .../StructRequiredClassObject.cs | 2 +- .../ARepeatableDirective.cs | 2 +- .../IntrospectionTestData/InputTestObject.cs | 2 +- .../IntrospectableObject.cs | 2 +- .../NonRepeatableDirective.cs | 2 +- .../TypeExtensionDescriptionController.cs | 2 +- .../MarkedUnion.cs | 2 +- .../PersonOrTeacher.cs | 2 +- .../SchoolController.cs | 2 +- .../Execution/TypeExtensionExecutionTests.cs | 2 +- .../TypeSystemDirectiveInvocationTests.cs | 2 +- .../Execution/UnionTypeExecutionTests.cs | 2 +- .../Execution/VariableExecutionTests.cs | 2 +- .../Execution/VariableKitchenSinkTests.cs | 2 +- .../Integration/MusicIndustryTests.cs | 2 +- .../PipelineTestDirective.cs | 2 +- .../DirectivePipelineMiddlewareTests.cs | 2 +- .../SimpleExecutionController.cs | 2 +- .../Schemas/DefaultTypeTests.cs | 1 + .../ActionMethodTemplateTests.cs | 43 +++++---- .../ActionMethodWithDirectiveController.cs | 4 +- .../ActionResultReturnTypeController.cs | 5 +- .../ArrayInputMethodController.cs | 4 +- .../ComplexityValueCheckController.cs | 2 +- .../ActionTestData/ContainerController.cs | 4 +- .../ActionTestData/CustomNamedItem.cs | 2 +- .../ActionTestData/ITestItem.cs | 2 +- .../ActionTestData/IUnionTestDataItem.cs | 2 +- .../InterfaceReturnTypeController.cs | 4 +- .../ActionTestData/OneMethodController.cs | 4 +- .../ActionTestData/ScalarInUnionController.cs | 2 +- .../ActionTestData/TestItemA.cs | 2 +- .../ActionTestData/TestItemB.cs | 2 +- .../ActionTestData/UnionDataA.cs | 2 +- .../ActionTestData/UnionDataB.cs | 2 +- .../ActionTestData/UnionTestController.cs | 5 +- .../ActionTestData/UnionTestProxy.cs | 2 +- .../AppliedDirectiveTemplateTests.cs | 6 +- .../{Templating => }/ArgumentTemplateTests.cs | 28 +++--- .../ControllerTemplateTests.cs | 40 ++++----- .../ArrayInputParamController.cs | 4 +- .../ArrayReturnController.cs | 2 +- .../ControllerWithDirective.cs | 4 +- .../ControllerWithStaticMethod.cs | 2 +- .../DeclaredGraphRootController.cs | 2 +- .../InvalidRouteController.cs | 2 +- .../NoInheritanceFromBaseController.cs | 2 +- .../NoRouteSpecifierController.cs | 2 +- .../ControllerTestData/OneMethodController.cs | 4 +- .../SimpleControllerNoMethods.cs | 2 +- .../TwoMethodClashController.cs | 4 +- .../TwoMethodNoClashController.cs | 4 +- .../TwoMethodsDifferentRootsController.cs | 4 +- .../DirectiveMethodTemplateTests.cs | 10 +-- .../DirectiveTemplateTests.cs | 23 ++--- .../DirectiveTestData/DirectiveWithArgs.cs | 2 +- .../DirectiveWithDeclaredDirectiveOnMethod.cs | 2 +- .../DirectiveWithDeclaredDirectives.cs | 2 +- .../DirectiveWithRequirements.cs | 4 +- .../DirectiveWithSecurityRequirements.cs | 2 +- .../MismatchedSignaturesDirective.cs | 2 +- .../NoLocationAttributeDirective.cs | 2 +- .../DirectiveTestData/NoLocationsDirective.cs | 2 +- .../OverlappingLocationsDirective.cs | 2 +- .../DirectiveTestData/RepeatableDirective.cs | 2 +- .../SimpleExecutableDirective.cs | 2 +- .../TestDirectiveMethodTemplateContainer.cs | 2 +- .../TestDirectiveMethodTemplateContainer2.cs | 4 +- .../EnumGraphTypeTemplateTests.cs | 90 ++++++++++--------- .../EnumTestData/DeprecatedValueEnum.cs | 2 +- .../EnumTestData/EnumCompleteByte.cs | 2 +- .../EnumTestData/EnumCompleteSByte.cs | 2 +- .../EnumTestData/EnumFromByte.cs | 2 +- .../EnumTestData/EnumFromInt.cs | 2 +- .../EnumTestData/EnumFromLong.cs | 2 +- .../EnumTestData/EnumFromSByte.cs | 2 +- .../EnumTestData/EnumFromShort.cs | 2 +- .../EnumTestData/EnumFromUInt.cs | 2 +- .../EnumTestData/EnumFromULong.cs | 2 +- .../EnumTestData/EnumFromUShort.cs | 2 +- .../EnumTestData/EnumWithDescription.cs | 2 +- .../EnumTestData/EnumWithDescriptions.cs | 2 +- .../EnumTestData/EnumWithDirective.cs | 4 +- .../EnumTestData/EnumWithDirectiveOnOption.cs | 4 +- .../EnumTestData/EnumWithDuplicateValues.cs | 2 +- .../EnumWithDuplicateValuesFromComposite.cs | 2 +- .../EnumTestData/EnumWithGraphName.cs | 2 +- .../EnumTestData/EnumWithInvalidValueName.cs | 2 +- .../EnumWithValueWithGraphName.cs | 2 +- ...ValueWithGraphNameButGraphNameIsInvalid.cs | 2 +- .../EnumTestData/SimpleEnum.cs | 2 +- .../ExtensionMethodController.cs | 6 +- .../GraphTypeNameTestData/AttributedClass.cs | 2 +- .../AttributedClassInvalidName.cs | 2 +- .../GraphTypeNameTestData/EnumNameTest.cs | 2 +- .../EnumNameTestWithTypeName.cs | 2 +- .../GraphTypeNameTestData/GenericClass.cs | 2 +- .../GenericClassWithAttribute.cs | 2 +- .../GraphTypeNameTestData/NoAttributeClass.cs | 2 +- .../NoAttributeClassForNewName.cs | 2 +- .../{Templating => }/GraphTypeNamesTests.cs | 7 +- .../InputGraphFieldTemplateTests.cs | 16 ++-- .../InputObjectTemplateTests.cs | 11 +-- .../InterfaceGraphTypeTemplateTests.cs | 45 +++++----- .../InterfaceTestData/IInterface1.cs | 2 +- .../InterfaceTestData/IInterface2.cs | 2 +- .../InterfaceTestData/IInterface3.cs | 2 +- .../IInterfaceWithDirective.cs | 4 +- .../InterfaceTestData/INestedInterface1.cs | 2 +- .../InterfaceTestData/INestedInterface2.cs | 2 +- .../InterfaceTestData/ISimpleInterface.cs | 2 +- .../ITestableInterfaceImplementation.cs | 2 +- ...nterfaceThatInheritsDeclaredMethodField.cs | 2 +- ...erfaceThatInheritsUndeclaredMethodField.cs | 4 +- .../InterfaceWithDeclaredInterfaceField.cs | 2 +- .../InterfaceWithUndeclaredInterfaceField.cs | 2 +- .../MethodGraphFieldTemplateTests.cs | 23 ++--- .../MethodTestData/ArrayMethodObject.cs | 4 +- .../MethodTestData/MethodClass.cs | 8 +- .../MethodClassWithDirective.cs | 4 +- .../ObjectGraphTypeTemplateTests.cs | 13 ++- .../ObjectTypeTests/CustomStruct.cs | 2 +- .../ObjectTypeTests/DescriptionObject.cs | 2 +- .../ObjectTypeTests/DescriptionStruct.cs | 2 +- .../ObjectTypeTests/ForceSkippedStruct.cs | 2 +- .../ObjectTypeTests/ForcedSkippedObject.cs | 2 +- .../ObjectTypeTests/IInputObject.cs | 2 +- .../ObjectTypeTests/InputNameObject.cs | 2 +- .../InputObjectIWithTaskProperty.cs | 2 +- .../InputObjectWithDirective.cs | 4 +- .../InputObjectWithDuplicateProperty.cs | 2 +- .../InputObjectWithGraphActionProperty.cs | 2 +- .../InputObjectWithInterfaceProperty.cs | 2 +- .../InputObjectWithUnionProxyProperty.cs | 2 +- .../ObjectThatInheritsExplicitMethodField.cs | 2 +- ...bjectThatInheritsNonExplicitMethodField.cs | 4 +- .../ObjectWithDeconstructor.cs | 4 +- .../ObjectTypeTests/ObjectWithDirective.cs | 4 +- .../ObjectWithExplicitMethodField.cs | 2 +- .../ObjectWithInvalidNonDeclaredMethods.cs | 2 +- .../ObjectWithMutationOperation.cs | 2 +- .../ObjectTypeTests/ObjectWithNoSetters.cs | 2 +- .../ObjectWithNonExplicitMethodField.cs | 4 +- .../ObjectTypeTests/ObjectWithStatics.cs | 2 +- .../ObjectTypeTests/OneMarkedMethod.cs | 2 +- .../ObjectTypeTests/OneMarkedProperty.cs | 2 +- .../ObjectTypeTests/RequiredConstructor.cs | 2 +- .../ObjectTypeTests/SimpleObjectNoMethods.cs | 2 +- .../ObjectTypeTests/SimpleObjectScalar.cs | 2 +- .../SimpleScalarObjectGraphType.cs | 3 +- .../ObjectTypeTests/SimpleScalarStruct.cs | 2 +- .../SimpleScalarStructGraphType.cs | 3 +- .../ObjectTypeTests/SimpleStructNoMethods.cs | 2 +- .../ObjectTypeTests/StructOneMarkedMethod.cs | 2 +- .../StructOneMarkedProperty.cs | 2 +- .../StructTwoMethodsWithSameName.cs | 2 +- ...TwoMethodsWithSameNameWithAttributeDiff.cs | 2 +- .../StructWithInvalidNonDeclaredMethods.cs | 2 +- .../ObjectTypeTests/StructWithNoSetters.cs | 2 +- .../ObjectTypeTests/TwoMethodsWithSameName.cs | 2 +- ...TwoMethodsWithSameNameWithAttributeDiff.cs | 2 +- .../ObjectTypeTests/TypeWithArrayProperty.cs | 4 +- .../ParameterTestData/ParameterTestClass.cs | 5 +- .../PropertyGraphFieldTemplateTests.cs | 19 ++-- .../ArrayKeyValuePairObject.cs | 2 +- .../PropertyTestData/ArrayPropertyObject.cs | 4 +- .../PropertyTestData/IPropInterface.cs | 2 +- .../PropertyTestData/NoGetterOnProperty.cs | 2 +- .../PropAuthorizeAttribute.cs | 2 +- .../PropertyClassWithDirective.cs | 4 +- .../PropertyTestData/PropertyProxy.cs | 2 +- .../PropertyTestData/SimplePropertyObject.cs | 3 +- .../TypeExtensionFieldTemplateTests.cs | 14 +-- .../Schemas/GraphFieldCloningTests.cs | 9 +- .../Schemas/GraphTypeExpressionTests.cs | 2 +- .../ControllerWithNoSecurityPolicies.cs | 2 +- .../ControllerWithSecurityPolicies.cs | 2 +- .../Schemas/GraphValidationTests.cs | 15 ++-- .../TestEnum.cs | 2 +- .../TestEnumNoDefaultValue.cs | 2 +- .../TestEnumNotIncludedDefault.cs | 2 +- ...ntrospectionDefaultValueValidationTests.cs | 6 +- .../Schemas/SchemaLanguageGeneratorTests.cs | 2 +- .../ArrayInputAndReturnController.cs | 2 +- .../SchemaTestData/ArrayMethodObject.cs | 2 +- .../ArrayObjectInputController.cs | 2 +- .../SchemaTestData/ArrayPropertyObject.cs | 2 +- .../SchemaTestData/ArrayReturnController.cs | 2 +- .../ArrayReturnDeclarationController.cs | 2 +- ...ollerWithDirectAndIndirectTypeExtension.cs | 3 +- .../SchemaTestData/DictionaryMethodObject.cs | 2 +- .../GenericObjectTypeWithGraphTypeName.cs | 2 +- .../SchemaTestData/KitchenSinkController.cs | 2 +- .../NestedQueryMethodController.cs | 2 +- .../PocoWithInterfaceArgument.cs | 1 + .../SchemaTestData/SimpleMethodController.cs | 2 +- .../SchemaTestData/TypeExtensionController.cs | 2 +- ...CollectionInterefaceImplementationTests.cs | 3 +- .../Schemas/SchemaTypeCollectionTests.cs | 6 +- .../MappedQuery_AuthorizationTests.cs | 2 +- .../Security/PerFieldAuthorizationTests.cs | 2 +- .../Security/PerRequestAuthorizationTests.cs | 2 +- .../PerFieldCounterController.cs | 2 +- .../PerRequestCounterController.cs | 2 +- .../SecurtyGroupData/SecuredController.cs | 2 +- .../BatchGraphQLHttpResponseWriterTests.cs | 2 +- .../MutlipartRequests/ConfigTests.cs | 1 + ...ltipartRequestGraphQLHttpProcessorTests.cs | 2 +- .../TestData/MultiPartFileController.cs | 2 +- .../Web/CancelTokenTests.cs | 2 +- .../Web/GetRequestTests.cs | 2 +- .../ExternalItemCollectionController.cs | 2 +- .../WebTestData/ItemInjectorHttpProcessor.cs | 2 +- 518 files changed, 780 insertions(+), 849 deletions(-) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ActionMethodTemplateTests.cs (87%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ActionTestData/ActionMethodWithDirectiveController.cs (78%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ActionTestData/ActionResultReturnTypeController.cs (90%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ActionTestData/ArrayInputMethodController.cs (80%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ActionTestData/ComplexityValueCheckController.cs (87%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ActionTestData/ContainerController.cs (87%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ActionTestData/CustomNamedItem.cs (83%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ActionTestData/ITestItem.cs (81%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ActionTestData/IUnionTestDataItem.cs (83%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ActionTestData/InterfaceReturnTypeController.cs (91%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ActionTestData/OneMethodController.cs (83%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ActionTestData/ScalarInUnionController.cs (88%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ActionTestData/TestItemA.cs (82%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ActionTestData/TestItemB.cs (82%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ActionTestData/UnionDataA.cs (84%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ActionTestData/UnionDataB.cs (84%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ActionTestData/UnionTestController.cs (92%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ActionTestData/UnionTestProxy.cs (91%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/AppliedDirectiveTemplateTests.cs (93%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ArgumentTemplateTests.cs (90%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ControllerTemplateTests.cs (65%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ControllerTestData/ArrayInputParamController.cs (80%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ControllerTestData/ArrayReturnController.cs (86%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ControllerTestData/ControllerWithDirective.cs (74%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ControllerTestData/ControllerWithStaticMethod.cs (88%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ControllerTestData/DeclaredGraphRootController.cs (84%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ControllerTestData/InvalidRouteController.cs (86%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ControllerTestData/NoInheritanceFromBaseController.cs (85%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ControllerTestData/NoRouteSpecifierController.cs (82%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ControllerTestData/OneMethodController.cs (80%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ControllerTestData/SimpleControllerNoMethods.cs (86%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ControllerTestData/TwoMethodClashController.cs (86%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ControllerTestData/TwoMethodNoClashController.cs (86%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ControllerTestData/TwoMethodsDifferentRootsController.cs (89%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/DirectiveMethodTemplateTests.cs (93%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/DirectiveTemplateTests.cs (80%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/DirectiveTestData/DirectiveWithArgs.cs (90%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/DirectiveTestData/DirectiveWithDeclaredDirectiveOnMethod.cs (91%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/DirectiveTestData/DirectiveWithDeclaredDirectives.cs (91%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/DirectiveTestData/DirectiveWithRequirements.cs (83%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/DirectiveTestData/DirectiveWithSecurityRequirements.cs (90%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/DirectiveTestData/MismatchedSignaturesDirective.cs (91%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/DirectiveTestData/NoLocationAttributeDirective.cs (87%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/DirectiveTestData/NoLocationsDirective.cs (87%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/DirectiveTestData/OverlappingLocationsDirective.cs (90%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/DirectiveTestData/RepeatableDirective.cs (89%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/DirectiveTestData/SimpleExecutableDirective.cs (91%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/DirectiveTestData/TestDirectiveMethodTemplateContainer.cs (91%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/DirectiveTestData/TestDirectiveMethodTemplateContainer2.cs (90%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/EnumGraphTypeTemplateTests.cs (55%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/EnumTestData/DeprecatedValueEnum.cs (84%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/EnumTestData/EnumCompleteByte.cs (99%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/EnumTestData/EnumCompleteSByte.cs (99%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/EnumTestData/EnumFromByte.cs (83%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/EnumTestData/EnumFromInt.cs (85%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/EnumTestData/EnumFromLong.cs (85%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/EnumTestData/EnumFromSByte.cs (86%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/EnumTestData/EnumFromShort.cs (86%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/EnumTestData/EnumFromUInt.cs (83%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/EnumTestData/EnumFromULong.cs (83%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/EnumTestData/EnumFromUShort.cs (84%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/EnumTestData/EnumWithDescription.cs (84%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/EnumTestData/EnumWithDescriptions.cs (87%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/EnumTestData/EnumWithDirective.cs (73%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/EnumTestData/EnumWithDirectiveOnOption.cs (74%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/EnumTestData/EnumWithDuplicateValues.cs (84%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/EnumTestData/EnumWithDuplicateValuesFromComposite.cs (86%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/EnumTestData/EnumWithGraphName.cs (84%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/EnumTestData/EnumWithInvalidValueName.cs (82%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/EnumTestData/EnumWithValueWithGraphName.cs (85%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/EnumTestData/EnumWithValueWithGraphNameButGraphNameIsInvalid.cs (85%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/EnumTestData/SimpleEnum.cs (81%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ExtensionMethodTestData/ExtensionMethodController.cs (95%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/GraphTypeNameTestData/AttributedClass.cs (82%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/GraphTypeNameTestData/AttributedClassInvalidName.cs (82%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/GraphTypeNameTestData/EnumNameTest.cs (80%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/GraphTypeNameTestData/EnumNameTestWithTypeName.cs (83%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/GraphTypeNameTestData/GenericClass.cs (82%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/GraphTypeNameTestData/GenericClassWithAttribute.cs (85%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/GraphTypeNameTestData/NoAttributeClass.cs (79%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/GraphTypeNameTestData/NoAttributeClassForNewName.cs (79%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/GraphTypeNamesTests.cs (95%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/InputGraphFieldTemplateTests.cs (91%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/InputObjectTemplateTests.cs (96%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/InterfaceGraphTypeTemplateTests.cs (51%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/InterfaceTestData/IInterface1.cs (80%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/InterfaceTestData/IInterface2.cs (81%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/InterfaceTestData/IInterface3.cs (79%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/InterfaceTestData/IInterfaceWithDirective.cs (73%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/InterfaceTestData/INestedInterface1.cs (80%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/InterfaceTestData/INestedInterface2.cs (80%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/InterfaceTestData/ISimpleInterface.cs (85%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/InterfaceTestData/ITestableInterfaceImplementation.cs (81%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/InterfaceTestData/InterfaceThatInheritsDeclaredMethodField.cs (85%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/InterfaceTestData/InterfaceThatInheritsUndeclaredMethodField.cs (82%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/InterfaceTestData/InterfaceWithDeclaredInterfaceField.cs (86%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/InterfaceTestData/InterfaceWithUndeclaredInterfaceField.cs (84%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/MethodGraphFieldTemplateTests.cs (89%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/MethodTestData/ArrayMethodObject.cs (78%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/MethodTestData/MethodClass.cs (93%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/MethodTestData/MethodClassWithDirective.cs (75%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ObjectGraphTypeTemplateTests.cs (97%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ObjectTypeTests/CustomStruct.cs (81%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ObjectTypeTests/DescriptionObject.cs (83%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ObjectTypeTests/DescriptionStruct.cs (83%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ObjectTypeTests/ForceSkippedStruct.cs (85%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ObjectTypeTests/ForcedSkippedObject.cs (85%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ObjectTypeTests/IInputObject.cs (82%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ObjectTypeTests/InputNameObject.cs (83%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ObjectTypeTests/InputObjectIWithTaskProperty.cs (85%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ObjectTypeTests/InputObjectWithDirective.cs (74%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ObjectTypeTests/InputObjectWithDuplicateProperty.cs (85%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ObjectTypeTests/InputObjectWithGraphActionProperty.cs (85%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ObjectTypeTests/InputObjectWithInterfaceProperty.cs (84%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ObjectTypeTests/InputObjectWithUnionProxyProperty.cs (85%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ObjectTypeTests/ObjectThatInheritsExplicitMethodField.cs (86%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ObjectTypeTests/ObjectThatInheritsNonExplicitMethodField.cs (81%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ObjectTypeTests/ObjectWithDeconstructor.cs (82%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ObjectTypeTests/ObjectWithDirective.cs (74%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ObjectTypeTests/ObjectWithExplicitMethodField.cs (85%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ObjectTypeTests/ObjectWithInvalidNonDeclaredMethods.cs (92%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ObjectTypeTests/ObjectWithMutationOperation.cs (87%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ObjectTypeTests/ObjectWithNoSetters.cs (84%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ObjectTypeTests/ObjectWithNonExplicitMethodField.cs (80%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ObjectTypeTests/ObjectWithStatics.cs (90%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ObjectTypeTests/OneMarkedMethod.cs (87%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ObjectTypeTests/OneMarkedProperty.cs (85%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ObjectTypeTests/RequiredConstructor.cs (84%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ObjectTypeTests/SimpleObjectNoMethods.cs (80%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ObjectTypeTests/SimpleObjectScalar.cs (82%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ObjectTypeTests/SimpleScalarObjectGraphType.cs (90%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ObjectTypeTests/SimpleScalarStruct.cs (82%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ObjectTypeTests/SimpleScalarStructGraphType.cs (90%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ObjectTypeTests/SimpleStructNoMethods.cs (80%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ObjectTypeTests/StructOneMarkedMethod.cs (87%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ObjectTypeTests/StructOneMarkedProperty.cs (85%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ObjectTypeTests/StructTwoMethodsWithSameName.cs (88%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ObjectTypeTests/StructTwoMethodsWithSameNameWithAttributeDiff.cs (88%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ObjectTypeTests/StructWithInvalidNonDeclaredMethods.cs (92%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ObjectTypeTests/StructWithNoSetters.cs (84%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ObjectTypeTests/TwoMethodsWithSameName.cs (88%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ObjectTypeTests/TwoMethodsWithSameNameWithAttributeDiff.cs (88%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ObjectTypeTests/TypeWithArrayProperty.cs (74%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/ParameterTestData/ParameterTestClass.cs (93%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/PropertyGraphFieldTemplateTests.cs (93%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/PropertyTestData/ArrayKeyValuePairObject.cs (84%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/PropertyTestData/ArrayPropertyObject.cs (74%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/PropertyTestData/IPropInterface.cs (81%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/PropertyTestData/NoGetterOnProperty.cs (84%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/PropertyTestData/PropAuthorizeAttribute.cs (85%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/PropertyTestData/PropertyClassWithDirective.cs (74%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/PropertyTestData/PropertyProxy.cs (82%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/PropertyTestData/SimplePropertyObject.cs (94%) rename src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/{Templating => }/TypeExtensionFieldTemplateTests.cs (96%) diff --git a/src/graphql-aspnet-subscriptions/Engine/TypeMakers/SubscriptionEnabledGraphFieldMaker.cs b/src/graphql-aspnet-subscriptions/Engine/TypeMakers/SubscriptionEnabledGraphFieldMaker.cs index 8d11a3ee4..6f8fd48c7 100644 --- a/src/graphql-aspnet-subscriptions/Engine/TypeMakers/SubscriptionEnabledGraphFieldMaker.cs +++ b/src/graphql-aspnet-subscriptions/Engine/TypeMakers/SubscriptionEnabledGraphFieldMaker.cs @@ -25,6 +25,7 @@ namespace GraphQL.AspNet.Engine.TypeMakers using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Internal.TypeTemplates; using GraphQL.AspNet.Schemas.Generation.TypeMakers; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Security; diff --git a/src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionControllerActionGraphFieldTemplate.cs b/src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionControllerActionGraphFieldTemplate.cs index 0a339d107..6f0917402 100644 --- a/src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionControllerActionGraphFieldTemplate.cs +++ b/src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionControllerActionGraphFieldTemplate.cs @@ -18,6 +18,7 @@ namespace GraphQL.AspNet.Internal.TypeTemplates using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Interfaces.Internal; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.TypeSystem; /// diff --git a/src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionGraphArgumentTemplate.cs b/src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionGraphArgumentTemplate.cs index 05483c3bd..4d7f84d04 100644 --- a/src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionGraphArgumentTemplate.cs +++ b/src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionGraphArgumentTemplate.cs @@ -13,6 +13,7 @@ namespace GraphQL.AspNet.Internal.TypeTemplates using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Interfaces.Internal; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; /// /// An input argument template that is capable of parsing additional information diff --git a/src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionGraphControllerTemplate.cs b/src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionGraphControllerTemplate.cs index 9a020c225..26aeacc3a 100644 --- a/src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionGraphControllerTemplate.cs +++ b/src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionGraphControllerTemplate.cs @@ -16,6 +16,7 @@ namespace GraphQL.AspNet.Internal.TypeTemplates using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Interfaces.Internal; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; /// /// A set of parsed metadata, read from a declared , to properly diff --git a/src/graphql-aspnet/Common/JsonNodes/JsonNodeException.cs b/src/graphql-aspnet/Common/JsonNodes/JsonNodeException.cs index 94edc1fe3..25046d727 100644 --- a/src/graphql-aspnet/Common/JsonNodes/JsonNodeException.cs +++ b/src/graphql-aspnet/Common/JsonNodes/JsonNodeException.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Common.Extensions +namespace GraphQL.AspNet.Common.JsonNodes { using System; using System.Text.Json.Nodes; diff --git a/src/graphql-aspnet/Common/JsonNodes/JsonNodeExtensions.cs b/src/graphql-aspnet/Common/JsonNodes/JsonNodeExtensions.cs index bc0d74b20..be7adf724 100644 --- a/src/graphql-aspnet/Common/JsonNodes/JsonNodeExtensions.cs +++ b/src/graphql-aspnet/Common/JsonNodes/JsonNodeExtensions.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Common.Extensions +namespace GraphQL.AspNet.Common.JsonNodes { using System; using System.Collections.Generic; diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Directives.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Directives.cs index 67df2f90c..1a0d187fb 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Directives.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Directives.cs @@ -13,8 +13,8 @@ namespace GraphQL.AspNet.Configuration using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Common; using GraphQL.AspNet.Interfaces.Configuration; - using GraphQL.AspNet.Interfaces.Configuration.Templates; using GraphQL.AspNet.Interfaces.Controllers; + using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; using GraphQL.AspNet.Schemas.TypeSystem; using Microsoft.AspNetCore.Authorization; diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Internals.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Internals.cs index 3bf9a16e0..b436cf44a 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Internals.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Internals.cs @@ -11,11 +11,11 @@ namespace GraphQL.AspNet.Configuration { using System; using GraphQL.AspNet.Common; - using GraphQL.AspNet.Configuration.Templates; using GraphQL.AspNet.Execution; using GraphQL.AspNet.Execution.Parsing; using GraphQL.AspNet.Execution.Parsing.Lexing.Tokens; - using GraphQL.AspNet.Interfaces.Configuration.Templates; + using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; + using GraphQL.AspNet.Schemas.RuntimeSchemaItemDefinitions; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Mutations.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Mutations.cs index b9c76bf7d..289787be6 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Mutations.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Mutations.cs @@ -12,7 +12,7 @@ namespace GraphQL.AspNet.Configuration using System; using GraphQL.AspNet.Common; using GraphQL.AspNet.Interfaces.Configuration; - using GraphQL.AspNet.Interfaces.Configuration.Templates; + using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; using GraphQL.AspNet.Schemas.TypeSystem; /// diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Queries.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Queries.cs index caa50a341..9eadf56fe 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Queries.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Queries.cs @@ -12,7 +12,7 @@ namespace GraphQL.AspNet.Configuration using System; using GraphQL.AspNet.Common; using GraphQL.AspNet.Interfaces.Configuration; - using GraphQL.AspNet.Interfaces.Configuration.Templates; + using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; using GraphQL.AspNet.Schemas.TypeSystem; /// diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_ResolvedFields.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_ResolvedFields.cs index 13abff5b8..fe80302c3 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_ResolvedFields.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_ResolvedFields.cs @@ -12,8 +12,8 @@ namespace GraphQL.AspNet.Configuration using System; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Common; - using GraphQL.AspNet.Interfaces.Configuration.Templates; using GraphQL.AspNet.Interfaces.Controllers; + using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; using Microsoft.AspNetCore.Authorization; /// diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_TypeExtensions.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_TypeExtensions.cs index ecf6e844b..a5d06acb0 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_TypeExtensions.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_TypeExtensions.cs @@ -14,8 +14,8 @@ namespace GraphQL.AspNet.Configuration using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Common; using GraphQL.AspNet.Execution; - using GraphQL.AspNet.Interfaces.Configuration.Templates; using GraphQL.AspNet.Interfaces.Controllers; + using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; using Microsoft.AspNetCore.Authorization; /// diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_VirtualFields.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_VirtualFields.cs index 76affd06b..3ad888a7a 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_VirtualFields.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_VirtualFields.cs @@ -12,11 +12,11 @@ namespace GraphQL.AspNet.Configuration using System; using System.Runtime.CompilerServices; using GraphQL.AspNet.Common; - using GraphQL.AspNet.Configuration.Templates; using GraphQL.AspNet.Execution; using GraphQL.AspNet.Interfaces.Configuration; - using GraphQL.AspNet.Interfaces.Configuration.Templates; using GraphQL.AspNet.Interfaces.Controllers; + using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; + using GraphQL.AspNet.Schemas.RuntimeSchemaItemDefinitions; using Microsoft.AspNetCore.Authorization; /// diff --git a/src/graphql-aspnet/Configuration/ResolverIsolationOptions.cs b/src/graphql-aspnet/Configuration/ResolverIsolationOptions.cs index 56194be3a..d562ca47d 100644 --- a/src/graphql-aspnet/Configuration/ResolverIsolationOptions.cs +++ b/src/graphql-aspnet/Configuration/ResolverIsolationOptions.cs @@ -10,7 +10,7 @@ namespace GraphQL.AspNet.Configuration { using System; - using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; /// /// A set of options indicating the various resolver types that may be diff --git a/src/graphql-aspnet/Configuration/ResolverIsolationOptionsExtensions.cs b/src/graphql-aspnet/Configuration/ResolverIsolationOptionsExtensions.cs index c784645e0..c46d3a9c5 100644 --- a/src/graphql-aspnet/Configuration/ResolverIsolationOptionsExtensions.cs +++ b/src/graphql-aspnet/Configuration/ResolverIsolationOptionsExtensions.cs @@ -9,7 +9,7 @@ namespace GraphQL.AspNet.Configuration { - using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; /// /// Helper methods for working with . diff --git a/src/graphql-aspnet/Configuration/SchemaOptions.cs b/src/graphql-aspnet/Configuration/SchemaOptions.cs index e87b2e894..cd8962d01 100644 --- a/src/graphql-aspnet/Configuration/SchemaOptions.cs +++ b/src/graphql-aspnet/Configuration/SchemaOptions.cs @@ -19,8 +19,8 @@ namespace GraphQL.AspNet.Configuration using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Directives; using GraphQL.AspNet.Interfaces.Configuration; - using GraphQL.AspNet.Interfaces.Configuration.Templates; using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Schemas.TypeSystem; using Microsoft.Extensions.DependencyInjection; diff --git a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory.cs b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory.cs index 881436421..db9390468 100644 --- a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory.cs +++ b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory.cs @@ -16,11 +16,11 @@ namespace GraphQL.AspNet.Engine using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Configuration.Startup; using GraphQL.AspNet.Interfaces.Configuration; - using GraphQL.AspNet.Interfaces.Configuration.Templates; using GraphQL.AspNet.Interfaces.Engine; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; using GraphQL.AspNet.Schemas.Generation; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Schemas.TypeSystem.Scalars; using Microsoft.Extensions.DependencyInjection; diff --git a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Controllers.cs b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Controllers.cs index 4fd394969..137f006b1 100644 --- a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Controllers.cs +++ b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Controllers.cs @@ -16,7 +16,7 @@ namespace GraphQL.AspNet.Engine using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; diff --git a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Directives.cs b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Directives.cs index e04192fee..0035a512f 100644 --- a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Directives.cs +++ b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Directives.cs @@ -11,7 +11,6 @@ namespace GraphQL.AspNet.Engine { using System.Linq; using GraphQL.AspNet.Execution; - using GraphQL.AspNet.Internal.TypeTemplates; using GraphQL.AspNet.Schemas.TypeSystem; /// diff --git a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_GraphTypes.cs b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_GraphTypes.cs index 560dcd9c9..54dda36db 100644 --- a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_GraphTypes.cs +++ b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_GraphTypes.cs @@ -13,11 +13,11 @@ namespace GraphQL.AspNet.Engine using GraphQL.AspNet.Common; using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Engine.TypeMakers; using GraphQL.AspNet.Interfaces.Engine; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal; + using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Schemas.Generation.TypeMakers; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Schemas.TypeSystem.Scalars; using GraphQL.AspNet.ServerExtensions.MultipartRequests.Model; diff --git a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_RuntimeDefinitions.cs b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_RuntimeDefinitions.cs index 2043ff81b..e5a2fb0d1 100644 --- a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_RuntimeDefinitions.cs +++ b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_RuntimeDefinitions.cs @@ -10,8 +10,8 @@ namespace GraphQL.AspNet.Engine { using GraphQL.AspNet.Common; - using GraphQL.AspNet.Interfaces.Configuration.Templates; - using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; /// /// The default schema factory, capable of creating singleton instances of diff --git a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Validation.cs b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Validation.cs index c8a2def45..4ef73245b 100644 --- a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Validation.cs +++ b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Validation.cs @@ -12,7 +12,6 @@ namespace GraphQL.AspNet.Engine using System; using System.Collections.Generic; using GraphQL.AspNet.Configuration; - using GraphQL.AspNet.Interfaces.Configuration.Templates; using GraphQL.AspNet.Schemas.SchemaItemValidators; using GraphQL.AspNet.Schemas.TypeSystem; diff --git a/src/graphql-aspnet/Engine/DefaultGraphQLTypeMakerFactory.cs b/src/graphql-aspnet/Engine/DefaultGraphQLTypeMakerFactory.cs index 0a4172d90..d0f03f95b 100644 --- a/src/graphql-aspnet/Engine/DefaultGraphQLTypeMakerFactory.cs +++ b/src/graphql-aspnet/Engine/DefaultGraphQLTypeMakerFactory.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Schemas.Generation +namespace GraphQL.AspNet.Engine { using System; using GraphQL.AspNet.Common; @@ -19,7 +19,6 @@ namespace GraphQL.AspNet.Schemas.Generation using GraphQL.AspNet.Schemas.Generation.TypeMakers; using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Schemas.TypeSystem.Scalars; /// /// An object used during schema generation to organize and expose the various diff --git a/src/graphql-aspnet/Engine/DefaultQueryOperationComplexityCalculator{TSchema}.cs b/src/graphql-aspnet/Engine/DefaultQueryOperationComplexityCalculator{TSchema}.cs index 98ba2c495..dac61868f 100644 --- a/src/graphql-aspnet/Engine/DefaultQueryOperationComplexityCalculator{TSchema}.cs +++ b/src/graphql-aspnet/Engine/DefaultQueryOperationComplexityCalculator{TSchema}.cs @@ -14,7 +14,7 @@ namespace GraphQL.AspNet.Engine using GraphQL.AspNet.Interfaces.Engine; using GraphQL.AspNet.Interfaces.Execution; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.TypeSystem; /// diff --git a/src/graphql-aspnet/Execution/BatchResultProcessor.cs b/src/graphql-aspnet/Execution/BatchResultProcessor.cs index dc167d063..b3f713c1d 100644 --- a/src/graphql-aspnet/Execution/BatchResultProcessor.cs +++ b/src/graphql-aspnet/Execution/BatchResultProcessor.cs @@ -20,7 +20,7 @@ namespace GraphQL.AspNet.Execution using GraphQL.AspNet.Execution.FieldResolution; using GraphQL.AspNet.Interfaces.Execution; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal; + using GraphQL.AspNet.Schemas; /// /// A data processor that handles internal batch operations for items being processed through a graph query. diff --git a/src/graphql-aspnet/Execution/ExecutionExtensionMethods.cs b/src/graphql-aspnet/Execution/ExecutionExtensionMethods.cs index 769cddb80..13275bb4b 100644 --- a/src/graphql-aspnet/Execution/ExecutionExtensionMethods.cs +++ b/src/graphql-aspnet/Execution/ExecutionExtensionMethods.cs @@ -13,8 +13,8 @@ namespace GraphQL.AspNet.Execution using System.Threading; using System.Threading.Tasks; using GraphQL.AspNet.Execution.Contexts; + using GraphQL.AspNet.Execution.Resolvers; using GraphQL.AspNet.Interfaces.Execution; - using GraphQL.AspNet.Internal.Resolvers; using RouteConstants = GraphQL.AspNet.Constants.Routing; /// diff --git a/src/graphql-aspnet/Execution/FieldResolution/FieldDataItem.cs b/src/graphql-aspnet/Execution/FieldResolution/FieldDataItem.cs index 38e07f5bb..2ad5ca315 100644 --- a/src/graphql-aspnet/Execution/FieldResolution/FieldDataItem.cs +++ b/src/graphql-aspnet/Execution/FieldResolution/FieldDataItem.cs @@ -24,7 +24,6 @@ namespace GraphQL.AspNet.Execution.FieldResolution using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Internal; /// /// An ecapsulation of a piece of real data supplied to, or resolved from, a graph field. diff --git a/src/graphql-aspnet/Execution/FieldSourceCollection.cs b/src/graphql-aspnet/Execution/FieldSourceCollection.cs index f1ed3786b..44f8e8e7e 100644 --- a/src/graphql-aspnet/Execution/FieldSourceCollection.cs +++ b/src/graphql-aspnet/Execution/FieldSourceCollection.cs @@ -14,7 +14,7 @@ namespace GraphQL.AspNet.Execution using GraphQL.AspNet.Common; using GraphQL.AspNet.Execution.FieldResolution; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.Structural; /// diff --git a/src/graphql-aspnet/Execution/ListMangler.cs b/src/graphql-aspnet/Execution/ListMangler.cs index a95077718..39350dc44 100644 --- a/src/graphql-aspnet/Execution/ListMangler.cs +++ b/src/graphql-aspnet/Execution/ListMangler.cs @@ -18,7 +18,7 @@ namespace GraphQL.AspNet.Execution using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Common.Generics; using GraphQL.AspNet.Execution.Exceptions; - using GraphQL.AspNet.Internal; + using GraphQL.AspNet.Schemas; /* Motivation * ------------------------------ diff --git a/src/graphql-aspnet/Execution/QueryPlans/InputArguments/ArgumentGenerator.cs b/src/graphql-aspnet/Execution/QueryPlans/InputArguments/ArgumentGenerator.cs index 147b6e073..25b9e2fbd 100644 --- a/src/graphql-aspnet/Execution/QueryPlans/InputArguments/ArgumentGenerator.cs +++ b/src/graphql-aspnet/Execution/QueryPlans/InputArguments/ArgumentGenerator.cs @@ -15,10 +15,10 @@ namespace GraphQL.AspNet.Execution.QueryPlans.InputArguments using GraphQL.AspNet.Execution; using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Execution.QueryPlans.DocumentParts.SuppliedValues; + using GraphQL.AspNet.Execution.Resolvers; using GraphQL.AspNet.Execution.Source; using GraphQL.AspNet.Interfaces.Execution.QueryPlans.DocumentParts; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal.Resolvers; using GraphQL.AspNet.Schemas.TypeSystem; /// diff --git a/src/graphql-aspnet/Execution/Resolvers/EnumInputValueResolver.cs b/src/graphql-aspnet/Execution/Resolvers/EnumInputValueResolver.cs index 969557165..431565293 100644 --- a/src/graphql-aspnet/Execution/Resolvers/EnumInputValueResolver.cs +++ b/src/graphql-aspnet/Execution/Resolvers/EnumInputValueResolver.cs @@ -7,14 +7,12 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.Resolvers +namespace GraphQL.AspNet.Execution.Resolvers { using System; using GraphQL.AspNet.Common; using GraphQL.AspNet.Execution.Exceptions; - using GraphQL.AspNet.Execution.Source; using GraphQL.AspNet.Interfaces.Execution; - using GraphQL.AspNet.Interfaces.Execution.QueryPlans.DocumentParts; using GraphQL.AspNet.Interfaces.Execution.QueryPlans.Resolvables; using GraphQL.AspNet.Interfaces.Execution.Variables; using GraphQL.AspNet.Interfaces.Schema; diff --git a/src/graphql-aspnet/Execution/Resolvers/EnumLeafValueResolver.cs b/src/graphql-aspnet/Execution/Resolvers/EnumLeafValueResolver.cs index 1d910ecce..ccef9e797 100644 --- a/src/graphql-aspnet/Execution/Resolvers/EnumLeafValueResolver.cs +++ b/src/graphql-aspnet/Execution/Resolvers/EnumLeafValueResolver.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.Resolvers +namespace GraphQL.AspNet.Execution.Resolvers { using System; using GraphQL.AspNet.Common; diff --git a/src/graphql-aspnet/Execution/Resolvers/ExtendedGraphFieldResolver.cs b/src/graphql-aspnet/Execution/Resolvers/ExtendedGraphFieldResolver.cs index 2471e6b98..b85c32a7d 100644 --- a/src/graphql-aspnet/Execution/Resolvers/ExtendedGraphFieldResolver.cs +++ b/src/graphql-aspnet/Execution/Resolvers/ExtendedGraphFieldResolver.cs @@ -6,7 +6,7 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.Resolvers +namespace GraphQL.AspNet.Execution.Resolvers { using System; using System.Diagnostics; diff --git a/src/graphql-aspnet/Execution/Resolvers/FieldResolverMetaData.cs b/src/graphql-aspnet/Execution/Resolvers/FieldResolverMetaData.cs index 564a6969a..61d620d49 100644 --- a/src/graphql-aspnet/Execution/Resolvers/FieldResolverMetaData.cs +++ b/src/graphql-aspnet/Execution/Resolvers/FieldResolverMetaData.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.Resolvers +namespace GraphQL.AspNet.Execution.Resolvers { using System; using System.Diagnostics; diff --git a/src/graphql-aspnet/Execution/Resolvers/FieldResolverParameterMetaData.cs b/src/graphql-aspnet/Execution/Resolvers/FieldResolverParameterMetaData.cs index fe01700f8..537817371 100644 --- a/src/graphql-aspnet/Execution/Resolvers/FieldResolverParameterMetaData.cs +++ b/src/graphql-aspnet/Execution/Resolvers/FieldResolverParameterMetaData.cs @@ -7,13 +7,14 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.Resolvers +namespace GraphQL.AspNet.Execution.Resolvers { using System; using System.Diagnostics; using System.Reflection; using GraphQL.AspNet.Common; using GraphQL.AspNet.Interfaces.Execution; + using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Schemas.TypeSystem; /// diff --git a/src/graphql-aspnet/Execution/Resolvers/FieldResolverParameterMetaDataCollection.cs b/src/graphql-aspnet/Execution/Resolvers/FieldResolverParameterMetaDataCollection.cs index e3ba5509f..e93a65cd2 100644 --- a/src/graphql-aspnet/Execution/Resolvers/FieldResolverParameterMetaDataCollection.cs +++ b/src/graphql-aspnet/Execution/Resolvers/FieldResolverParameterMetaDataCollection.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.Resolvers +namespace GraphQL.AspNet.Execution.Resolvers { using System.Collections; using System.Collections.Generic; diff --git a/src/graphql-aspnet/Execution/Resolvers/FunctionGraphFieldResolver{TSource,TReturn}.cs b/src/graphql-aspnet/Execution/Resolvers/FunctionGraphFieldResolver{TSource,TReturn}.cs index 2079f2abc..5361130fd 100644 --- a/src/graphql-aspnet/Execution/Resolvers/FunctionGraphFieldResolver{TSource,TReturn}.cs +++ b/src/graphql-aspnet/Execution/Resolvers/FunctionGraphFieldResolver{TSource,TReturn}.cs @@ -7,10 +7,9 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.Resolvers +namespace GraphQL.AspNet.Execution.Resolvers { using System; - using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; using GraphQL.AspNet.Common; diff --git a/src/graphql-aspnet/Execution/Resolvers/GraphControllerActionResolver.cs b/src/graphql-aspnet/Execution/Resolvers/GraphControllerActionResolver.cs index b6276e959..2f7aefead 100644 --- a/src/graphql-aspnet/Execution/Resolvers/GraphControllerActionResolver.cs +++ b/src/graphql-aspnet/Execution/Resolvers/GraphControllerActionResolver.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.Resolvers +namespace GraphQL.AspNet.Execution.Resolvers { using System; using System.Diagnostics; diff --git a/src/graphql-aspnet/Execution/Resolvers/GraphControllerActionResolverBase.cs b/src/graphql-aspnet/Execution/Resolvers/GraphControllerActionResolverBase.cs index 6e8fc0883..059d4a1ed 100644 --- a/src/graphql-aspnet/Execution/Resolvers/GraphControllerActionResolverBase.cs +++ b/src/graphql-aspnet/Execution/Resolvers/GraphControllerActionResolverBase.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.Resolvers +namespace GraphQL.AspNet.Execution.Resolvers { using System.Diagnostics; using GraphQL.AspNet.Controllers.ActionResults; diff --git a/src/graphql-aspnet/Execution/Resolvers/GraphControllerRouteFieldResolver.cs b/src/graphql-aspnet/Execution/Resolvers/GraphControllerRouteFieldResolver.cs index 71036ddd4..bf418aa5d 100644 --- a/src/graphql-aspnet/Execution/Resolvers/GraphControllerRouteFieldResolver.cs +++ b/src/graphql-aspnet/Execution/Resolvers/GraphControllerRouteFieldResolver.cs @@ -7,9 +7,8 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.Resolvers +namespace GraphQL.AspNet.Execution.Resolvers { - using System; using System.Threading; using System.Threading.Tasks; using GraphQL.AspNet.Common; diff --git a/src/graphql-aspnet/Execution/Resolvers/GraphDirectiveActionResolver.cs b/src/graphql-aspnet/Execution/Resolvers/GraphDirectiveActionResolver.cs index 46b27a839..821b154bc 100644 --- a/src/graphql-aspnet/Execution/Resolvers/GraphDirectiveActionResolver.cs +++ b/src/graphql-aspnet/Execution/Resolvers/GraphDirectiveActionResolver.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.Resolvers +namespace GraphQL.AspNet.Execution.Resolvers { using System; using System.Collections.Generic; @@ -21,7 +21,6 @@ namespace GraphQL.AspNet.Internal.Resolvers using GraphQL.AspNet.Execution.Contexts; using GraphQL.AspNet.Interfaces.Controllers; using GraphQL.AspNet.Interfaces.Execution; - using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Schemas.TypeSystem; /// diff --git a/src/graphql-aspnet/Execution/Resolvers/InputObjectValueResolver.cs b/src/graphql-aspnet/Execution/Resolvers/InputObjectValueResolver.cs index 7534ff1b2..d792da957 100644 --- a/src/graphql-aspnet/Execution/Resolvers/InputObjectValueResolver.cs +++ b/src/graphql-aspnet/Execution/Resolvers/InputObjectValueResolver.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.Resolvers +namespace GraphQL.AspNet.Execution.Resolvers { using System; using System.Collections.Generic; diff --git a/src/graphql-aspnet/Execution/Resolvers/InputValueResolverBase.cs b/src/graphql-aspnet/Execution/Resolvers/InputValueResolverBase.cs index 327f9633c..ed7596c07 100644 --- a/src/graphql-aspnet/Execution/Resolvers/InputValueResolverBase.cs +++ b/src/graphql-aspnet/Execution/Resolvers/InputValueResolverBase.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.Resolvers +namespace GraphQL.AspNet.Execution.Resolvers { using GraphQL.AspNet.Interfaces.Execution.QueryPlans.Resolvables; using GraphQL.AspNet.Interfaces.Execution.Variables; diff --git a/src/graphql-aspnet/Execution/Resolvers/InputValueResolverMethodGenerator.cs b/src/graphql-aspnet/Execution/Resolvers/InputValueResolverMethodGenerator.cs index a84bc1a3b..40fa69d11 100644 --- a/src/graphql-aspnet/Execution/Resolvers/InputValueResolverMethodGenerator.cs +++ b/src/graphql-aspnet/Execution/Resolvers/InputValueResolverMethodGenerator.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.Resolvers +namespace GraphQL.AspNet.Execution.Resolvers { using System; using System.Collections.Generic; diff --git a/src/graphql-aspnet/Execution/Resolvers/InternalFieldResolverMetaData.cs b/src/graphql-aspnet/Execution/Resolvers/InternalFieldResolverMetaData.cs index cac314c97..da55ee2a7 100644 --- a/src/graphql-aspnet/Execution/Resolvers/InternalFieldResolverMetaData.cs +++ b/src/graphql-aspnet/Execution/Resolvers/InternalFieldResolverMetaData.cs @@ -7,10 +7,9 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.Resolvers +namespace GraphQL.AspNet.Execution.Resolvers { using System; - using System.Linq; using System.Reflection; using GraphQL.AspNet.Common; using GraphQL.AspNet.Common.Extensions; diff --git a/src/graphql-aspnet/Execution/Resolvers/Introspeection/Schema_TypeGraphFieldResolver.cs b/src/graphql-aspnet/Execution/Resolvers/Introspeection/Schema_TypeGraphFieldResolver.cs index 452bb3d81..d080e0d34 100644 --- a/src/graphql-aspnet/Execution/Resolvers/Introspeection/Schema_TypeGraphFieldResolver.cs +++ b/src/graphql-aspnet/Execution/Resolvers/Introspeection/Schema_TypeGraphFieldResolver.cs @@ -7,9 +7,8 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.Resolvers.Introspeection +namespace GraphQL.AspNet.Execution.Resolvers.Introspeection { - using System; using System.Threading; using System.Threading.Tasks; using GraphQL.AspNet.Common; diff --git a/src/graphql-aspnet/Execution/Resolvers/Introspeection/Type_EnumValuesGraphFieldResolver.cs b/src/graphql-aspnet/Execution/Resolvers/Introspeection/Type_EnumValuesGraphFieldResolver.cs index 5e0d86f9f..91d39b49e 100644 --- a/src/graphql-aspnet/Execution/Resolvers/Introspeection/Type_EnumValuesGraphFieldResolver.cs +++ b/src/graphql-aspnet/Execution/Resolvers/Introspeection/Type_EnumValuesGraphFieldResolver.cs @@ -7,9 +7,8 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.Resolvers.Introspeection +namespace GraphQL.AspNet.Execution.Resolvers.Introspeection { - using System; using System.Linq; using System.Threading; using System.Threading.Tasks; diff --git a/src/graphql-aspnet/Execution/Resolvers/Introspeection/Type_TypeGraphFieldResolver.cs b/src/graphql-aspnet/Execution/Resolvers/Introspeection/Type_TypeGraphFieldResolver.cs index 360b4d47c..9bbe91c61 100644 --- a/src/graphql-aspnet/Execution/Resolvers/Introspeection/Type_TypeGraphFieldResolver.cs +++ b/src/graphql-aspnet/Execution/Resolvers/Introspeection/Type_TypeGraphFieldResolver.cs @@ -7,9 +7,8 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.Resolvers.Introspeection +namespace GraphQL.AspNet.Execution.Resolvers.Introspeection { - using System; using System.Linq; using System.Threading; using System.Threading.Tasks; diff --git a/src/graphql-aspnet/Execution/Resolvers/ListInputValueResolver.cs b/src/graphql-aspnet/Execution/Resolvers/ListInputValueResolver.cs index 481a768b2..82cd369b3 100644 --- a/src/graphql-aspnet/Execution/Resolvers/ListInputValueResolver.cs +++ b/src/graphql-aspnet/Execution/Resolvers/ListInputValueResolver.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.Resolvers +namespace GraphQL.AspNet.Execution.Resolvers { using System; using System.Collections; diff --git a/src/graphql-aspnet/Execution/Resolvers/ObjectMethodGraphFieldResolver.cs b/src/graphql-aspnet/Execution/Resolvers/ObjectMethodGraphFieldResolver.cs index ca9ec4736..bf64469d6 100644 --- a/src/graphql-aspnet/Execution/Resolvers/ObjectMethodGraphFieldResolver.cs +++ b/src/graphql-aspnet/Execution/Resolvers/ObjectMethodGraphFieldResolver.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.Resolvers +namespace GraphQL.AspNet.Execution.Resolvers { using System; using System.Reflection; diff --git a/src/graphql-aspnet/Execution/Resolvers/ObjectPropertyGraphFieldResolver.cs b/src/graphql-aspnet/Execution/Resolvers/ObjectPropertyGraphFieldResolver.cs index 03f6e410c..020137ad7 100644 --- a/src/graphql-aspnet/Execution/Resolvers/ObjectPropertyGraphFieldResolver.cs +++ b/src/graphql-aspnet/Execution/Resolvers/ObjectPropertyGraphFieldResolver.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.Resolvers +namespace GraphQL.AspNet.Execution.Resolvers { using System; using System.Diagnostics; diff --git a/src/graphql-aspnet/Execution/Resolvers/ScalarInputValueResolver.cs b/src/graphql-aspnet/Execution/Resolvers/ScalarInputValueResolver.cs index c11a270c1..93027b54e 100644 --- a/src/graphql-aspnet/Execution/Resolvers/ScalarInputValueResolver.cs +++ b/src/graphql-aspnet/Execution/Resolvers/ScalarInputValueResolver.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.Resolvers +namespace GraphQL.AspNet.Execution.Resolvers { using GraphQL.AspNet.Common; using GraphQL.AspNet.Execution.Exceptions; diff --git a/src/graphql-aspnet/Execution/RulesEngine/RuleSets/DirectiveExecution/DirectiveValidation/Rule_5_7_ArgumentsMustbeValid.cs b/src/graphql-aspnet/Execution/RulesEngine/RuleSets/DirectiveExecution/DirectiveValidation/Rule_5_7_ArgumentsMustbeValid.cs index 39511d217..bd9920cdc 100644 --- a/src/graphql-aspnet/Execution/RulesEngine/RuleSets/DirectiveExecution/DirectiveValidation/Rule_5_7_ArgumentsMustbeValid.cs +++ b/src/graphql-aspnet/Execution/RulesEngine/RuleSets/DirectiveExecution/DirectiveValidation/Rule_5_7_ArgumentsMustbeValid.cs @@ -18,7 +18,7 @@ namespace GraphQL.AspNet.Execution.RulesEngine.RuleSets.DirectiveExecution.Direc using GraphQL.AspNet.Execution.QueryPlans.InputArguments; using GraphQL.AspNet.Execution.RulesEngine.RuleSets.DirectiveExecution.Common; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal; + using GraphQL.AspNet.Schemas; /// /// A rule to ensure that the location where the directive is being diff --git a/src/graphql-aspnet/Execution/RulesEngine/RuleSets/FieldResolution/FieldCompletion/Rule_6_4_3_SchemaValueCompletion.cs b/src/graphql-aspnet/Execution/RulesEngine/RuleSets/FieldResolution/FieldCompletion/Rule_6_4_3_SchemaValueCompletion.cs index a7b2edb91..3fd5e9507 100644 --- a/src/graphql-aspnet/Execution/RulesEngine/RuleSets/FieldResolution/FieldCompletion/Rule_6_4_3_SchemaValueCompletion.cs +++ b/src/graphql-aspnet/Execution/RulesEngine/RuleSets/FieldResolution/FieldCompletion/Rule_6_4_3_SchemaValueCompletion.cs @@ -12,7 +12,6 @@ namespace GraphQL.AspNet.Execution.RulesEngine.RuleSets.FieldResolution.FieldCom using GraphQL.AspNet.Execution.Contexts; using GraphQL.AspNet.Execution.FieldResolution; using GraphQL.AspNet.Execution.RulesEngine.RuleSets.FieldResolution.Common; - using GraphQL.AspNet.Internal; using GraphQL.AspNet.Schemas; /// diff --git a/src/graphql-aspnet/Execution/RulesEngine/RuleSets/FieldResolution/FieldCompletion/Rule_6_4_3_ServerValueCompletion.cs b/src/graphql-aspnet/Execution/RulesEngine/RuleSets/FieldResolution/FieldCompletion/Rule_6_4_3_ServerValueCompletion.cs index 449e26e2e..5cce4dace 100644 --- a/src/graphql-aspnet/Execution/RulesEngine/RuleSets/FieldResolution/FieldCompletion/Rule_6_4_3_ServerValueCompletion.cs +++ b/src/graphql-aspnet/Execution/RulesEngine/RuleSets/FieldResolution/FieldCompletion/Rule_6_4_3_ServerValueCompletion.cs @@ -16,7 +16,7 @@ namespace GraphQL.AspNet.Execution.RulesEngine.RuleSets.FieldResolution.FieldCom using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Execution.FieldResolution; using GraphQL.AspNet.Execution.RulesEngine.RuleSets.FieldResolution.Common; - using GraphQL.AspNet.Internal; + using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Schemas.TypeSystem; /// diff --git a/src/graphql-aspnet/Execution/Variables/ResolvedVariableGenerator.cs b/src/graphql-aspnet/Execution/Variables/ResolvedVariableGenerator.cs index 7bf2ba08a..652259ef6 100644 --- a/src/graphql-aspnet/Execution/Variables/ResolvedVariableGenerator.cs +++ b/src/graphql-aspnet/Execution/Variables/ResolvedVariableGenerator.cs @@ -13,12 +13,12 @@ namespace GraphQL.AspNet.Execution.Variables using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Execution.Parsing.NodeBuilders; using GraphQL.AspNet.Execution.QueryPlans; + using GraphQL.AspNet.Execution.Resolvers; using GraphQL.AspNet.Interfaces.Execution; using GraphQL.AspNet.Interfaces.Execution.QueryPlans.DocumentParts; using GraphQL.AspNet.Interfaces.Execution.QueryPlans.Resolvables; using GraphQL.AspNet.Interfaces.Execution.Variables; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal.Resolvers; /// /// An object that attempts to convert the untyped keyvalue pairs (usually pulled from a json doc) diff --git a/src/graphql-aspnet/Interfaces/Engine/IGraphArgumentMaker.cs b/src/graphql-aspnet/Interfaces/Engine/IGraphArgumentMaker.cs index 09eea5015..93bd73cb9 100644 --- a/src/graphql-aspnet/Interfaces/Engine/IGraphArgumentMaker.cs +++ b/src/graphql-aspnet/Interfaces/Engine/IGraphArgumentMaker.cs @@ -8,9 +8,9 @@ // ************************************************************* namespace GraphQL.AspNet.Interfaces.Engine { - using GraphQL.AspNet.Engine.TypeMakers; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Schemas.Generation.TypeMakers; /// /// A maker that can generate input arguments. diff --git a/src/graphql-aspnet/Interfaces/Engine/IGraphFieldMaker.cs b/src/graphql-aspnet/Interfaces/Engine/IGraphFieldMaker.cs index 9da6a05c7..ba954d436 100644 --- a/src/graphql-aspnet/Interfaces/Engine/IGraphFieldMaker.cs +++ b/src/graphql-aspnet/Interfaces/Engine/IGraphFieldMaker.cs @@ -9,9 +9,9 @@ namespace GraphQL.AspNet.Interfaces.Engine { - using GraphQL.AspNet.Engine.TypeMakers; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Schemas.Generation.TypeMakers; /// /// A "maker" that can generate fully qualified graph fields from a given template. diff --git a/src/graphql-aspnet/Interfaces/Engine/IGraphQLSchemaFactory{TSchema}.cs b/src/graphql-aspnet/Interfaces/Engine/IGraphQLSchemaFactory{TSchema}.cs index dc5d6ed27..aa8597f2e 100644 --- a/src/graphql-aspnet/Interfaces/Engine/IGraphQLSchemaFactory{TSchema}.cs +++ b/src/graphql-aspnet/Interfaces/Engine/IGraphQLSchemaFactory{TSchema}.cs @@ -12,8 +12,8 @@ namespace GraphQL.AspNet.Interfaces.Engine using System.Collections.Generic; using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Interfaces.Configuration; - using GraphQL.AspNet.Interfaces.Configuration.Templates; using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; using Microsoft.Extensions.DependencyInjection; /// diff --git a/src/graphql-aspnet/Interfaces/Engine/IGraphTypeMaker.cs b/src/graphql-aspnet/Interfaces/Engine/IGraphTypeMaker.cs index 1651da336..24c86d2d9 100644 --- a/src/graphql-aspnet/Interfaces/Engine/IGraphTypeMaker.cs +++ b/src/graphql-aspnet/Interfaces/Engine/IGraphTypeMaker.cs @@ -10,8 +10,8 @@ namespace GraphQL.AspNet.Interfaces.Engine { using System; - using GraphQL.AspNet.Engine.TypeMakers; using GraphQL.AspNet.Interfaces.Internal; + using GraphQL.AspNet.Schemas.Generation.TypeMakers; /// /// An object that can create a specific graph type from its associated concrete type according to a set of rules diff --git a/src/graphql-aspnet/Interfaces/Engine/IQueryExecutionPlanCacheProvider.cs b/src/graphql-aspnet/Interfaces/Engine/IQueryExecutionPlanCacheProvider.cs index 86004a922..a800e03d2 100644 --- a/src/graphql-aspnet/Interfaces/Engine/IQueryExecutionPlanCacheProvider.cs +++ b/src/graphql-aspnet/Interfaces/Engine/IQueryExecutionPlanCacheProvider.cs @@ -12,10 +12,11 @@ namespace GraphQL.AspNet.Interfaces.Engine using System; using System.Threading.Tasks; using GraphQL.AspNet.Interfaces.Execution; + using GraphQL.AspNet.Schemas.TypeSystem; /// /// An interface describing the query plan cache. Build your own cache against any technology you wish - /// and subsitute it in the at start up. This cache instance is a singleton reference + /// and subsitute it in the at start up. This cache instance is a singleton reference /// per server instance. /// public interface IQueryExecutionPlanCacheProvider diff --git a/src/graphql-aspnet/Interfaces/Engine/IUnionGraphTypeMaker.cs b/src/graphql-aspnet/Interfaces/Engine/IUnionGraphTypeMaker.cs index 8cfe7a628..838393a35 100644 --- a/src/graphql-aspnet/Interfaces/Engine/IUnionGraphTypeMaker.cs +++ b/src/graphql-aspnet/Interfaces/Engine/IUnionGraphTypeMaker.cs @@ -8,8 +8,8 @@ // ************************************************************* namespace GraphQL.AspNet.Interfaces.Engine { - using GraphQL.AspNet.Engine.TypeMakers; using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Schemas.Generation.TypeMakers; /// /// A type maker targeting the generation of unions from pre-configured proxy classes. diff --git a/src/graphql-aspnet/Interfaces/Internal/IGraphControllerTemplate.cs b/src/graphql-aspnet/Interfaces/Internal/IGraphControllerTemplate.cs index 58ed0878e..ea4463d22 100644 --- a/src/graphql-aspnet/Interfaces/Internal/IGraphControllerTemplate.cs +++ b/src/graphql-aspnet/Interfaces/Internal/IGraphControllerTemplate.cs @@ -10,7 +10,7 @@ namespace GraphQL.AspNet.Interfaces.Internal { using System.Collections.Generic; - using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; /// /// A special marker interface that identifies a valid diff --git a/src/graphql-aspnet/Interfaces/Internal/IGraphFieldTemplateBase.cs b/src/graphql-aspnet/Interfaces/Internal/IGraphFieldTemplateBase.cs index b416dcce3..fad3b3add 100644 --- a/src/graphql-aspnet/Interfaces/Internal/IGraphFieldTemplateBase.cs +++ b/src/graphql-aspnet/Interfaces/Internal/IGraphFieldTemplateBase.cs @@ -10,8 +10,8 @@ namespace GraphQL.AspNet.Interfaces.Internal { using System; using System.Collections.Generic; - using GraphQL.AspNet.Internal.TypeTemplates; using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.TypeSystem; /// diff --git a/src/graphql-aspnet/Interfaces/Internal/IGraphItemDependencies.cs b/src/graphql-aspnet/Interfaces/Internal/IGraphItemDependencies.cs index 4b92956d0..cad74ae6c 100644 --- a/src/graphql-aspnet/Interfaces/Internal/IGraphItemDependencies.cs +++ b/src/graphql-aspnet/Interfaces/Internal/IGraphItemDependencies.cs @@ -11,7 +11,7 @@ namespace GraphQL.AspNet.Interfaces.Internal { using System.Collections.Generic; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; /// /// An interface representing the collection of dependencies rendered during the creation of an item related to the object graph. diff --git a/src/graphql-aspnet/Interfaces/Internal/ISchemaItemTemplate.cs b/src/graphql-aspnet/Interfaces/Internal/ISchemaItemTemplate.cs index 777527c7f..6cb14bd2f 100644 --- a/src/graphql-aspnet/Interfaces/Internal/ISchemaItemTemplate.cs +++ b/src/graphql-aspnet/Interfaces/Internal/ISchemaItemTemplate.cs @@ -12,7 +12,7 @@ namespace GraphQL.AspNet.Interfaces.Internal using System; using System.Collections.Generic; using System.Reflection; - using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.Structural; /// diff --git a/src/graphql-aspnet/Interfaces/Schema/IGraphField.cs b/src/graphql-aspnet/Interfaces/Schema/IGraphField.cs index c5ae023f0..58f960426 100644 --- a/src/graphql-aspnet/Interfaces/Schema/IGraphField.cs +++ b/src/graphql-aspnet/Interfaces/Schema/IGraphField.cs @@ -11,7 +11,7 @@ namespace GraphQL.AspNet.Interfaces.Schema { using GraphQL.AspNet.Execution; using GraphQL.AspNet.Interfaces.Execution; - using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; /// /// Describes a single field in the type system. This describes how a given field is to be represented with its diff --git a/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLResolvableSchemaItemDefinition.cs b/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLResolvableSchemaItemDefinition.cs index 2db7788e3..88b1be02b 100644 --- a/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLResolvableSchemaItemDefinition.cs +++ b/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLResolvableSchemaItemDefinition.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Interfaces.Configuration.Templates +namespace GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions { using System; diff --git a/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeDirectiveActionDefinition.cs b/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeDirectiveActionDefinition.cs index 45d09efa9..0308327f0 100644 --- a/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeDirectiveActionDefinition.cs +++ b/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeDirectiveActionDefinition.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Interfaces.Configuration.Templates +namespace GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions { /// /// An intermediate template that utilizies a key/value pair system to build up a set of component parts diff --git a/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeFieldDefinition.cs b/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeFieldDefinition.cs index d01c6ccca..8ee426e14 100644 --- a/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeFieldDefinition.cs +++ b/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeFieldDefinition.cs @@ -7,12 +7,8 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Interfaces.Configuration.Templates +namespace GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions { - using System; - using System.Collections.Generic; - using GraphQL.AspNet.Configuration; - /// /// An intermediate template that utilizies a key/value pair system to build up a set of component parts /// that the templating engine will use to generate a full fledged field in a schema. diff --git a/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeResolvedFieldDefinition.cs b/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeResolvedFieldDefinition.cs index 2c2e07509..8b0d001d2 100644 --- a/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeResolvedFieldDefinition.cs +++ b/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeResolvedFieldDefinition.cs @@ -7,13 +7,8 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Interfaces.Configuration.Templates +namespace GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions { - using System; - using System.Collections.Generic; - using System.Diagnostics; - using GraphQL.AspNet.Configuration; - /// /// An intermediate template that utilizies a key/value pair system to build up a set of component parts /// that the templating engine will use to generate a full fledged field in a schema. diff --git a/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeSchemaItemDefinition.cs b/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeSchemaItemDefinition.cs index cf623e03a..898162ed3 100644 --- a/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeSchemaItemDefinition.cs +++ b/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeSchemaItemDefinition.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Interfaces.Configuration.Templates +namespace GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions { using System; using System.Collections.Generic; diff --git a/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeTypeExtensionDefinition.cs b/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeTypeExtensionDefinition.cs index 29e7c72e4..fb3446726 100644 --- a/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeTypeExtensionDefinition.cs +++ b/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeTypeExtensionDefinition.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Interfaces.Configuration.Templates +namespace GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions { using System; using GraphQL.AspNet.Execution; diff --git a/src/graphql-aspnet/Middleware/FieldExecution/Components/ProcessChildFieldsMiddleware.cs b/src/graphql-aspnet/Middleware/FieldExecution/Components/ProcessChildFieldsMiddleware.cs index bf18ecd5f..29ed5d53c 100644 --- a/src/graphql-aspnet/Middleware/FieldExecution/Components/ProcessChildFieldsMiddleware.cs +++ b/src/graphql-aspnet/Middleware/FieldExecution/Components/ProcessChildFieldsMiddleware.cs @@ -28,7 +28,6 @@ namespace GraphQL.AspNet.Middleware.FieldExecution.Components using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Internal; /// /// A middleware component that, when a result exists on the context, invokes the next set diff --git a/src/graphql-aspnet/Middleware/FieldExecution/Components/ValidateFieldExecutionMiddleware.cs b/src/graphql-aspnet/Middleware/FieldExecution/Components/ValidateFieldExecutionMiddleware.cs index b72efd68d..4b08e46bb 100644 --- a/src/graphql-aspnet/Middleware/FieldExecution/Components/ValidateFieldExecutionMiddleware.cs +++ b/src/graphql-aspnet/Middleware/FieldExecution/Components/ValidateFieldExecutionMiddleware.cs @@ -20,7 +20,7 @@ namespace GraphQL.AspNet.Middleware.FieldExecution.Components using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Interfaces.Middleware; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal; + using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Schemas.TypeSystem; /// diff --git a/src/graphql-aspnet/Schemas/Generation/TypeMakers/DependentTypeCollection.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/DependentTypeCollection.cs index ad125aa77..646ea3c34 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeMakers/DependentTypeCollection.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/DependentTypeCollection.cs @@ -7,13 +7,13 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Engine.TypeMakers +namespace GraphQL.AspNet.Schemas.Generation.TypeMakers { using System; using System.Collections.Generic; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.TypeSystem; /// diff --git a/src/graphql-aspnet/Schemas/Generation/TypeMakers/DirectiveMaker.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/DirectiveMaker.cs index 95dabfdcd..8b9011f31 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeMakers/DirectiveMaker.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/DirectiveMaker.cs @@ -12,12 +12,10 @@ namespace GraphQL.AspNet.Schemas.Generation.TypeMakers using System; using System.Collections.Generic; using GraphQL.AspNet.Common; - using GraphQL.AspNet.Engine.TypeMakers; using GraphQL.AspNet.Interfaces.Configuration; using GraphQL.AspNet.Interfaces.Engine; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal.TypeTemplates; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Security; diff --git a/src/graphql-aspnet/Schemas/Generation/TypeMakers/EnumGraphTypeMaker.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/EnumGraphTypeMaker.cs index 2addfd48a..eacce93ab 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeMakers/EnumGraphTypeMaker.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/EnumGraphTypeMaker.cs @@ -13,13 +13,11 @@ namespace GraphQL.AspNet.Schemas.Generation.TypeMakers using System.Linq; using GraphQL.AspNet.Common; using GraphQL.AspNet.Configuration; - using GraphQL.AspNet.Engine.TypeMakers; using GraphQL.AspNet.Execution.RulesEngine.RuleSets.DirectiveExecution.DirectiveValidation; using GraphQL.AspNet.Interfaces.Configuration; using GraphQL.AspNet.Interfaces.Engine; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal.TypeTemplates; using GraphQL.AspNet.Schemas.TypeSystem; /// diff --git a/src/graphql-aspnet/Schemas/Generation/TypeMakers/FieldContainerGraphTypeMakerBase.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/FieldContainerGraphTypeMakerBase.cs index 60af6dd55..c5a7a96f9 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeMakers/FieldContainerGraphTypeMakerBase.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/FieldContainerGraphTypeMakerBase.cs @@ -15,7 +15,7 @@ namespace GraphQL.AspNet.Schemas.Generation.TypeMakers using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Interfaces.Configuration; using GraphQL.AspNet.Interfaces.Internal; - using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; /// /// A base type maker for those types that generate fields. Used to centralize common code. diff --git a/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphArgumentCreationResult.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphArgumentCreationResult.cs index 8c7abe466..3c2302781 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphArgumentCreationResult.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphArgumentCreationResult.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Engine.TypeMakers +namespace GraphQL.AspNet.Schemas.Generation.TypeMakers { using GraphQL.AspNet.Interfaces.Schema; diff --git a/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphArgumentMaker.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphArgumentMaker.cs index 0e2e8817e..a3202bc53 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphArgumentMaker.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphArgumentMaker.cs @@ -11,12 +11,10 @@ namespace GraphQL.AspNet.Schemas.Generation.TypeMakers { using GraphQL.AspNet.Common; using GraphQL.AspNet.Configuration.Formatting; - using GraphQL.AspNet.Engine.TypeMakers; using GraphQL.AspNet.Interfaces.Configuration; using GraphQL.AspNet.Interfaces.Engine; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Schemas.TypeSystem.Scalars; diff --git a/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphFieldCreationResult.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphFieldCreationResult.cs index 606b2118d..84cd58bec 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphFieldCreationResult.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphFieldCreationResult.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Engine.TypeMakers +namespace GraphQL.AspNet.Schemas.Generation.TypeMakers { using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; diff --git a/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphFieldMaker.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphFieldMaker.cs index 362f72427..1f652b683 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphFieldMaker.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphFieldMaker.cs @@ -17,14 +17,12 @@ namespace GraphQL.AspNet.Schemas.Generation.TypeMakers using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Common.Generics; using GraphQL.AspNet.Configuration.Formatting; - using GraphQL.AspNet.Engine.TypeMakers; using GraphQL.AspNet.Execution.RulesEngine.RuleSets.DocumentValidation.FieldSelectionSteps; using GraphQL.AspNet.Interfaces.Configuration; using GraphQL.AspNet.Interfaces.Engine; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal; - using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Schemas.TypeSystem.Scalars; using GraphQL.AspNet.Security; diff --git a/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphMakerExtensions.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphMakerExtensions.cs index 7c4defc6a..2134c8688 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphMakerExtensions.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphMakerExtensions.cs @@ -6,7 +6,7 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Engine.TypeMakers +namespace GraphQL.AspNet.Schemas.Generation.TypeMakers { using System.Collections.Generic; using GraphQL.AspNet.Common; diff --git a/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphTypeCreationResult.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphTypeCreationResult.cs index fdf4219ce..a203e4d45 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphTypeCreationResult.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphTypeCreationResult.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Engine.TypeMakers +namespace GraphQL.AspNet.Schemas.Generation.TypeMakers { using System; using System.Diagnostics; diff --git a/src/graphql-aspnet/Schemas/Generation/TypeMakers/InputObjectGraphTypeMaker.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/InputObjectGraphTypeMaker.cs index 9fef91d19..cf58e42cc 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeMakers/InputObjectGraphTypeMaker.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/InputObjectGraphTypeMaker.cs @@ -13,12 +13,10 @@ namespace GraphQL.AspNet.Schemas.Generation.TypeMakers using System.Linq; using GraphQL.AspNet.Common; using GraphQL.AspNet.Configuration; - using GraphQL.AspNet.Engine.TypeMakers; using GraphQL.AspNet.Interfaces.Configuration; using GraphQL.AspNet.Interfaces.Engine; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal.TypeTemplates; using GraphQL.AspNet.Schemas.TypeSystem; /// diff --git a/src/graphql-aspnet/Schemas/Generation/TypeMakers/InterfaceGraphTypeMaker.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/InterfaceGraphTypeMaker.cs index d06c4041f..a5cb9c5dc 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeMakers/InterfaceGraphTypeMaker.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/InterfaceGraphTypeMaker.cs @@ -11,13 +11,10 @@ namespace GraphQL.AspNet.Schemas.Generation.TypeMakers { using System; using GraphQL.AspNet.Common; - using GraphQL.AspNet.Engine.TypeMakers; using GraphQL.AspNet.Interfaces.Configuration; using GraphQL.AspNet.Interfaces.Engine; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal; - using GraphQL.AspNet.Internal.TypeTemplates; using GraphQL.AspNet.Schemas.TypeSystem; /// diff --git a/src/graphql-aspnet/Schemas/Generation/TypeMakers/ObjectGraphTypeMaker.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/ObjectGraphTypeMaker.cs index b4edaf042..855822732 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeMakers/ObjectGraphTypeMaker.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/ObjectGraphTypeMaker.cs @@ -14,13 +14,10 @@ namespace GraphQL.AspNet.Schemas.Generation.TypeMakers using System.Linq; using GraphQL.AspNet.Common; using GraphQL.AspNet.Configuration; - using GraphQL.AspNet.Engine.TypeMakers; using GraphQL.AspNet.Interfaces.Configuration; using GraphQL.AspNet.Interfaces.Engine; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal; - using GraphQL.AspNet.Internal.TypeTemplates; using GraphQL.AspNet.Schemas.TypeSystem; /// diff --git a/src/graphql-aspnet/Schemas/Generation/TypeMakers/ScalarGraphTypeMaker.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/ScalarGraphTypeMaker.cs index 217b8eb05..47e73bba7 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeMakers/ScalarGraphTypeMaker.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/ScalarGraphTypeMaker.cs @@ -12,7 +12,6 @@ namespace GraphQL.AspNet.Schemas.Generation.TypeMakers using System; using GraphQL.AspNet.Common; using GraphQL.AspNet.Common.Extensions; - using GraphQL.AspNet.Engine.TypeMakers; using GraphQL.AspNet.Interfaces.Configuration; using GraphQL.AspNet.Interfaces.Engine; using GraphQL.AspNet.Interfaces.Internal; diff --git a/src/graphql-aspnet/Schemas/Generation/TypeMakers/UnionGraphTypeMaker.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/UnionGraphTypeMaker.cs index 1125c89f4..23779eaad 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeMakers/UnionGraphTypeMaker.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/UnionGraphTypeMaker.cs @@ -14,7 +14,6 @@ namespace GraphQL.AspNet.Schemas.Generation.TypeMakers using GraphQL.AspNet.Common; using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Common.Generics; - using GraphQL.AspNet.Engine.TypeMakers; using GraphQL.AspNet.Execution; using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Interfaces.Configuration; @@ -22,8 +21,7 @@ namespace GraphQL.AspNet.Schemas.Generation.TypeMakers using GraphQL.AspNet.Interfaces.Execution; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal; - using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Schemas.TypeSystem.Scalars; diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/AppliedDirectiveTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/AppliedDirectiveTemplate.cs index 25b679714..fd06b5132 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/AppliedDirectiveTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/AppliedDirectiveTemplate.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.TypeTemplates +namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates { using System; using GraphQL.AspNet.Attributes; diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/ApplyDirectiveAttributeExtensions.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/ApplyDirectiveAttributeExtensions.cs index 07955e75e..ea8522c4c 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/ApplyDirectiveAttributeExtensions.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/ApplyDirectiveAttributeExtensions.cs @@ -6,7 +6,7 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.TypeTemplates +namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates { using System.Collections.Generic; using System.Reflection; diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/ControllerActionGraphFieldTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/ControllerActionGraphFieldTemplate.cs index 17ba2ff3d..fb5310ae2 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/ControllerActionGraphFieldTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/ControllerActionGraphFieldTemplate.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.TypeTemplates +namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates { using System.Diagnostics; using System.Reflection; @@ -16,9 +16,9 @@ namespace GraphQL.AspNet.Internal.TypeTemplates using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Execution; using GraphQL.AspNet.Execution.Exceptions; + using GraphQL.AspNet.Execution.Resolvers; using GraphQL.AspNet.Interfaces.Execution; using GraphQL.AspNet.Interfaces.Internal; - using GraphQL.AspNet.Internal.Resolvers; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/DependentType.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/DependentType.cs index c2bc4c0fd..a75242340 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/DependentType.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/DependentType.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.TypeTemplates +namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates { using System; using System.Diagnostics; diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/EnumGraphTypeTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/EnumGraphTypeTemplate.cs index 256878b91..ce4f75aa2 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/EnumGraphTypeTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/EnumGraphTypeTemplate.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.TypeTemplates +namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates { using System; using System.Collections.Generic; diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/EnumValueTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/EnumValueTemplate.cs index 6ef432b93..24afca5fc 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/EnumValueTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/EnumValueTemplate.cs @@ -6,7 +6,7 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.TypeTemplates +namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates { using System; using System.ComponentModel; diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphArgumentTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphArgumentTemplate.cs index 1bd775e7e..bb8b68d02 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphArgumentTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphArgumentTemplate.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.TypeTemplates +namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates { using System; using System.Collections.Generic; @@ -21,10 +21,9 @@ namespace GraphQL.AspNet.Internal.TypeTemplates using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Execution; using GraphQL.AspNet.Execution.Exceptions; + using GraphQL.AspNet.Execution.Resolvers; using GraphQL.AspNet.Interfaces.Execution; using GraphQL.AspNet.Interfaces.Internal; - using GraphQL.AspNet.Internal.Resolvers; - using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; using Microsoft.AspNetCore.Mvc; diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphControllerTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphControllerTemplate.cs index ce462ebae..057e782dd 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphControllerTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphControllerTemplate.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.TypeTemplates +namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates { using System; using System.Collections.Generic; diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveMethodTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveMethodTemplate.cs index 1642b5cf9..1c23e9678 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveMethodTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveMethodTemplate.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.TypeTemplates +namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates { using System; using System.Collections.Generic; @@ -21,11 +21,10 @@ namespace GraphQL.AspNet.Internal.TypeTemplates using GraphQL.AspNet.Common; using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Execution.Exceptions; + using GraphQL.AspNet.Execution.Resolvers; using GraphQL.AspNet.Interfaces.Controllers; using GraphQL.AspNet.Interfaces.Execution; using GraphQL.AspNet.Interfaces.Internal; - using GraphQL.AspNet.Internal.Resolvers; - using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveMethodTemplateContainer.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveMethodTemplateContainer.cs index 78fe85242..5b6f47786 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveMethodTemplateContainer.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveMethodTemplateContainer.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.TypeTemplates +namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates { using System.Collections.Generic; using System.Linq; diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveTemplate.cs index a092acdb9..09c30e1fc 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveTemplate.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.TypeTemplates +namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates { using System; using System.Collections.Generic; @@ -21,9 +21,9 @@ namespace GraphQL.AspNet.Internal.TypeTemplates using GraphQL.AspNet.Directives; using GraphQL.AspNet.Execution; using GraphQL.AspNet.Execution.Exceptions; + using GraphQL.AspNet.Execution.Resolvers; using GraphQL.AspNet.Interfaces.Execution; using GraphQL.AspNet.Interfaces.Internal; - using GraphQL.AspNet.Internal.Resolvers; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Security; diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphFieldTemplateBase.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphFieldTemplateBase.cs index f4b7900c5..549e9d33a 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphFieldTemplateBase.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphFieldTemplateBase.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.TypeTemplates +namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates { using System; using System.Collections.Generic; @@ -18,17 +18,14 @@ namespace GraphQL.AspNet.Internal.TypeTemplates using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Common; using GraphQL.AspNet.Common.Extensions; - using GraphQL.AspNet.Common.Generics; using GraphQL.AspNet.Execution; using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Interfaces.Controllers; using GraphQL.AspNet.Interfaces.Execution; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Schemas.TypeSystem.Scalars; using GraphQL.AspNet.Security; /// diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphFieldTemplateSource.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphFieldTemplateSource.cs index 2f8f9c84c..10ceb701c 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphFieldTemplateSource.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphFieldTemplateSource.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.TypeTemplates +namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates { using System; diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphTypeExtensionFieldTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphTypeExtensionFieldTemplate.cs index 116a51989..e59ecd899 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphTypeExtensionFieldTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphTypeExtensionFieldTemplate.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.TypeTemplates +namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates { using System; using System.Reflection; @@ -15,11 +15,10 @@ namespace GraphQL.AspNet.Internal.TypeTemplates using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Execution; using GraphQL.AspNet.Execution.Exceptions; + using GraphQL.AspNet.Execution.Resolvers; using GraphQL.AspNet.Interfaces.Controllers; using GraphQL.AspNet.Interfaces.Execution; using GraphQL.AspNet.Interfaces.Internal; - using GraphQL.AspNet.Internal.Resolvers; - using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphTypeTemplateBase.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphTypeTemplateBase.cs index 57b53a905..3a46d6e03 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphTypeTemplateBase.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphTypeTemplateBase.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.TypeTemplates +namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates { using System.Reflection; using GraphQL.AspNet.Attributes; diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphTypeTemplates.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphTypeTemplates.cs index f401f2dd0..73afa5027 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphTypeTemplates.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphTypeTemplates.cs @@ -15,7 +15,6 @@ namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates using GraphQL.AspNet.Directives; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal.TypeTemplates; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Schemas.TypeSystem.Scalars; diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/InputGraphFieldTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/InputGraphFieldTemplate.cs index b1bb35b0e..6e823e7ae 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/InputGraphFieldTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/InputGraphFieldTemplate.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.TypeTemplates +namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates { using System; using System.Collections.Generic; @@ -23,7 +23,6 @@ namespace GraphQL.AspNet.Internal.TypeTemplates using GraphQL.AspNet.Interfaces.Controllers; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/InputObjectGraphTypeTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/InputObjectGraphTypeTemplate.cs index d142f5cc8..fd2d02439 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/InputObjectGraphTypeTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/InputObjectGraphTypeTemplate.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.TypeTemplates +namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates { using System; using System.Collections.Generic; diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/InterfaceGraphTypeTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/InterfaceGraphTypeTemplate.cs index 91f069df4..718d49cf8 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/InterfaceGraphTypeTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/InterfaceGraphTypeTemplate.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.TypeTemplates +namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates { using System; using System.Collections.Generic; diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/MemberInfoProvider.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/MemberInfoProvider.cs index 11f88a47e..27861cbaa 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/MemberInfoProvider.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/MemberInfoProvider.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.TypeTemplates +namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates { using System.Reflection; using GraphQL.AspNet.Common; diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplate.cs index 35692ee32..fe246abe1 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplate.cs @@ -7,9 +7,8 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.TypeTemplates +namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates { - using System; using System.Reflection; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Common.Extensions; diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplateBase.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplateBase.cs index 9555e8120..a52b4ea25 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplateBase.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplateBase.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.TypeTemplates +namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates { using System; using System.Collections.Generic; @@ -16,9 +16,9 @@ namespace GraphQL.AspNet.Internal.TypeTemplates using System.Reflection; using GraphQL.AspNet.Common; using GraphQL.AspNet.Execution.Exceptions; + using GraphQL.AspNet.Execution.Resolvers; using GraphQL.AspNet.Interfaces.Execution; using GraphQL.AspNet.Interfaces.Internal; - using GraphQL.AspNet.Internal.Resolvers; /// /// A base class representing common functionality between all field templates based on @@ -95,7 +95,7 @@ public override void ValidateOrThrow() if (this.ExpectedReturnType == null) { throw new GraphTypeDeclarationException( - $"Invalid graph method declaration. The method '{this.InternalFullName}' has no valid {nameof(ExpectedReturnType)}. An expected " + + $"Invalid graph method declaration. The method '{this.InternalFullName}' has no valid {nameof(this.ExpectedReturnType)}. An expected " + "return type must be assigned from the declared return type."); } } diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/NonLeafGraphTypeTemplateBase.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/NonLeafGraphTypeTemplateBase.cs index 09960f193..e2af0e2ed 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/NonLeafGraphTypeTemplateBase.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/NonLeafGraphTypeTemplateBase.cs @@ -7,14 +7,13 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.TypeTemplates +namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates { using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Linq; - using System.Linq.Expressions; using System.Reflection; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Common; diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/ObjectGraphTypeTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/ObjectGraphTypeTemplate.cs index 8208fb022..f3c872288 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/ObjectGraphTypeTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/ObjectGraphTypeTemplate.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.TypeTemplates +namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates { using System; using System.Collections.Generic; diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/PropertyGraphFieldTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/PropertyGraphFieldTemplate.cs index 0b5722249..0755108c0 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/PropertyGraphFieldTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/PropertyGraphFieldTemplate.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.TypeTemplates +namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates { using System; using System.Collections.Generic; @@ -18,9 +18,9 @@ namespace GraphQL.AspNet.Internal.TypeTemplates using GraphQL.AspNet.Common; using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Execution.Exceptions; + using GraphQL.AspNet.Execution.Resolvers; using GraphQL.AspNet.Interfaces.Execution; using GraphQL.AspNet.Interfaces.Internal; - using GraphQL.AspNet.Internal.Resolvers; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; @@ -91,7 +91,7 @@ public override void ValidateOrThrow() if (this.ExpectedReturnType == null) { throw new GraphTypeDeclarationException( - $"The graph property '{this.InternalFullName}' has no valid {nameof(ExpectedReturnType)}. An expected " + + $"The graph property '{this.InternalFullName}' has no valid {nameof(this.ExpectedReturnType)}. An expected " + "return type must be assigned from the declared return type."); } } diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/RuntimeGraphControllerTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/RuntimeGraphControllerTemplate.cs index 7205863da..169aef51a 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/RuntimeGraphControllerTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/RuntimeGraphControllerTemplate.cs @@ -7,13 +7,13 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.TypeTemplates +namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates { using System.Collections.Generic; using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Execution.Exceptions; - using GraphQL.AspNet.Interfaces.Configuration.Templates; using GraphQL.AspNet.Interfaces.Internal; + using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; /// /// A "controller template" representing a single runtime configured field (e.g. minimal api). diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/RuntimeSchemaItemAttributeProvider.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/RuntimeSchemaItemAttributeProvider.cs index bb70caf85..f6b5941a2 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/RuntimeSchemaItemAttributeProvider.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/RuntimeSchemaItemAttributeProvider.cs @@ -7,13 +7,13 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.TypeTemplates +namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates { using System; using System.Collections.Generic; using System.Reflection; using GraphQL.AspNet.Common; - using GraphQL.AspNet.Interfaces.Configuration.Templates; + using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; /// /// A custom that can provide runtime declared attributes diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/ScalarGraphTypeTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/ScalarGraphTypeTemplate.cs index da3d9ac23..e5e59e88e 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/ScalarGraphTypeTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/ScalarGraphTypeTemplate.cs @@ -7,17 +7,14 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.TypeTemplates +namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates { using System; using GraphQL.AspNet.Common; using GraphQL.AspNet.Execution; - using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Interfaces.Internal; - using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Schemas.TypeSystem.Scalars; using GraphQL.AspNet.Security; /// diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/SchemaItemTemplateBase.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/SchemaItemTemplateBase.cs index 499881104..d16a767a5 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/SchemaItemTemplateBase.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/SchemaItemTemplateBase.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.TypeTemplates +namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates { using System; using System.Collections.Generic; diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/UnionGraphTypeTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/UnionGraphTypeTemplate.cs index c67bf40be..52663bbcf 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/UnionGraphTypeTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/UnionGraphTypeTemplate.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.TypeTemplates +namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates { using System; using GraphQL.AspNet.Common; @@ -18,7 +18,6 @@ namespace GraphQL.AspNet.Internal.TypeTemplates using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Schemas.TypeSystem.Scalars; using GraphQL.AspNet.Security; /// diff --git a/src/graphql-aspnet/Schemas/GraphSchema.cs b/src/graphql-aspnet/Schemas/GraphSchema.cs index 5337998ec..d4e51a4da 100644 --- a/src/graphql-aspnet/Schemas/GraphSchema.cs +++ b/src/graphql-aspnet/Schemas/GraphSchema.cs @@ -17,7 +17,6 @@ namespace GraphQL.AspNet.Schemas using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Interfaces.Configuration; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Schemas.TypeSystem.TypeCollections; diff --git a/src/graphql-aspnet/Schemas/GraphTypeExpression_Statics.cs b/src/graphql-aspnet/Schemas/GraphTypeExpression_Statics.cs index 1e49ce56e..64d4a0a2a 100644 --- a/src/graphql-aspnet/Schemas/GraphTypeExpression_Statics.cs +++ b/src/graphql-aspnet/Schemas/GraphTypeExpression_Statics.cs @@ -16,7 +16,6 @@ namespace GraphQL.AspNet.Schemas using GraphQL.AspNet.Common; using GraphQL.AspNet.Execution.Parsing.Lexing.Tokens; using GraphQL.AspNet.Execution.RulesEngine.RuleSets.DocumentValidation.QueryFragmentSteps; - using GraphQL.AspNet.Internal; using GraphQL.AspNet.Schemas.TypeSystem; /// diff --git a/src/graphql-aspnet/Schemas/GraphTypeNames.cs b/src/graphql-aspnet/Schemas/GraphTypeNames.cs index 9a1dc18c9..4cedfd4ee 100644 --- a/src/graphql-aspnet/Schemas/GraphTypeNames.cs +++ b/src/graphql-aspnet/Schemas/GraphTypeNames.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal +namespace GraphQL.AspNet.Schemas { using System; using System.Collections.Concurrent; @@ -17,7 +17,6 @@ namespace GraphQL.AspNet.Internal using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Schemas.TypeSystem.Scalars; /// /// A global collection of known graph type names and their concrete type references. diff --git a/src/graphql-aspnet/Schemas/GraphValidation.cs b/src/graphql-aspnet/Schemas/GraphValidation.cs index 8493baefb..18e331c0b 100644 --- a/src/graphql-aspnet/Schemas/GraphValidation.cs +++ b/src/graphql-aspnet/Schemas/GraphValidation.cs @@ -7,14 +7,13 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal +namespace GraphQL.AspNet.Schemas { using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Reflection; - using System.Threading; using System.Threading.Tasks; using GraphQL.AspNet.Common; using GraphQL.AspNet.Common.Extensions; @@ -22,7 +21,6 @@ namespace GraphQL.AspNet.Internal using GraphQL.AspNet.Directives; using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Schemas.TypeSystem; using Microsoft.AspNetCore.Authorization; @@ -108,6 +106,9 @@ public static TypeKind ResolveTypeKind(Type type, TypeKind? overrideValue = null if (Validation.IsCastable(type)) return TypeKind.DIRECTIVE; + + if (GlobalTypes.IsBuiltInScalar(type)) + return TypeKind.SCALAR; } return overrideValue ?? TypeKind.OBJECT; diff --git a/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/BaseRuntimeControllerActionDefinition.cs b/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/BaseRuntimeControllerActionDefinition.cs index 8c0132c88..de5774975 100644 --- a/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/BaseRuntimeControllerActionDefinition.cs +++ b/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/BaseRuntimeControllerActionDefinition.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Configuration.Templates +namespace GraphQL.AspNet.Schemas.RuntimeSchemaItemDefinitions { using System; using System.Collections.Generic; @@ -15,7 +15,7 @@ namespace GraphQL.AspNet.Configuration.Templates using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Execution; - using GraphQL.AspNet.Interfaces.Configuration.Templates; + using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; using GraphQL.AspNet.Schemas.Structural; /// diff --git a/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeDirectiveActionDefinition.cs b/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeDirectiveActionDefinition.cs index 40c5eb404..3729fd0a6 100644 --- a/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeDirectiveActionDefinition.cs +++ b/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeDirectiveActionDefinition.cs @@ -7,13 +7,13 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Configuration.Templates +namespace GraphQL.AspNet.Schemas.RuntimeSchemaItemDefinitions { using System; using System.Diagnostics; using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Execution; - using GraphQL.AspNet.Interfaces.Configuration.Templates; + using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; /// /// An internal implementation of the diff --git a/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeResolvedFieldDefinition.cs b/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeResolvedFieldDefinition.cs index 7097cf01e..18eeafdab 100644 --- a/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeResolvedFieldDefinition.cs +++ b/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeResolvedFieldDefinition.cs @@ -7,16 +7,15 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Configuration.Templates +namespace GraphQL.AspNet.Schemas.RuntimeSchemaItemDefinitions { using System; using System.Diagnostics; - using System.Linq; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Common; using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Execution; - using GraphQL.AspNet.Interfaces.Configuration.Templates; + using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; using GraphQL.AspNet.Schemas.Structural; /// diff --git a/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeTypeExtensionDefinition.cs b/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeTypeExtensionDefinition.cs index 714d1db38..2e0cacd76 100644 --- a/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeTypeExtensionDefinition.cs +++ b/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeTypeExtensionDefinition.cs @@ -7,15 +7,14 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Configuration.Templates +namespace GraphQL.AspNet.Schemas.RuntimeSchemaItemDefinitions { using System; using System.Diagnostics; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Execution; - using GraphQL.AspNet.Interfaces.Configuration.Templates; - using GraphQL.AspNet.Internal; + using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; diff --git a/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeVirtualFieldTemplate.cs b/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeVirtualFieldTemplate.cs index bc8c1459f..a9a2df9e7 100644 --- a/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeVirtualFieldTemplate.cs +++ b/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeVirtualFieldTemplate.cs @@ -7,13 +7,13 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Configuration.Templates +namespace GraphQL.AspNet.Schemas.RuntimeSchemaItemDefinitions { using System; using System.Diagnostics; using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Execution; - using GraphQL.AspNet.Interfaces.Configuration.Templates; + using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; /// /// An internal implementation of the diff --git a/src/graphql-aspnet/Schemas/SchemaLanguageGenerator.cs b/src/graphql-aspnet/Schemas/SchemaLanguageGenerator.cs index ac1486fd3..ea4121ef0 100644 --- a/src/graphql-aspnet/Schemas/SchemaLanguageGenerator.cs +++ b/src/graphql-aspnet/Schemas/SchemaLanguageGenerator.cs @@ -17,7 +17,6 @@ namespace GraphQL.AspNet.Schemas using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Common.Generics; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal; using GraphQL.AspNet.Schemas.TypeSystem; /// diff --git a/src/graphql-aspnet/Schemas/Structural/GraphFieldCollection.cs b/src/graphql-aspnet/Schemas/Structural/GraphFieldCollection.cs index 46c9a1825..8b373efde 100644 --- a/src/graphql-aspnet/Schemas/Structural/GraphFieldCollection.cs +++ b/src/graphql-aspnet/Schemas/Structural/GraphFieldCollection.cs @@ -17,9 +17,8 @@ namespace GraphQL.AspNet.Schemas.Structural using GraphQL.AspNet.Common; using GraphQL.AspNet.Execution; using GraphQL.AspNet.Execution.Exceptions; + using GraphQL.AspNet.Execution.Resolvers; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal; - using GraphQL.AspNet.Internal.Resolvers; using GraphQL.AspNet.Schemas.TypeSystem; /// diff --git a/src/graphql-aspnet/Schemas/TypeSystem/EnumGraphType.cs b/src/graphql-aspnet/Schemas/TypeSystem/EnumGraphType.cs index 35faf8da1..e1ddabfeb 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/EnumGraphType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/EnumGraphType.cs @@ -13,9 +13,9 @@ namespace GraphQL.AspNet.Schemas.TypeSystem using System.Diagnostics; using GraphQL.AspNet.Common; using GraphQL.AspNet.Common.Extensions; + using GraphQL.AspNet.Execution.Resolvers; using GraphQL.AspNet.Interfaces.Execution; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal.Resolvers; using GraphQL.AspNet.Schemas.Structural; /// diff --git a/src/graphql-aspnet/Schemas/TypeSystem/ExtendableGraphTypeExtensions.cs b/src/graphql-aspnet/Schemas/TypeSystem/ExtendableGraphTypeExtensions.cs index 51b4b15e5..b57ebd62f 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/ExtendableGraphTypeExtensions.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/ExtendableGraphTypeExtensions.cs @@ -12,9 +12,8 @@ namespace GraphQL.AspNet.Schemas.TypeSystem using System.Threading.Tasks; using GraphQL.AspNet.Common; using GraphQL.AspNet.Execution; + using GraphQL.AspNet.Execution.Resolvers; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal; - using GraphQL.AspNet.Internal.Resolvers; using GraphQL.AspNet.Schemas.Structural; /// diff --git a/src/graphql-aspnet/Schemas/TypeSystem/GlobalTypes.cs b/src/graphql-aspnet/Schemas/TypeSystem/GlobalTypes.cs index d6b704536..ba068c271 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/GlobalTypes.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/GlobalTypes.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Schemas.TypeSystem.Scalars +namespace GraphQL.AspNet.Schemas.TypeSystem { using System; using System.Collections.Generic; @@ -17,7 +17,7 @@ namespace GraphQL.AspNet.Schemas.TypeSystem.Scalars using GraphQL.AspNet.Common.Generics; using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal; + using GraphQL.AspNet.Schemas.TypeSystem.Scalars; /// /// A map of .NET types and their related built in scalar types and unions. diff --git a/src/graphql-aspnet/Schemas/TypeSystem/GraphUnionProxy.cs b/src/graphql-aspnet/Schemas/TypeSystem/GraphUnionProxy.cs index 4bd85a7a2..7c41dba8f 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/GraphUnionProxy.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/GraphUnionProxy.cs @@ -13,7 +13,6 @@ namespace GraphQL.AspNet.Schemas.TypeSystem using System.Collections.Generic; using System.Diagnostics; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal; /// /// An basic implementation of that can be diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_SchemaField.cs b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_SchemaField.cs index aa5247d06..a03d43a14 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_SchemaField.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_SchemaField.cs @@ -14,8 +14,8 @@ namespace GraphQL.AspNet.Schemas.TypeSystem.Introspection.Fields using GraphQL.AspNet.Common; using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Execution; + using GraphQL.AspNet.Execution.Resolvers; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal.Resolvers; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Schemas.TypeSystem.Introspection.Model; diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_TypeGraphField.cs b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_TypeGraphField.cs index cfd9705f8..31412d509 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_TypeGraphField.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_TypeGraphField.cs @@ -12,8 +12,8 @@ namespace GraphQL.AspNet.Schemas.TypeSystem.Introspection.Fields using System; using System.Diagnostics; using GraphQL.AspNet.Execution; + using GraphQL.AspNet.Execution.Resolvers.Introspeection; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal.Resolvers.Introspeection; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Schemas.TypeSystem.Introspection.Model; diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_TypeNameMetaField.cs b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_TypeNameMetaField.cs index 0e0377f9a..892933a2c 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_TypeNameMetaField.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_TypeNameMetaField.cs @@ -14,8 +14,8 @@ namespace GraphQL.AspNet.Schemas.TypeSystem.Introspection.Fields using GraphQL.AspNet.Common; using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Execution; + using GraphQL.AspNet.Execution.Resolvers; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal.Resolvers; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_TypeType.cs b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_TypeType.cs index 0afcd06ea..c4d35bf6c 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_TypeType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_TypeType.cs @@ -13,7 +13,7 @@ namespace GraphQL.AspNet.Schemas.TypeSystem.Introspection using System.Diagnostics; using System.Threading.Tasks; using GraphQL.AspNet.Execution; - using GraphQL.AspNet.Internal.Resolvers.Introspeection; + using GraphQL.AspNet.Execution.Resolvers.Introspeection; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Schemas.TypeSystem.Introspection.Model; diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedInputValueType.cs b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedInputValueType.cs index feed02fc3..e524487f3 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedInputValueType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedInputValueType.cs @@ -15,7 +15,6 @@ namespace GraphQL.AspNet.Schemas.TypeSystem.Introspection.Model using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal; using GraphQL.AspNet.Schemas.Structural; /// diff --git a/src/graphql-aspnet/Schemas/TypeSystem/MethodGraphField.cs b/src/graphql-aspnet/Schemas/TypeSystem/MethodGraphField.cs index d5fa64702..1bb13eeb9 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/MethodGraphField.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/MethodGraphField.cs @@ -17,8 +17,7 @@ namespace GraphQL.AspNet.Schemas.TypeSystem using GraphQL.AspNet.Execution; using GraphQL.AspNet.Interfaces.Execution; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal; - using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Security; diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/ScalarGraphTypeBase.cs b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/ScalarGraphTypeBase.cs index 6a2959b2c..99a8639f9 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/ScalarGraphTypeBase.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/ScalarGraphTypeBase.cs @@ -15,7 +15,7 @@ namespace GraphQL.AspNet.Schemas.TypeSystem.Scalars using GraphQL.AspNet.Execution; using GraphQL.AspNet.Interfaces.Execution; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.Structural; /// diff --git a/src/graphql-aspnet/Schemas/TypeSystem/TypeCollections/ConcreteTypeCollection.cs b/src/graphql-aspnet/Schemas/TypeSystem/TypeCollections/ConcreteTypeCollection.cs index f6a77ba5c..58759f537 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/TypeCollections/ConcreteTypeCollection.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/TypeCollections/ConcreteTypeCollection.cs @@ -18,7 +18,6 @@ namespace GraphQL.AspNet.Schemas.TypeSystem.TypeCollections using GraphQL.AspNet.Directives; using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal; /// /// A colleciton of and their associated concrete .NET . diff --git a/src/graphql-aspnet/Schemas/TypeSystem/TypeCollections/SchemaTypeCollection.cs b/src/graphql-aspnet/Schemas/TypeSystem/TypeCollections/SchemaTypeCollection.cs index 026ad609e..39997dadb 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/TypeCollections/SchemaTypeCollection.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/TypeCollections/SchemaTypeCollection.cs @@ -20,7 +20,6 @@ namespace GraphQL.AspNet.Schemas.TypeSystem.TypeCollections using GraphQL.AspNet.Directives; using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal; using GraphQL.AspNet.Schemas.Structural; /// diff --git a/src/graphql-aspnet/Schemas/TypeSystem/VirtualGraphField.cs b/src/graphql-aspnet/Schemas/TypeSystem/VirtualGraphField.cs index 93fc096c3..377f6bd7b 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/VirtualGraphField.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/VirtualGraphField.cs @@ -16,11 +16,11 @@ namespace GraphQL.AspNet.Schemas.TypeSystem using GraphQL.AspNet.Common; using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Execution; + using GraphQL.AspNet.Execution.Resolvers; using GraphQL.AspNet.Interfaces.Execution; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal.Resolvers; - using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Security; diff --git a/src/graphql-aspnet/ServerExtensions/MultipartRequests/Web/MultiPartHttpFormPayloadParser.cs b/src/graphql-aspnet/ServerExtensions/MultipartRequests/Web/MultiPartHttpFormPayloadParser.cs index bfcd2c209..17b1e9340 100644 --- a/src/graphql-aspnet/ServerExtensions/MultipartRequests/Web/MultiPartHttpFormPayloadParser.cs +++ b/src/graphql-aspnet/ServerExtensions/MultipartRequests/Web/MultiPartHttpFormPayloadParser.cs @@ -18,6 +18,7 @@ namespace GraphQL.AspNet.ServerExtensions.MultipartRequests.Web using System.Threading.Tasks; using GraphQL.AspNet.Common; using GraphQL.AspNet.Common.Extensions; + using GraphQL.AspNet.Common.JsonNodes; using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.ServerExtensions.MultipartRequests.Configuration; using GraphQL.AspNet.ServerExtensions.MultipartRequests.Exceptions; diff --git a/src/graphql-aspnet/ServerExtensions/MultipartRequests/Web/MultiPartHttpFormPayloadParser_Json.cs b/src/graphql-aspnet/ServerExtensions/MultipartRequests/Web/MultiPartHttpFormPayloadParser_Json.cs index 7fc366eb5..e7c38d1ba 100644 --- a/src/graphql-aspnet/ServerExtensions/MultipartRequests/Web/MultiPartHttpFormPayloadParser_Json.cs +++ b/src/graphql-aspnet/ServerExtensions/MultipartRequests/Web/MultiPartHttpFormPayloadParser_Json.cs @@ -15,6 +15,7 @@ namespace GraphQL.AspNet.ServerExtensions.MultipartRequests.Web using System.Text.Json; using System.Text.Json.Nodes; using GraphQL.AspNet.Common.Extensions; + using GraphQL.AspNet.Common.JsonNodes; using GraphQL.AspNet.ServerExtensions.MultipartRequests.Configuration; using GraphQL.AspNet.ServerExtensions.MultipartRequests.Exceptions; using GraphQL.AspNet.ServerExtensions.MultipartRequests.Model; diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Controllers/ControllerExtensionTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Controllers/ControllerExtensionTests.cs index 195e9f3d9..701a3794d 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Controllers/ControllerExtensionTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Controllers/ControllerExtensionTests.cs @@ -16,8 +16,8 @@ namespace GraphQL.AspNet.Tests.Controllers using GraphQL.AspNet.Controllers.ActionResults; using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.SubscriptionServer; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using GraphQL.AspNet.Tests.Controllers.ControllerTestData; using NUnit.Framework; diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Controllers/ControllerTestData/InvokableController.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Controllers/ControllerTestData/InvokableController.cs index 5308f2267..c687a2464 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Controllers/ControllerTestData/InvokableController.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Controllers/ControllerTestData/InvokableController.cs @@ -13,7 +13,7 @@ namespace GraphQL.AspNet.Tests.Controllers.ControllerTestData using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Interfaces.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; [GraphRoute("invoke")] public class InvokableController : GraphController diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/DefaultEventRouterTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/DefaultEventRouterTests.cs index 2b9fc2712..7cba711c3 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/DefaultEventRouterTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/DefaultEventRouterTests.cs @@ -16,7 +16,7 @@ namespace GraphQL.AspNet.Tests.Engine using GraphQL.AspNet.Interfaces.Subscriptions; using GraphQL.AspNet.Schemas; using GraphQL.AspNet.SubscriptionServer; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using Moq; using NUnit.Framework; diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Execution/ExecutionDirectiveTestData/DirectiveTestController.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Execution/ExecutionDirectiveTestData/DirectiveTestController.cs index abd07dc4e..b05636594 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Execution/ExecutionDirectiveTestData/DirectiveTestController.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Execution/ExecutionDirectiveTestData/DirectiveTestController.cs @@ -14,7 +14,7 @@ namespace GraphQL.AspNet.Tests.Execution.ExecutionDirectiveTestData using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Interfaces.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class DirectiveTestController : GraphController { diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Execution/SubscriptionQueryExecutionData/SubQueryController.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Execution/SubscriptionQueryExecutionData/SubQueryController.cs index 240be6dda..67242ac98 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Execution/SubscriptionQueryExecutionData/SubQueryController.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Execution/SubscriptionQueryExecutionData/SubQueryController.cs @@ -12,7 +12,7 @@ namespace GraphQL.AspNet.Tests.Execution.SubscriptionQueryExecutionData using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Interfaces.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; [GraphRoute("subscriptionData")] public class SubQueryController : GraphController diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Execution/SubscriptionQueryExecutionDirectiveTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Execution/SubscriptionQueryExecutionDirectiveTests.cs index 9c4927a20..e2785fad8 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Execution/SubscriptionQueryExecutionDirectiveTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Execution/SubscriptionQueryExecutionDirectiveTests.cs @@ -10,8 +10,8 @@ namespace GraphQL.AspNet.Tests.Execution { using System.Threading.Tasks; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using GraphQL.AspNet.Tests.Execution.ExecutionDirectiveTestData; using GraphQL.AspNet.Tests.Execution.SubscriptionQueryExecutionData; using GraphQL.AspNet.Tests.Mocks; diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Execution/SubscriptionQueryExecutionTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Execution/SubscriptionQueryExecutionTests.cs index 8cd83d4cb..e52428e63 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Execution/SubscriptionQueryExecutionTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Execution/SubscriptionQueryExecutionTests.cs @@ -12,8 +12,8 @@ namespace GraphQL.AspNet.Tests.Execution using System.Security.Cryptography; using System.Threading.Tasks; using GraphQL.AspNet; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using GraphQL.AspNet.Tests.Execution.SubscriptionQueryExecutionData; using GraphQL.AspNet.Tests.Mocks; using NuGet.Frameworks; diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/ActionTestData/OneMethodSubscriptionController.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/ActionTestData/OneMethodSubscriptionController.cs index 5da209c80..427c7f34e 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/ActionTestData/OneMethodSubscriptionController.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/ActionTestData/OneMethodSubscriptionController.cs @@ -12,7 +12,7 @@ namespace GraphQL.AspNet.Tests.Internal.Templating.ActionTestData using System.ComponentModel; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class OneMethodSubscriptionController : GraphController { diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/ActionTestData/SubscriptionMethodController.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/ActionTestData/SubscriptionMethodController.cs index fda682edc..294895235 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/ActionTestData/SubscriptionMethodController.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/ActionTestData/SubscriptionMethodController.cs @@ -12,7 +12,7 @@ namespace GraphQL.AspNet.Tests.Internal.Templating.ActionTestData using System.ComponentModel; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class SubscriptionMethodController : GraphController { diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/ControllerTestData/SimpleSubscriptionController.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/ControllerTestData/SimpleSubscriptionController.cs index 91b3de616..fb44ccd21 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/ControllerTestData/SimpleSubscriptionController.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/ControllerTestData/SimpleSubscriptionController.cs @@ -13,7 +13,7 @@ namespace GraphQL.AspNet.Tests.Internal.Templating.ControllerTestData using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Interfaces.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using NUnit.Framework; public class SimpleSubscriptionController : GraphController diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/GraphActionTemplateTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/GraphActionTemplateTests.cs index 1047d9ca0..68565ac88 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/GraphActionTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/GraphActionTemplateTests.cs @@ -18,7 +18,7 @@ namespace GraphQL.AspNet.Tests.Internal.Templating using GraphQL.AspNet.Internal.TypeTemplates; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Internal.Templating.ActionTestData; using Moq; using NUnit.Framework; diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/GraphControllerTemplateTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/GraphControllerTemplateTests.cs index 77708d8d1..4395ceb95 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/GraphControllerTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/GraphControllerTemplateTests.cs @@ -11,6 +11,7 @@ namespace GraphQL.AspNet.Tests.Internal.Templating { using System.Linq; using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Tests.Internal.Templating.ControllerTestData; using NUnit.Framework; diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Middleware/PublishRaisedSubscriptionEventsMiddlewareTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Middleware/PublishRaisedSubscriptionEventsMiddlewareTests.cs index 3c90472ae..2a9e4d151 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Middleware/PublishRaisedSubscriptionEventsMiddlewareTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Middleware/PublishRaisedSubscriptionEventsMiddlewareTests.cs @@ -19,8 +19,8 @@ namespace GraphQL.AspNet.Tests.Middleware using GraphQL.AspNet.Middleware.QueryExecution.Components; using GraphQL.AspNet.Schemas; using GraphQL.AspNet.SubscriptionServer; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using NUnit.Framework; [TestFixture] diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Mocks/SubscriptionContextBuilder.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Mocks/SubscriptionContextBuilder.cs index b243a0d07..db504ce63 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Mocks/SubscriptionContextBuilder.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Mocks/SubscriptionContextBuilder.cs @@ -21,6 +21,7 @@ namespace GraphQL.AspNet.Tests.Mocks using GraphQL.AspNet.Interfaces.Security; using GraphQL.AspNet.Interfaces.Subscriptions; using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.Structural; using Moq; diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/SchemaTestData/DuplicateEventNameController.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/SchemaTestData/DuplicateEventNameController.cs index fad8b2a2a..0044b1654 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/SchemaTestData/DuplicateEventNameController.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/SchemaTestData/DuplicateEventNameController.cs @@ -11,7 +11,7 @@ namespace GraphQL.AspNet.Tests.Schemas.SchemaTestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class DuplicateEventNameController : GraphController { diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/SchemaTestData/OneFieldMapController.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/SchemaTestData/OneFieldMapController.cs index 1ae37d7a7..65202f018 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/SchemaTestData/OneFieldMapController.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/SchemaTestData/OneFieldMapController.cs @@ -11,7 +11,7 @@ namespace GraphQL.AspNet.Tests.Schemas.SchemaTestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class OneFieldMapController : GraphController { diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/SchemaTestData/OneFieldMapWithEventNameController.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/SchemaTestData/OneFieldMapWithEventNameController.cs index 790745cd3..a3268cb4f 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/SchemaTestData/OneFieldMapWithEventNameController.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/SchemaTestData/OneFieldMapWithEventNameController.cs @@ -11,7 +11,7 @@ namespace GraphQL.AspNet.Tests.Schemas.SchemaTestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class OneFieldMapWithEventNameController : GraphController { diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/SchemaTestData/SimpleMethodController.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/SchemaTestData/SimpleMethodController.cs index ee752fd11..d9fcd495a 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/SchemaTestData/SimpleMethodController.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/SchemaTestData/SimpleMethodController.cs @@ -11,7 +11,7 @@ namespace GraphQL.AspNet.Tests.Schemas.SchemaTestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class SimpleMethodController : GraphController { diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/ClientSubscriptionTestData/ClientSubscriptionTestController.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/ClientSubscriptionTestData/ClientSubscriptionTestController.cs index 44d53b8ed..e7b0d44fc 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/ClientSubscriptionTestData/ClientSubscriptionTestController.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/ClientSubscriptionTestData/ClientSubscriptionTestController.cs @@ -11,7 +11,7 @@ namespace GraphQL.AspNet.Tests.SubscriptionServer.ClientSubscriptionTestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class ClientSubscriptionTestController : GraphController { diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlTransportWs/GqltwsClientAsserts.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlTransportWs/GqltwsClientAsserts.cs index 9cd2488b7..a5b72f3b8 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlTransportWs/GqltwsClientAsserts.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlTransportWs/GqltwsClientAsserts.cs @@ -12,7 +12,7 @@ namespace GraphQL.AspNet.Tests.SubscriptionServer.Protocols.GraphqlTransportWs using System.Text; using System.Text.Json; using GraphQL.AspNet.SubscriptionServer.Protocols.GraphqlTransportWs.Messaging; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Mocks; using GraphQL.AspNet.Tests.SubscriptionServer.Protocols.GraphqlTransportWs.GraphqlTransportWsData; using NUnit.Framework; diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlTransportWs/GqltwsClientProxyTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlTransportWs/GqltwsClientProxyTests.cs index 0e7b8f0de..9fb6e0a09 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlTransportWs/GqltwsClientProxyTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlTransportWs/GqltwsClientProxyTests.cs @@ -21,8 +21,8 @@ namespace GraphQL.AspNet.Tests.SubscriptionServer.Protocols.GraphqlTransportWs using GraphQL.AspNet.SubscriptionServer.Protocols.GraphqlTransportWs; using GraphQL.AspNet.SubscriptionServer.Protocols.GraphqlTransportWs.Messaging; using GraphQL.AspNet.SubscriptionServer.Protocols.GraphqlTransportWs.Messaging.Messages; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using GraphQL.AspNet.Web; using GraphQL.AspNet.Tests.Mocks; using GraphQL.AspNet.Tests.SubscriptionServer.Protocols.GraphqlTransportWs.GraphqlTransportWsData; diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlTransportWs/GqltwsConverterTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlTransportWs/GqltwsConverterTests.cs index f92bffd54..2360e85cb 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlTransportWs/GqltwsConverterTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlTransportWs/GqltwsConverterTests.cs @@ -21,8 +21,8 @@ namespace GraphQL.AspNet.Tests.SubscriptionServer.Protocols.GraphqlTransportWs using GraphQL.AspNet.SubscriptionServer.Protocols.GraphqlTransportWs.Messaging.Common; using GraphQL.AspNet.SubscriptionServer.Protocols.GraphqlTransportWs.Messaging.Converters; using GraphQL.AspNet.SubscriptionServer.Protocols.GraphqlTransportWs.Messaging.Messages; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using GraphQL.AspNet.Tests.Mocks; using GraphQL.AspNet.Tests.SubscriptionServer.Protocols.GraphqlTransportWs.GraphqlTransportWsData; using Microsoft.Extensions.DependencyInjection; diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlTransportWs/GraphqlTransportWsData/GqltwsDataMessageController.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlTransportWs/GraphqlTransportWsData/GqltwsDataMessageController.cs index e9ad4981b..399abb88b 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlTransportWs/GraphqlTransportWsData/GqltwsDataMessageController.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlTransportWs/GraphqlTransportWsData/GqltwsDataMessageController.cs @@ -11,7 +11,7 @@ namespace GraphQL.AspNet.Tests.SubscriptionServer.Protocols.GraphqlTransportWs.G { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class GqltwsDataMessageController : GraphController { diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlTransportWs/GraphqlTransportWsData/GqltwsResponseMessageConverter.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlTransportWs/GraphqlTransportWsData/GqltwsResponseMessageConverter.cs index 66f7c1983..ffdb3ee7f 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlTransportWs/GraphqlTransportWsData/GqltwsResponseMessageConverter.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlTransportWs/GraphqlTransportWsData/GqltwsResponseMessageConverter.cs @@ -14,7 +14,7 @@ namespace GraphQL.AspNet.Tests.SubscriptionServer.Protocols.GraphqlTransportWs.G using System.Text.Json.Serialization; using GraphQL.AspNet.SubscriptionServer.Protocols.GraphqlTransportWs; using GraphQL.AspNet.SubscriptionServer.Protocols.GraphqlTransportWs.Messaging; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; internal class GqltwsResponseMessageConverter : JsonConverter { diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlTransportWs/GraphqlTransportWsData/GqltwsSubscriptionController.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlTransportWs/GraphqlTransportWsData/GqltwsSubscriptionController.cs index 0784783f6..d6a3fd130 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlTransportWs/GraphqlTransportWsData/GqltwsSubscriptionController.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlTransportWs/GraphqlTransportWsData/GqltwsSubscriptionController.cs @@ -12,7 +12,7 @@ namespace GraphQL.AspNet.Tests.SubscriptionServer.Protocols.GraphqlTransportWs.G using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Interfaces.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class GqltwsSubscriptionController : GraphController { diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlWsLegacy/GraphqlWsLegacyClientAsserts.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlWsLegacy/GraphqlWsLegacyClientAsserts.cs index ca3609107..84f0242cd 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlWsLegacy/GraphqlWsLegacyClientAsserts.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlWsLegacy/GraphqlWsLegacyClientAsserts.cs @@ -12,7 +12,7 @@ namespace GraphQL.AspNet.Tests.SubscriptionServer.Protocols.GraphqlWsLegacy using System.Text; using System.Text.Json; using GraphQL.AspNet.SubscriptionServer.Protocols.GraphqlWsLegacy.Messaging; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Mocks; using GraphQL.AspNet.Tests.SubscriptionServer.Protocols.GraphqlWsLegacy.GraphqlWsLegacyData; using NUnit.Framework; diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlWsLegacy/GraphqlWsLegacyClientProxyTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlWsLegacy/GraphqlWsLegacyClientProxyTests.cs index 3dd66af5e..dcad906a1 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlWsLegacy/GraphqlWsLegacyClientProxyTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlWsLegacy/GraphqlWsLegacyClientProxyTests.cs @@ -20,8 +20,8 @@ namespace GraphQL.AspNet.Tests.SubscriptionServer.Protocols.GraphqlWsLegacy using GraphQL.AspNet.SubscriptionServer.Protocols.GraphqlWsLegacy; using GraphQL.AspNet.SubscriptionServer.Protocols.GraphqlWsLegacy.Messaging; using GraphQL.AspNet.SubscriptionServer.Protocols.GraphqlWsLegacy.Messaging.Messages; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using GraphQL.AspNet.Tests.Mocks; using GraphQL.AspNet.Tests.SubscriptionServer.Protocols.GraphqlWsLegacy.GraphqlWsLegacyData; using Microsoft.Extensions.DependencyInjection; diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlWsLegacy/GraphqlWsLegacyConverterTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlWsLegacy/GraphqlWsLegacyConverterTests.cs index c2ad46c18..41a9d7652 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlWsLegacy/GraphqlWsLegacyConverterTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlWsLegacy/GraphqlWsLegacyConverterTests.cs @@ -17,7 +17,6 @@ namespace GraphQL.AspNet.Tests.SubscriptionServer.Protocols.GraphqlWsLegacy using GraphQL.AspNet.Interfaces.Engine; using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using GraphQL.AspNet.Common.Extensions; using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; @@ -27,6 +26,7 @@ namespace GraphQL.AspNet.Tests.SubscriptionServer.Protocols.GraphqlWsLegacy using GraphQL.AspNet.SubscriptionServer.Protocols.GraphqlWsLegacy.Messaging.Converters; using GraphQL.AspNet.SubscriptionServer.Protocols.GraphqlWsLegacy.Messaging; using GraphQL.AspNet.SubscriptionServer.Protocols.GraphqlWsLegacy.Messaging.Common; + using GraphQL.AspNet.Tests.Common.CommonHelpers; [TestFixture] public class GraphqlWsLegacyConverterTests diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlWsLegacy/GraphqlWsLegacyData/GraphqlWsLegacyDataMessageController.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlWsLegacy/GraphqlWsLegacyData/GraphqlWsLegacyDataMessageController.cs index 4ea41140a..7ea13f9a7 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlWsLegacy/GraphqlWsLegacyData/GraphqlWsLegacyDataMessageController.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlWsLegacy/GraphqlWsLegacyData/GraphqlWsLegacyDataMessageController.cs @@ -11,7 +11,7 @@ namespace GraphQL.AspNet.Tests.SubscriptionServer.Protocols.GraphqlWsLegacy.Grap { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class GraphqlWsLegacyDataMessageController : GraphController { diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlWsLegacy/GraphqlWsLegacyData/GraphqlWsLegacyResponseMessageConverter.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlWsLegacy/GraphqlWsLegacyData/GraphqlWsLegacyResponseMessageConverter.cs index 3077979f0..33d94835d 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlWsLegacy/GraphqlWsLegacyData/GraphqlWsLegacyResponseMessageConverter.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlWsLegacy/GraphqlWsLegacyData/GraphqlWsLegacyResponseMessageConverter.cs @@ -14,7 +14,7 @@ namespace GraphQL.AspNet.Tests.SubscriptionServer.Protocols.GraphqlWsLegacy.Grap using System.Text.Json.Serialization; using GraphQL.AspNet.SubscriptionServer.Protocols.GraphqlWsLegacy; using GraphQL.AspNet.SubscriptionServer.Protocols.GraphqlWsLegacy.Messaging; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; internal class GraphqlWsLegacyResponseMessageConverter : JsonConverter { diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlWsLegacy/GraphqlWsLegacyData/GraphqlWsLegacySubscriptionController.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlWsLegacy/GraphqlWsLegacyData/GraphqlWsLegacySubscriptionController.cs index e946bb77c..11bd7d66f 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlWsLegacy/GraphqlWsLegacyData/GraphqlWsLegacySubscriptionController.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlWsLegacy/GraphqlWsLegacyData/GraphqlWsLegacySubscriptionController.cs @@ -11,7 +11,7 @@ namespace GraphQL.AspNet.Tests.SubscriptionServer.Protocols.GraphqlWsLegacy.Grap { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class GraphqlWsLegacySubscriptionController : GraphController { diff --git a/src/unit-tests/graphql-aspnet-testframework/GraphQLTemplateHelper.cs b/src/unit-tests/graphql-aspnet-testframework/GraphQLTemplateHelper.cs index bc1244264..ab9ffb6e9 100644 --- a/src/unit-tests/graphql-aspnet-testframework/GraphQLTemplateHelper.cs +++ b/src/unit-tests/graphql-aspnet-testframework/GraphQLTemplateHelper.cs @@ -18,10 +18,10 @@ namespace GraphQL.AspNet.Tests.Framework using GraphQL.AspNet.Directives; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal.TypeTemplates; using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Schemas.Generation; using GraphQL.AspNet.Schemas.Generation.TypeMakers; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Schemas.TypeSystem.Scalars; using GraphQL.AspNet.Tests.Framework.PipelineContextBuilders; diff --git a/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/QueryContextBuilder.cs b/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/QueryContextBuilder.cs index bfeda5882..386ed7354 100644 --- a/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/QueryContextBuilder.cs +++ b/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/QueryContextBuilder.cs @@ -21,6 +21,7 @@ namespace GraphQL.AspNet.Tests.Framework.PipelineContextBuilders using GraphQL.AspNet.Interfaces.Logging; using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Interfaces.Security; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.Structural; using Moq; @@ -159,7 +160,7 @@ public virtual QueryExecutionContext Build() foreach (var kvp in _sourceData) { var mockField = new Mock(); - mockField.Setup(x => x.FieldSource).Returns(Internal.TypeTemplates.GraphFieldSource.Action); + mockField.Setup(x => x.FieldSource).Returns(GraphFieldSource.Action); mockField.Setup(x => x.Route).Returns(kvp.Key); context.DefaultFieldSources.AddSource(mockField.Object, kvp.Value); } diff --git a/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/SingleMethodGraphControllerTemplate.cs b/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/SingleMethodGraphControllerTemplate.cs index cc16e52bb..b36536a29 100644 --- a/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/SingleMethodGraphControllerTemplate.cs +++ b/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/SingleMethodGraphControllerTemplate.cs @@ -11,7 +11,7 @@ namespace GraphQL.AspNet.Tests.Framework.PipelineContextBuilders { using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Interfaces.Internal; - using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; /// /// A mocked controller template that will selectively parse actions instead of the whole template. diff --git a/src/unit-tests/graphql-aspnet-testframework/TestServer.cs b/src/unit-tests/graphql-aspnet-testframework/TestServer.cs index e13c8222a..931ee0707 100644 --- a/src/unit-tests/graphql-aspnet-testframework/TestServer.cs +++ b/src/unit-tests/graphql-aspnet-testframework/TestServer.cs @@ -20,7 +20,6 @@ namespace GraphQL.AspNet.Tests.Framework using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Directives; using GraphQL.AspNet.Engine; - using GraphQL.AspNet.Engine.TypeMakers; using GraphQL.AspNet.Execution; using GraphQL.AspNet.Execution.Contexts; using GraphQL.AspNet.Execution.FieldResolution; diff --git a/src/unit-tests/graphql-aspnet-tests-common/CommonHelpers/CommonAssertions.cs b/src/unit-tests/graphql-aspnet-tests-common/CommonHelpers/CommonAssertions.cs index 592e33cee..703a05d39 100644 --- a/src/unit-tests/graphql-aspnet-tests-common/CommonHelpers/CommonAssertions.cs +++ b/src/unit-tests/graphql-aspnet-tests-common/CommonHelpers/CommonAssertions.cs @@ -7,12 +7,11 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Framework.CommonHelpers +namespace GraphQL.AspNet.Tests.Common.CommonHelpers { using System.Collections.Generic; using System.Text.Json; - using GraphQL.AspNet.Tests.Framework.CommonHelpers.JsonComparing; - using NUnit; + using GraphQL.AspNet.Tests.Common.CommonHelpers.JsonComparing; using NUnit.Framework; /// diff --git a/src/unit-tests/graphql-aspnet-tests-common/CommonHelpers/InheritedTwoPropertyObject.cs b/src/unit-tests/graphql-aspnet-tests-common/CommonHelpers/InheritedTwoPropertyObject.cs index cf57a4ae5..0cf503309 100644 --- a/src/unit-tests/graphql-aspnet-tests-common/CommonHelpers/InheritedTwoPropertyObject.cs +++ b/src/unit-tests/graphql-aspnet-tests-common/CommonHelpers/InheritedTwoPropertyObject.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Framework.CommonHelpers +namespace GraphQL.AspNet.Tests.Common.CommonHelpers { using System.Diagnostics; using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests-common/CommonHelpers/JsonComparing/JsonComparer.cs b/src/unit-tests/graphql-aspnet-tests-common/CommonHelpers/JsonComparing/JsonComparer.cs index 83dcd7d56..6f236d00d 100644 --- a/src/unit-tests/graphql-aspnet-tests-common/CommonHelpers/JsonComparing/JsonComparer.cs +++ b/src/unit-tests/graphql-aspnet-tests-common/CommonHelpers/JsonComparing/JsonComparer.cs @@ -7,9 +7,8 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Framework.CommonHelpers.JsonComparing +namespace GraphQL.AspNet.Tests.Common.CommonHelpers.JsonComparing { - using System; using System.Text.Json; using NUnit.Framework; diff --git a/src/unit-tests/graphql-aspnet-tests-common/CommonHelpers/JsonComparing/JsonComparrisonResult.cs b/src/unit-tests/graphql-aspnet-tests-common/CommonHelpers/JsonComparing/JsonComparrisonResult.cs index df17d79c6..692f7eeb0 100644 --- a/src/unit-tests/graphql-aspnet-tests-common/CommonHelpers/JsonComparing/JsonComparrisonResult.cs +++ b/src/unit-tests/graphql-aspnet-tests-common/CommonHelpers/JsonComparing/JsonComparrisonResult.cs @@ -7,10 +7,8 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Framework.CommonHelpers.JsonComparing +namespace GraphQL.AspNet.Tests.Common.CommonHelpers.JsonComparing { - using System; - /// /// A result containing the details of a json string comparrison. /// diff --git a/src/unit-tests/graphql-aspnet-tests-common/CommonHelpers/TwoPropertyGenericObject.cs b/src/unit-tests/graphql-aspnet-tests-common/CommonHelpers/TwoPropertyGenericObject.cs index ca93e24d9..ab1222590 100644 --- a/src/unit-tests/graphql-aspnet-tests-common/CommonHelpers/TwoPropertyGenericObject.cs +++ b/src/unit-tests/graphql-aspnet-tests-common/CommonHelpers/TwoPropertyGenericObject.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Framework.CommonHelpers +namespace GraphQL.AspNet.Tests.Common.CommonHelpers { /// /// A test object that has two properties of any type, both generic. diff --git a/src/unit-tests/graphql-aspnet-tests-common/CommonHelpers/TwoPropertyObject.cs b/src/unit-tests/graphql-aspnet-tests-common/CommonHelpers/TwoPropertyObject.cs index 28ab6c0ba..1ce05d9c7 100644 --- a/src/unit-tests/graphql-aspnet-tests-common/CommonHelpers/TwoPropertyObject.cs +++ b/src/unit-tests/graphql-aspnet-tests-common/CommonHelpers/TwoPropertyObject.cs @@ -7,11 +7,11 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Framework.CommonHelpers +namespace GraphQL.AspNet.Tests.Common.CommonHelpers { using System.Diagnostics; using GraphQL.AspNet.Attributes; - using GraphQL.AspNet.Tests.Framework.Interfaces; + using GraphQL.AspNet.Tests.Common.Interfaces; /// /// A represenstion of some data object with two properties of different value types. @@ -58,7 +58,7 @@ public TwoPropertyObject(string prop1, int prop2) /// public override string ToString() { - return $"{Property1}|{Property2}"; + return $"{this.Property1}|{this.Property2}"; } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests-common/CommonHelpers/TwoPropertyObjectV2.cs b/src/unit-tests/graphql-aspnet-tests-common/CommonHelpers/TwoPropertyObjectV2.cs index 3f235fd6f..6a80ca270 100644 --- a/src/unit-tests/graphql-aspnet-tests-common/CommonHelpers/TwoPropertyObjectV2.cs +++ b/src/unit-tests/graphql-aspnet-tests-common/CommonHelpers/TwoPropertyObjectV2.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Framework.CommonHelpers +namespace GraphQL.AspNet.Tests.Common.CommonHelpers { using System; using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests-common/CommonHelpers/TwoPropertyObjectV3.cs b/src/unit-tests/graphql-aspnet-tests-common/CommonHelpers/TwoPropertyObjectV3.cs index bbda54d51..ad7e645c1 100644 --- a/src/unit-tests/graphql-aspnet-tests-common/CommonHelpers/TwoPropertyObjectV3.cs +++ b/src/unit-tests/graphql-aspnet-tests-common/CommonHelpers/TwoPropertyObjectV3.cs @@ -6,11 +6,11 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Framework.CommonHelpers +namespace GraphQL.AspNet.Tests.Common.CommonHelpers { using System; using GraphQL.AspNet.Attributes; - using GraphQL.AspNet.Tests.Framework.Interfaces; + using GraphQL.AspNet.Tests.Common.Interfaces; /// /// A representation of a data object with two properties. diff --git a/src/unit-tests/graphql-aspnet-tests-common/CommonHelpers/TwoPropertyStruct.cs b/src/unit-tests/graphql-aspnet-tests-common/CommonHelpers/TwoPropertyStruct.cs index 58020806c..3cfe4bf54 100644 --- a/src/unit-tests/graphql-aspnet-tests-common/CommonHelpers/TwoPropertyStruct.cs +++ b/src/unit-tests/graphql-aspnet-tests-common/CommonHelpers/TwoPropertyStruct.cs @@ -7,11 +7,11 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Framework.CommonHelpers +namespace GraphQL.AspNet.Tests.Common.CommonHelpers { using System.Diagnostics; using GraphQL.AspNet.Attributes; - using GraphQL.AspNet.Tests.Framework.Interfaces; + using GraphQL.AspNet.Tests.Common.Interfaces; /// /// A represenstion of some data struct with two properties, both declared as graph exposed items. diff --git a/src/unit-tests/graphql-aspnet-tests-common/CommonHelpers/Utf8JsonReaderExtensions.cs b/src/unit-tests/graphql-aspnet-tests-common/CommonHelpers/Utf8JsonReaderExtensions.cs index 89c25a01a..dbfcd8740 100644 --- a/src/unit-tests/graphql-aspnet-tests-common/CommonHelpers/Utf8JsonReaderExtensions.cs +++ b/src/unit-tests/graphql-aspnet-tests-common/CommonHelpers/Utf8JsonReaderExtensions.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Framework.CommonHelpers +namespace GraphQL.AspNet.Tests.Common.CommonHelpers { using System; using System.Text; diff --git a/src/unit-tests/graphql-aspnet-tests-common/Interfaces/ISinglePropertyObject.cs b/src/unit-tests/graphql-aspnet-tests-common/Interfaces/ISinglePropertyObject.cs index 26ec8cd77..b567644cb 100644 --- a/src/unit-tests/graphql-aspnet-tests-common/Interfaces/ISinglePropertyObject.cs +++ b/src/unit-tests/graphql-aspnet-tests-common/Interfaces/ISinglePropertyObject.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Framework.Interfaces +namespace GraphQL.AspNet.Tests.Common.Interfaces { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Attributes/ApplyDirectiveAttributeExtensionTests.cs b/src/unit-tests/graphql-aspnet-tests/Attributes/ApplyDirectiveAttributeExtensionTests.cs index 3ba0d61c7..68aa8b92e 100644 --- a/src/unit-tests/graphql-aspnet-tests/Attributes/ApplyDirectiveAttributeExtensionTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Attributes/ApplyDirectiveAttributeExtensionTests.cs @@ -9,9 +9,9 @@ namespace GraphQL.AspNet.Tests.Attributes { using System.Linq; - using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Tests.Attributes.ApplyDirectiveAttributeTestData; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using NUnit.Framework; [TestFixture] diff --git a/src/unit-tests/graphql-aspnet-tests/Attributes/ApplyDirectiveAttributeTestData/ApplyDirectiveTestObject.cs b/src/unit-tests/graphql-aspnet-tests/Attributes/ApplyDirectiveAttributeTestData/ApplyDirectiveTestObject.cs index 2be6d630c..82a694de6 100644 --- a/src/unit-tests/graphql-aspnet-tests/Attributes/ApplyDirectiveAttributeTestData/ApplyDirectiveTestObject.cs +++ b/src/unit-tests/graphql-aspnet-tests/Attributes/ApplyDirectiveAttributeTestData/ApplyDirectiveTestObject.cs @@ -8,7 +8,7 @@ // ************************************************************* namespace GraphQL.AspNet.Tests.Attributes.ApplyDirectiveAttributeTestData { - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; [InheritedApplyDirective(typeof(TwoPropertyObject), "arg1")] internal class ApplyDirectiveTestObject diff --git a/src/unit-tests/graphql-aspnet-tests/Common/Extensions/LinqExtensionTests.cs b/src/unit-tests/graphql-aspnet-tests/Common/Extensions/LinqExtensionTests.cs index adeb91996..e114d7e70 100644 --- a/src/unit-tests/graphql-aspnet-tests/Common/Extensions/LinqExtensionTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Common/Extensions/LinqExtensionTests.cs @@ -13,7 +13,8 @@ namespace GraphQL.AspNet.Tests.Common.Extensions using System.Collections.Generic; using System.Linq; using GraphQL.AspNet.Common.Extensions; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + using GraphQL.AspNet.Tests.Common.Interfaces; using GraphQL.AspNet.Tests.Framework.Interfaces; using NUnit.Framework; diff --git a/src/unit-tests/graphql-aspnet-tests/Common/Extensions/TypeExtensionTests.cs b/src/unit-tests/graphql-aspnet-tests/Common/Extensions/TypeExtensionTests.cs index 5b3287e3c..0c7b971e6 100644 --- a/src/unit-tests/graphql-aspnet-tests/Common/Extensions/TypeExtensionTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Common/Extensions/TypeExtensionTests.cs @@ -15,9 +15,9 @@ namespace GraphQL.AspNet.Tests.Common.Extensions using System.Threading.Tasks; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Common.Extensions; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Common.Extensions.AttributeTestData; using GraphQL.AspNet.Tests.Common.Extensions.ReflectionExtensionTestData; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using GraphQL.AspNet.Tests.ThirdPartyDll; using GraphQL.AspNet.Tests.ThirdPartyDll.Model; using NUnit.Framework; diff --git a/src/unit-tests/graphql-aspnet-tests/Common/JsonNodeTests.cs b/src/unit-tests/graphql-aspnet-tests/Common/JsonNodeTests.cs index 914ab0fb8..be5d1b598 100644 --- a/src/unit-tests/graphql-aspnet-tests/Common/JsonNodeTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Common/JsonNodeTests.cs @@ -12,7 +12,8 @@ namespace GraphQL.AspNet.Tests.Common using System.Collections.Generic; using System.Text.Json.Nodes; using GraphQL.AspNet.Common.Extensions; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Common.JsonNodes; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using NUnit.Framework; [TestFixture] diff --git a/src/unit-tests/graphql-aspnet-tests/CommonHelpers/CompletePropertyObject.cs b/src/unit-tests/graphql-aspnet-tests/CommonHelpers/CompletePropertyObject.cs index 91bbe6d03..31cca6e55 100644 --- a/src/unit-tests/graphql-aspnet-tests/CommonHelpers/CompletePropertyObject.cs +++ b/src/unit-tests/graphql-aspnet-tests/CommonHelpers/CompletePropertyObject.cs @@ -10,7 +10,7 @@ // ReSharper disable All namespace GraphQL.AspNet.Tests.CommonHelpers { - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; /// /// An object representing a complex data object with properties that are a mix of scalars and objects. diff --git a/src/unit-tests/graphql-aspnet-tests/CommonHelpers/JsonComparingTests.cs b/src/unit-tests/graphql-aspnet-tests/CommonHelpers/JsonComparingTests.cs index 596bb4250..86e2a8f97 100644 --- a/src/unit-tests/graphql-aspnet-tests/CommonHelpers/JsonComparingTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/CommonHelpers/JsonComparingTests.cs @@ -10,7 +10,7 @@ namespace GraphQL.AspNet.Tests.CommonHelpers { using System.Text.Json; - using GraphQL.AspNet.Tests.Framework.CommonHelpers.JsonComparing; + using GraphQL.AspNet.Tests.Common.CommonHelpers.JsonComparing; using NUnit.Framework; /// diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/ConfigurationFieldNamingTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/ConfigurationFieldNamingTests.cs index e55e0da7c..94cf3c871 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/ConfigurationFieldNamingTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/ConfigurationFieldNamingTests.cs @@ -11,9 +11,9 @@ namespace GraphQL.AspNet.Tests.Configuration { using System.Threading.Tasks; using GraphQL.AspNet.Configuration.Formatting; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Configuration.ConfigurationTestData; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using NUnit.Framework; [TestFixture] diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/DirectiveApplicatorTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/DirectiveApplicatorTests.cs index f71f9b57c..58d1d9c75 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/DirectiveApplicatorTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/DirectiveApplicatorTests.cs @@ -14,8 +14,8 @@ namespace GraphQL.AspNet.Tests.Configuration using GraphQL.AspNet.Interfaces.Configuration; using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using NUnit.Framework; [TestFixture] diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/SchemaItemFilterExtensionTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/SchemaItemFilterExtensionTests.cs index c5e577da3..b5f0a6a57 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/SchemaItemFilterExtensionTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/SchemaItemFilterExtensionTests.cs @@ -14,9 +14,9 @@ namespace GraphQL.AspNet.Tests.Configuration using GraphQL.AspNet.Directives.Global; using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Configuration.SchemaItemExtensionTestData; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using Moq; using NUnit.Framework; diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/SchemaOptionsAddTypesTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/SchemaOptionsAddTypesTests.cs index 035567b20..03eafd86a 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/SchemaOptionsAddTypesTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/SchemaOptionsAddTypesTests.cs @@ -13,9 +13,9 @@ namespace GraphQL.AspNet.Tests.Configuration using GraphQL.AspNet.Configuration.Exceptions; using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Configuration.ConfigurationTestData; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using NUnit.Framework; [TestFixture] diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/SchemaOptionsApplyDirectiveTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/SchemaOptionsApplyDirectiveTests.cs index ac5655313..3d0a2cd7a 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/SchemaOptionsApplyDirectiveTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/SchemaOptionsApplyDirectiveTests.cs @@ -14,9 +14,9 @@ namespace GraphQL.AspNet.Tests.Configuration using GraphQL.AspNet.Configuration.Exceptions; using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Configuration.SchemaOptionsTestData; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/SchemaTypeToRegisterTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/SchemaTypeToRegisterTests.cs index 447b53d1b..c6df39f55 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/SchemaTypeToRegisterTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/SchemaTypeToRegisterTests.cs @@ -11,7 +11,7 @@ namespace GraphQL.AspNet.Tests.Configuration using System; using System.Collections.Generic; using GraphQL.AspNet.Configuration; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using NUnit.Framework; [TestFixture] diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/ServiceToRegisterTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/ServiceToRegisterTests.cs index e61cf8b97..7c112ec00 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/ServiceToRegisterTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/ServiceToRegisterTests.cs @@ -9,7 +9,8 @@ namespace GraphQL.AspNet.Tests.Configuration { using GraphQL.AspNet.Configuration; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + using GraphQL.AspNet.Tests.Common.Interfaces; using GraphQL.AspNet.Tests.Framework.Interfaces; using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedDirectiveTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedDirectiveTemplateTests.cs index 23c6a0267..52d2f41c0 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedDirectiveTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedDirectiveTemplateTests.cs @@ -13,7 +13,7 @@ namespace GraphQL.AspNet.Tests.Configuration.Templates using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Interfaces.Configuration; - using GraphQL.AspNet.Interfaces.Configuration.Templates; + using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Schemas.TypeSystem; using Microsoft.AspNetCore.Authorization; diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedMutationTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedMutationTemplateTests.cs index ab62ae5f4..1557d28fb 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedMutationTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedMutationTemplateTests.cs @@ -13,7 +13,7 @@ namespace GraphQL.AspNet.Tests.Configuration.Templates using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Interfaces.Configuration; - using GraphQL.AspNet.Interfaces.Configuration.Templates; + using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; using GraphQL.AspNet.Schemas; using Microsoft.Extensions.DependencyInjection; using Moq; diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedQueryGroupTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedQueryGroupTests.cs index c6ed9bbcc..cffa8095f 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedQueryGroupTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedQueryGroupTests.cs @@ -12,7 +12,6 @@ namespace GraphQL.AspNet.Tests.Configuration.Templates using System.Linq; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Configuration; - using GraphQL.AspNet.Interfaces.Configuration.Templates; using GraphQL.AspNet.Schemas; using Microsoft.AspNetCore.Authorization; using Microsoft.Extensions.DependencyInjection; diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedQueryTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedQueryTemplateTests.cs index adf6c7140..139afdac0 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedQueryTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedQueryTemplateTests.cs @@ -14,7 +14,7 @@ namespace GraphQL.AspNet.Tests.Configuration.Templates using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Execution; using GraphQL.AspNet.Interfaces.Configuration; - using GraphQL.AspNet.Interfaces.Configuration.Templates; + using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Tests.Framework; using Microsoft.Extensions.DependencyInjection; diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedTypeExtensionTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedTypeExtensionTemplateTests.cs index 0760fd2d5..826ac49df 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedTypeExtensionTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedTypeExtensionTemplateTests.cs @@ -14,9 +14,9 @@ namespace GraphQL.AspNet.Tests.Configuration.Templates using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Execution; using GraphQL.AspNet.Interfaces.Configuration; - using GraphQL.AspNet.Interfaces.Configuration.Templates; + using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; using GraphQL.AspNet.Schemas; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using Microsoft.AspNetCore.Authorization; using Microsoft.Extensions.DependencyInjection; using Moq; diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/ResolvedFieldTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/ResolvedFieldTemplateTests.cs index 98800d705..1e514e15e 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/ResolvedFieldTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/ResolvedFieldTemplateTests.cs @@ -12,9 +12,8 @@ namespace GraphQL.AspNet.Tests.Configuration.Templates using System.Linq; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Configuration; - using GraphQL.AspNet.Interfaces.Configuration.Templates; using GraphQL.AspNet.Schemas; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using Microsoft.AspNetCore.Authorization; using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; diff --git a/src/unit-tests/graphql-aspnet-tests/Controllers/ActionResults/ActionResultTests.cs b/src/unit-tests/graphql-aspnet-tests/Controllers/ActionResults/ActionResultTests.cs index 26308242e..74d60e5e9 100644 --- a/src/unit-tests/graphql-aspnet-tests/Controllers/ActionResults/ActionResultTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Controllers/ActionResults/ActionResultTests.cs @@ -14,7 +14,6 @@ namespace GraphQL.AspNet.Tests.Controllers.ActionResults using System.Threading.Tasks; using GraphQL.AspNet.Controllers.ActionResults; using GraphQL.AspNet.Controllers.InputModel; - using GraphQL.AspNet.Engine.TypeMakers; using GraphQL.AspNet.Execution; using GraphQL.AspNet.Execution.Contexts; using GraphQL.AspNet.Interfaces.Execution; diff --git a/src/unit-tests/graphql-aspnet-tests/Controllers/ActionResults/ActuionResultTestData/ActionableController.cs b/src/unit-tests/graphql-aspnet-tests/Controllers/ActionResults/ActuionResultTestData/ActionableController.cs index 903f31ed0..4f610fde7 100644 --- a/src/unit-tests/graphql-aspnet-tests/Controllers/ActionResults/ActuionResultTestData/ActionableController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Controllers/ActionResults/ActuionResultTestData/ActionableController.cs @@ -12,7 +12,7 @@ namespace GraphQL.AspNet.Tests.Controllers.ActionResults.ActuionResultTestData using System.Threading.Tasks; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class ActionableController : GraphController { diff --git a/src/unit-tests/graphql-aspnet-tests/Controllers/GraphControllerTests.cs b/src/unit-tests/graphql-aspnet-tests/Controllers/GraphControllerTests.cs index 92261bce7..c54882415 100644 --- a/src/unit-tests/graphql-aspnet-tests/Controllers/GraphControllerTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Controllers/GraphControllerTests.cs @@ -14,9 +14,9 @@ namespace GraphQL.AspNet.Tests.Controllers using System.Threading.Tasks; using GraphQL.AspNet.Controllers.ActionResults; using GraphQL.AspNet.Controllers.InputModel; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Controllers.ControllerTestData; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using NUnit.Framework; [TestFixture] diff --git a/src/unit-tests/graphql-aspnet-tests/Controllers/GraphQueryProcessorTests.cs b/src/unit-tests/graphql-aspnet-tests/Controllers/GraphQueryProcessorTests.cs index 1172e54b9..ba13218cd 100644 --- a/src/unit-tests/graphql-aspnet-tests/Controllers/GraphQueryProcessorTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Controllers/GraphQueryProcessorTests.cs @@ -15,9 +15,9 @@ namespace GraphQL.AspNet.Tests.Controllers using GraphQL.AspNet.Interfaces.Execution; using GraphQL.AspNet.Interfaces.Web; using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Controllers.GraphQueryControllerData; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using GraphQL.AspNet.Web; using Microsoft.AspNetCore.Http; using Microsoft.Net.Http.Headers; diff --git a/src/unit-tests/graphql-aspnet-tests/Directives/DeprecatedDirectiveTests.cs b/src/unit-tests/graphql-aspnet-tests/Directives/DeprecatedDirectiveTests.cs index 7236f3d7e..96542984b 100644 --- a/src/unit-tests/graphql-aspnet-tests/Directives/DeprecatedDirectiveTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Directives/DeprecatedDirectiveTests.cs @@ -24,7 +24,6 @@ namespace GraphQL.AspNet.Tests.Directives using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using Microsoft.Extensions.DependencyInjection; using Moq; using NUnit.Framework; @@ -33,6 +32,7 @@ namespace GraphQL.AspNet.Tests.Directives using GraphQL.AspNet.Interfaces.Execution.QueryPlans.InputArguments; using GraphQL.AspNet.Interfaces.Execution.Variables; using GraphQL.AspNet.Execution.QueryPlans.InputArguments; + using GraphQL.AspNet.Tests.Common.CommonHelpers; [TestFixture] [FixtureLifeCycle(LifeCycle.InstancePerTestCase)] diff --git a/src/unit-tests/graphql-aspnet-tests/Directives/DirectiveTestData/SimpleExecutionController.cs b/src/unit-tests/graphql-aspnet-tests/Directives/DirectiveTestData/SimpleExecutionController.cs index 97d876e14..0b3325b4e 100644 --- a/src/unit-tests/graphql-aspnet-tests/Directives/DirectiveTestData/SimpleExecutionController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Directives/DirectiveTestData/SimpleExecutionController.cs @@ -12,7 +12,7 @@ namespace GraphQL.AspNet.Tests.Directives.DirectiveTestData using System; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; [GraphRoute("simple")] public class SimpleExecutionController : GraphController diff --git a/src/unit-tests/graphql-aspnet-tests/Directives/DocumentAlterationDirectiveTests.cs b/src/unit-tests/graphql-aspnet-tests/Directives/DocumentAlterationDirectiveTests.cs index 3f615a262..d912e0f8f 100644 --- a/src/unit-tests/graphql-aspnet-tests/Directives/DocumentAlterationDirectiveTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Directives/DocumentAlterationDirectiveTests.cs @@ -10,9 +10,9 @@ namespace GraphQL.AspNet.Tests.Directives { using System.Threading.Tasks; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Directives.DirectiveTestData; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using NUnit.Framework; [TestFixture] diff --git a/src/unit-tests/graphql-aspnet-tests/Directives/IncludeDirectiveTests.cs b/src/unit-tests/graphql-aspnet-tests/Directives/IncludeDirectiveTests.cs index 550009019..94fbd026b 100644 --- a/src/unit-tests/graphql-aspnet-tests/Directives/IncludeDirectiveTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Directives/IncludeDirectiveTests.cs @@ -11,9 +11,9 @@ namespace GraphQL.AspNet.Tests.Directives { using System.Threading.Tasks; using GraphQL.AspNet.Directives.Global; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Directives.DirectiveTestData; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using NUnit.Framework; [TestFixture] diff --git a/src/unit-tests/graphql-aspnet-tests/Directives/IncludeSkipCombinedDirectiveTests.cs b/src/unit-tests/graphql-aspnet-tests/Directives/IncludeSkipCombinedDirectiveTests.cs index dc8b0bcfe..c036913b0 100644 --- a/src/unit-tests/graphql-aspnet-tests/Directives/IncludeSkipCombinedDirectiveTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Directives/IncludeSkipCombinedDirectiveTests.cs @@ -11,9 +11,9 @@ namespace GraphQL.AspNet.Tests.Directives { using System.Threading.Tasks; using GraphQL.AspNet.Directives.Global; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Directives.DirectiveTestData; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using NUnit.Framework; [TestFixture] diff --git a/src/unit-tests/graphql-aspnet-tests/Directives/RepeatableDirectiveTests.cs b/src/unit-tests/graphql-aspnet-tests/Directives/RepeatableDirectiveTests.cs index a6ed1be7e..713c8b2f3 100644 --- a/src/unit-tests/graphql-aspnet-tests/Directives/RepeatableDirectiveTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Directives/RepeatableDirectiveTests.cs @@ -10,9 +10,9 @@ namespace GraphQL.AspNet.Tests.Directives { using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Configuration.Exceptions; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Directives.DirectiveTestData; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; diff --git a/src/unit-tests/graphql-aspnet-tests/Directives/SkipDirectiveTests.cs b/src/unit-tests/graphql-aspnet-tests/Directives/SkipDirectiveTests.cs index e35fd88d1..a843217db 100644 --- a/src/unit-tests/graphql-aspnet-tests/Directives/SkipDirectiveTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Directives/SkipDirectiveTests.cs @@ -11,9 +11,9 @@ namespace GraphQL.AspNet.Tests.Directives { using System.Threading.Tasks; using GraphQL.AspNet.Directives.Global; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Directives.DirectiveTestData; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using NUnit.Framework; [TestFixture] diff --git a/src/unit-tests/graphql-aspnet-tests/Directives/SpecifiedByDirectiveTests.cs b/src/unit-tests/graphql-aspnet-tests/Directives/SpecifiedByDirectiveTests.cs index 9e259722c..afe40c79c 100644 --- a/src/unit-tests/graphql-aspnet-tests/Directives/SpecifiedByDirectiveTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Directives/SpecifiedByDirectiveTests.cs @@ -29,11 +29,11 @@ namespace GraphQL.AspNet.Tests.Directives using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using Microsoft.Extensions.DependencyInjection; using Moq; using NUnit.Framework; using GraphQL.AspNet.Execution.RulesEngine.RuleSets.DocumentValidation.QueryInputValueSteps; + using GraphQL.AspNet.Tests.Common.CommonHelpers; [TestFixture] [FixtureLifeCycle(LifeCycle.InstancePerTestCase)] diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/CustomObjectWithCustomScalarArgument.cs b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/CustomObjectWithCustomScalarArgument.cs index 4f3811fb6..165f70f88 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/CustomObjectWithCustomScalarArgument.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/CustomObjectWithCustomScalarArgument.cs @@ -10,7 +10,7 @@ namespace GraphQL.AspNet.Tests.Engine.DefaultSchemaFactoryTestData { using GraphQL.AspNet.Attributes; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class CustomObjectWithCustomScalarArgument { diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/CustomObjectWithCustomScalarField.cs b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/CustomObjectWithCustomScalarField.cs index 258efa429..7f6a58ddf 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/CustomObjectWithCustomScalarField.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/CustomObjectWithCustomScalarField.cs @@ -10,7 +10,7 @@ namespace GraphQL.AspNet.Tests.Engine.DefaultSchemaFactoryTestData { using GraphQL.AspNet.Attributes; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class CustomObjectWithCustomScalarField { diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/TwoPropertyObjectAsScalar.cs b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/TwoPropertyObjectAsScalar.cs index bbc0d2c30..bcedb9dff 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/TwoPropertyObjectAsScalar.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/TwoPropertyObjectAsScalar.cs @@ -12,7 +12,7 @@ namespace GraphQL.AspNet.Tests.Engine.DefaultSchemaFactoryTestData using System; using GraphQL.AspNet.Common; using GraphQL.AspNet.Schemas.TypeSystem.Scalars; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class TwoPropertyObjectAsScalar : ScalarGraphTypeBase { diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTests.cs b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTests.cs index 3f293cc35..8e92788ef 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTests.cs @@ -19,8 +19,9 @@ namespace GraphQL.AspNet.Tests.Engine using GraphQL.AspNet.Schemas.Generation; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + using GraphQL.AspNet.Tests.Common.Interfaces; using GraphQL.AspNet.Tests.Engine.DefaultSchemaFactoryTestData; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using GraphQL.AspNet.Tests.Framework.Interfaces; using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/DirectiveTypeMakerTests.cs b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/DirectiveTypeMakerTests.cs index 78cf8b482..5a93802ef 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/DirectiveTypeMakerTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/DirectiveTypeMakerTests.cs @@ -10,16 +10,16 @@ namespace GraphQL.AspNet.Tests.Engine.TypeMakers { using System.Linq; using GraphQL.AspNet.Engine; + using GraphQL.AspNet.Execution.Resolvers; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal.Resolvers; using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Schemas.Generation; using GraphQL.AspNet.Schemas.Generation.TypeMakers; using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.CommonHelpers; using GraphQL.AspNet.Tests.Engine.TypeMakers.TestData; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using NUnit.Framework; [TestFixture] diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/EnumGraphTypeMakerTests.cs b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/EnumGraphTypeMakerTests.cs index 038c3b902..0cabe13cb 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/EnumGraphTypeMakerTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/EnumGraphTypeMakerTests.cs @@ -12,7 +12,6 @@ namespace GraphQL.AspNet.Tests.Engine.TypeMakers using System.Linq; using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Configuration.Formatting; - using GraphQL.AspNet.Engine.TypeMakers; using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/FieldMaker_InputFieldTests.cs b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/FieldMaker_InputFieldTests.cs index c51081630..f733d8d02 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/FieldMaker_InputFieldTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/FieldMaker_InputFieldTests.cs @@ -10,14 +10,13 @@ namespace GraphQL.AspNet.Tests.Engine.TypeMakers { using System.Linq; - using GraphQL.AspNet.Engine.TypeMakers; using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Schemas.Generation; using GraphQL.AspNet.Schemas.Generation.TypeMakers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.CommonHelpers; using GraphQL.AspNet.Tests.Engine.TypeMakers.TestData; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using NUnit.Framework; public class FieldMaker_InputFieldTests : GraphTypeMakerTestBase diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/FieldMaker_StandardFieldTests.cs b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/FieldMaker_StandardFieldTests.cs index 797ee3978..4740c5528 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/FieldMaker_StandardFieldTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/FieldMaker_StandardFieldTests.cs @@ -9,12 +9,11 @@ namespace GraphQL.AspNet.Tests.Engine.TypeMakers { using System.Linq; - using GraphQL.AspNet.Engine.TypeMakers; using GraphQL.AspNet.Interfaces.Internal; - using GraphQL.AspNet.Internal.TypeTemplates; using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Schemas.Generation; using GraphQL.AspNet.Schemas.Generation.TypeMakers; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Security; @@ -138,7 +137,7 @@ public void PropertyGraphField_DefaultValuesCheck() var parent = obj.Object; var propInfo = typeof(SimplePropertyObject).GetProperty(nameof(SimplePropertyObject.Name)); - var template = new AspNet.Internal.TypeTemplates.PropertyGraphFieldTemplate(parent, propInfo, TypeKind.OBJECT); + var template = new PropertyGraphFieldTemplate(parent, propInfo, TypeKind.OBJECT); template.Parse(); template.ValidateOrThrow(); @@ -159,7 +158,7 @@ public void PropertyGraphField_GraphName_OverridesDefaultName() var parent = obj.Object; var propInfo = typeof(SimplePropertyObject).GetProperty(nameof(SimplePropertyObject.Age)); - var template = new AspNet.Internal.TypeTemplates.PropertyGraphFieldTemplate(parent, propInfo, TypeKind.OBJECT); + var template = new PropertyGraphFieldTemplate(parent, propInfo, TypeKind.OBJECT); template.Parse(); template.ValidateOrThrow(); @@ -184,7 +183,7 @@ public void PropertyGraphField_DirectivesAreAppliedToCreatedField() var parent = obj.Object; var propInfo = typeof(ObjectDirectiveTestItem).GetProperty(nameof(ObjectDirectiveTestItem.Prop1)); - var template = new AspNet.Internal.TypeTemplates.PropertyGraphFieldTemplate(parent, propInfo, TypeKind.OBJECT); + var template = new PropertyGraphFieldTemplate(parent, propInfo, TypeKind.OBJECT); template.Parse(); template.ValidateOrThrow(); diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/GraphTypeMakerTestBase.cs b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/GraphTypeMakerTestBase.cs index f909bdb68..3aec6ed20 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/GraphTypeMakerTestBase.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/GraphTypeMakerTestBase.cs @@ -12,13 +12,13 @@ namespace GraphQL.AspNet.Tests.Engine.TypeMakers using System; using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Engine; - using GraphQL.AspNet.Engine.TypeMakers; using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Tests.Framework; using GraphQL.AspNet.Schemas.Generation; using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Schemas.Generation.TypeMakers; using Microsoft.AspNetCore.Hosting.Server; using GraphQL.AspNet.Tests.CommonHelpers; diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/InputObjectGraphTypeMakerTests.cs b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/InputObjectGraphTypeMakerTests.cs index ee2aab5a8..f258a5004 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/InputObjectGraphTypeMakerTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/InputObjectGraphTypeMakerTests.cs @@ -11,12 +11,12 @@ namespace GraphQL.AspNet.Tests.Engine.TypeMakers using System.Linq; using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal; - using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Engine.TypeMakers.TestData; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using NUnit.Framework; [TestFixture] diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/ObjectGraphTypeMakerTests.cs b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/ObjectGraphTypeMakerTests.cs index e1f41fa2c..d65d8175d 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/ObjectGraphTypeMakerTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/ObjectGraphTypeMakerTests.cs @@ -16,10 +16,10 @@ namespace GraphQL.AspNet.Tests.Engine.TypeMakers using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Schemas.Generation; using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.CommonHelpers; using GraphQL.AspNet.Tests.Engine.TypeMakers.TestData; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using NUnit.Framework; [TestFixture] diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/ScalarGraphTypeMakerTests.cs b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/ScalarGraphTypeMakerTests.cs index 16081c822..8c0842808 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/ScalarGraphTypeMakerTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/ScalarGraphTypeMakerTests.cs @@ -10,10 +10,9 @@ namespace GraphQL.AspNet.Tests.Engine.TypeMakers { using System; using GraphQL.AspNet.Configuration.Formatting; - using GraphQL.AspNet.Engine.TypeMakers; - using GraphQL.AspNet.Internal.TypeTemplates; using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Schemas.Generation.TypeMakers; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Tests.Framework; using NUnit.Framework; diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/CustomScalarWithDirectives.cs b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/CustomScalarWithDirectives.cs index 4df497d82..18106e813 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/CustomScalarWithDirectives.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/CustomScalarWithDirectives.cs @@ -14,7 +14,7 @@ namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData using GraphQL.AspNet.Common; using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Schemas.TypeSystem.Scalars; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; [ApplyDirective(typeof(DirectiveWithArgs), 87, "scalar arg")] public class CustomScalarWithDirectives : ScalarGraphTypeBase diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/InputTestObject.cs b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/InputTestObject.cs index 2bcbf1d39..a38dad10a 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/InputTestObject.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/InputTestObject.cs @@ -12,7 +12,7 @@ namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData using System.ComponentModel.DataAnnotations; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class InputTestObject { diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/InputTestObjectWithDefaultFieldValues.cs b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/InputTestObjectWithDefaultFieldValues.cs index 35a5809f9..3fe095029 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/InputTestObjectWithDefaultFieldValues.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/InputTestObjectWithDefaultFieldValues.cs @@ -10,7 +10,7 @@ namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData { using System.ComponentModel.DataAnnotations; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class InputTestObjectWithDefaultFieldValues { diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/MultiMethodDirective.cs b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/MultiMethodDirective.cs index abef67a8c..25136a25e 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/MultiMethodDirective.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/MultiMethodDirective.cs @@ -13,7 +13,7 @@ namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData using GraphQL.AspNet.Directives; using GraphQL.AspNet.Interfaces.Controllers; using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; [Description("A Multi Method Directive")] public class MultiMethodDirective : GraphDirective diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/RepeatableDirective.cs b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/RepeatableDirective.cs index 067bc1957..294b24a5f 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/RepeatableDirective.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/RepeatableDirective.cs @@ -12,7 +12,7 @@ namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData using GraphQL.AspNet.Directives; using GraphQL.AspNet.Interfaces.Controllers; using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; [Repeatable] public class RepeatableDirective : GraphDirective diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/TypeCreationItem.cs b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/TypeCreationItem.cs index 908f40eaa..0710b4c81 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/TypeCreationItem.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/TypeCreationItem.cs @@ -10,7 +10,7 @@ namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData { using GraphQL.AspNet.Attributes; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class TypeCreationItem { diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/UnionProxyWithInvalidDirective.cs b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/UnionProxyWithInvalidDirective.cs index 511cd55a5..94b721492 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/UnionProxyWithInvalidDirective.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/UnionProxyWithInvalidDirective.cs @@ -10,7 +10,7 @@ namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; // not a directive [ApplyDirective(typeof(TwoPropertyObject), 121, "union directive")] diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/UnionTestController.cs b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/UnionTestController.cs index 682179986..fcb25b622 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/UnionTestController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/UnionTestController.cs @@ -14,7 +14,7 @@ namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Interfaces.Controllers; using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; [GraphRoute("unionTest")] public class UnionTestController : GraphController diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/UnionTypeMakerTests.cs b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/UnionTypeMakerTests.cs index 8f36ed1b2..e55a7f19b 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/UnionTypeMakerTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/UnionTypeMakerTests.cs @@ -10,7 +10,6 @@ namespace GraphQL.AspNet.Tests.Engine.TypeMakers { using System; using System.Linq; - using GraphQL.AspNet.Engine.TypeMakers; using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Schemas; diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/ApolloTracingTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/ApolloTracingTests.cs index 8fe9d1980..9f8231184 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/ApolloTracingTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/ApolloTracingTests.cs @@ -16,10 +16,10 @@ namespace GraphQL.AspNet.Tests.Execution using GraphQL.AspNet.Engine; using GraphQL.AspNet.Execution.Metrics; using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Execution.TestData.BatchResolverTestData; using GraphQL.AspNet.Tests.Execution.TestData.ExecutionPlanTestData; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using Microsoft.Extensions.DependencyInjection; using Moq; using NUnit.Framework; diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/AuthenticatedUserTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/AuthenticatedUserTests.cs index 97c48db54..60e0d8d39 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/AuthenticatedUserTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/AuthenticatedUserTests.cs @@ -9,9 +9,9 @@ namespace GraphQL.AspNet.Tests.Execution { using System.Threading.Tasks; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Execution.TestData.AuthenticatedUserTestData; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using NUnit.Framework; [TestFixture] diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/DefaultGraphResponseWriterTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/DefaultGraphResponseWriterTests.cs index 010349f40..2713810cf 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/DefaultGraphResponseWriterTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/DefaultGraphResponseWriterTests.cs @@ -21,9 +21,9 @@ namespace GraphQL.AspNet.Tests.Execution using GraphQL.AspNet.Interfaces.Engine; using GraphQL.AspNet.Interfaces.Execution; using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Execution.TestData.ExecutionPlanTestData; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using Moq; using NUnit.Framework; diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/ExecutionDirectiveTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/ExecutionDirectiveTests.cs index 4db4c5129..011d5dc70 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/ExecutionDirectiveTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/ExecutionDirectiveTests.cs @@ -13,9 +13,9 @@ namespace GraphQL.AspNet.Tests.Execution using GraphQL.AspNet.Directives; using GraphQL.AspNet.Interfaces.Execution.QueryPlans.DocumentParts; using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Execution.TestData.ExecutionDirectiveTestData; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/FieldSourceCollectionTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/FieldSourceCollectionTests.cs index 802d1d322..3421584c4 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/FieldSourceCollectionTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/FieldSourceCollectionTests.cs @@ -11,7 +11,7 @@ namespace GraphQL.AspNet.Tests.Execution { using GraphQL.AspNet.Execution; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.Structural; using Moq; using NUnit.Framework; diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/FragmentExecutionTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/FragmentExecutionTests.cs index 0247606b6..806895ee3 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/FragmentExecutionTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/FragmentExecutionTests.cs @@ -11,9 +11,9 @@ namespace GraphQL.AspNet.Tests.Execution { using System.Threading.Tasks; using GraphQL.AspNet.Common; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Execution.TestData.ExecutionPlanTestData; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using NUnit.Framework; [TestFixture] diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/GeneralExecutionTests_NET60.cs b/src/unit-tests/graphql-aspnet-tests/Execution/GeneralExecutionTests_NET60.cs index 58326e2d4..4dfa7ae6f 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/GeneralExecutionTests_NET60.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/GeneralExecutionTests_NET60.cs @@ -14,8 +14,8 @@ namespace GraphQL.AspNet.Tests.Execution using System.Threading.Tasks; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using NUnit.Framework; [TestFixture] diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionRuntimeFieldTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionRuntimeFieldTests.cs index 362d5d13e..86aae17a2 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionRuntimeFieldTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionRuntimeFieldTests.cs @@ -13,10 +13,10 @@ namespace GraphQL.AspNet.Tests.Execution using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Controllers.ActionResults; using GraphQL.AspNet.Interfaces.Controllers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Execution.TestData.RuntimeFieldTest; using GraphQL.AspNet.Tests.Execution.TestData.RuntimeFieldTestData; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionTests.cs index 09625a8ca..0def7e3a1 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionTests.cs @@ -12,9 +12,9 @@ namespace GraphQL.AspNet.Tests.Execution using System; using System.Threading.Tasks; using GraphQL.AspNet.Execution; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Execution.TestData.ExecutionPlanTestData; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using NUnit.Framework; [TestFixture] diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionTests2.cs b/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionTests2.cs index 5a2cf77ad..a7018e795 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionTests2.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionTests2.cs @@ -11,9 +11,9 @@ namespace GraphQL.AspNet.Tests.Execution { using System.Linq; using System.Threading.Tasks; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Execution.TestData.ExecutionPlanTestData; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using Newtonsoft.Json.Linq; using NUnit.Framework; diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/InheritanceExecutionTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/InheritanceExecutionTests.cs index ea1a20f8b..ce45f30ee 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/InheritanceExecutionTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/InheritanceExecutionTests.cs @@ -10,9 +10,9 @@ namespace GraphQL.AspNet.Tests.Execution { using System.Threading.Tasks; using GraphQL.AspNet.Execution; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Execution.TestData.InheritanceTestData; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using NUnit.Framework; [TestFixture] diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/InterfaceExecutionTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/InterfaceExecutionTests.cs index 827153742..8627aee9d 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/InterfaceExecutionTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/InterfaceExecutionTests.cs @@ -11,9 +11,9 @@ namespace GraphQL.AspNet.Tests.Execution { using System.Threading.Tasks; using GraphQL.AspNet.Execution; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Execution.TestData.InterfaceExtensionTestData; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using NUnit.Framework; [TestFixture] diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/IntrospectionTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/IntrospectionTests.cs index 7703127ea..83529f943 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/IntrospectionTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/IntrospectionTests.cs @@ -18,10 +18,10 @@ namespace GraphQL.AspNet.Tests.Execution using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Schemas.TypeSystem.Introspection.Model; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Execution.TestData; using GraphQL.AspNet.Tests.Execution.TestData.IntrospectionTestData; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using NUnit.Framework; [TestFixture] diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/ListManglerTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/ListManglerTests.cs index b4f7bf561..e2dcab4a3 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/ListManglerTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/ListManglerTests.cs @@ -15,8 +15,8 @@ namespace GraphQL.AspNet.Tests.Execution using GraphQL.AspNet.Common; using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Execution; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Execution.TestData.ListManglerTestData; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using NUnit.Framework; [TestFixture] diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/QueryPlans/ArgumentGeneratorTestData/InputController.cs b/src/unit-tests/graphql-aspnet-tests/Execution/QueryPlans/ArgumentGeneratorTestData/InputController.cs index e116ae7f6..4ec0c5c95 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/QueryPlans/ArgumentGeneratorTestData/InputController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/QueryPlans/ArgumentGeneratorTestData/InputController.cs @@ -13,7 +13,7 @@ namespace GraphQL.AspNet.Tests.Execution.QueryPlans.ArgumentGeneratorTestData using System.Linq; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class InputController : GraphController { diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/QueryPlans/ArgumentGeneratorTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/QueryPlans/ArgumentGeneratorTests.cs index 4dcb22f55..53a36fc46 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/QueryPlans/ArgumentGeneratorTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/QueryPlans/ArgumentGeneratorTests.cs @@ -18,9 +18,9 @@ namespace GraphQL.AspNet.Tests.Execution.QueryPlans using GraphQL.AspNet.Execution.Variables; using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Execution.QueryPlans.ArgumentGeneratorTestData; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using NUnit.Framework; [TestFixture] diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/QueryPlans/ExecutionPlanGenerationTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/QueryPlans/ExecutionPlanGenerationTests.cs index ac28597de..827f3238a 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/QueryPlans/ExecutionPlanGenerationTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/QueryPlans/ExecutionPlanGenerationTests.cs @@ -13,14 +13,15 @@ namespace GraphQL.AspNet.Tests.Execution.QueryPlans using System.Linq; using System.Threading.Tasks; using GraphQL.AspNet.Engine; + using GraphQL.AspNet.Execution.Resolvers; using GraphQL.AspNet.Execution.Variables; using GraphQL.AspNet.Interfaces.Execution; using GraphQL.AspNet.Interfaces.Execution.QueryPlans.DocumentParts; - using GraphQL.AspNet.Internal.Resolvers; using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + using GraphQL.AspNet.Tests.Common.Interfaces; using GraphQL.AspNet.Tests.Execution.QueryPlans.PlanGenerationTestData; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using GraphQL.AspNet.Tests.Framework.Interfaces; using NUnit.Framework; diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/QueryPlans/PlanGenerationTestData/SimplePlanGenerationController.cs b/src/unit-tests/graphql-aspnet-tests/Execution/QueryPlans/PlanGenerationTestData/SimplePlanGenerationController.cs index 013c9999d..12d9d322b 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/QueryPlans/PlanGenerationTestData/SimplePlanGenerationController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/QueryPlans/PlanGenerationTestData/SimplePlanGenerationController.cs @@ -12,7 +12,7 @@ namespace GraphQL.AspNet.Tests.Execution.QueryPlans.PlanGenerationTestData using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Interfaces.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; [GraphRoute("simple")] public class SimplePlanGenerationController : GraphController diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/InputResolverGeneratorTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/InputResolverGeneratorTests.cs index 676efaca5..3262f1340 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/InputResolverGeneratorTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/InputResolverGeneratorTests.cs @@ -7,12 +7,11 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal +namespace GraphQL.AspNet.Tests.Execution.Resolvers { using System; using System.Collections; using System.Collections.Generic; - using GraphQL.AspNet.Engine; using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Execution.Parsing; using GraphQL.AspNet.Execution.Parsing.Lexing; @@ -21,19 +20,18 @@ namespace GraphQL.AspNet.Tests.Internal using GraphQL.AspNet.Execution.Parsing.SyntaxNodes; using GraphQL.AspNet.Execution.QueryPlans.DocumentParts; using GraphQL.AspNet.Execution.QueryPlans.DocumentParts.SuppliedValues; + using GraphQL.AspNet.Execution.Resolvers; using GraphQL.AspNet.Execution.Source; using GraphQL.AspNet.Interfaces.Execution.QueryPlans.DocumentParts; using GraphQL.AspNet.Interfaces.Execution.QueryPlans.Resolvables; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal.Resolvers; using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Schemas.TypeSystem.Scalars; + using GraphQL.AspNet.Tests.Execution.Resolvers.InputValueNodeTestData; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Internal.InputValueNodeTestData; using Moq; using NUnit.Framework; - using NUnit.Framework.Constraints; [TestFixture] public class InputResolverGeneratorTests diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/InputValueNodeTestData/CoffeeCan.cs b/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/InputValueNodeTestData/CoffeeCan.cs index 7ccfc71a0..947ecfa0b 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/InputValueNodeTestData/CoffeeCan.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/InputValueNodeTestData/CoffeeCan.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.InputValueNodeTestData +namespace GraphQL.AspNet.Tests.Execution.Resolvers.InputValueNodeTestData { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/InputValueNodeTestData/Telephone.cs b/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/InputValueNodeTestData/Telephone.cs index 57edaf6f2..ea6e57ae3 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/InputValueNodeTestData/Telephone.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/InputValueNodeTestData/Telephone.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.InputValueNodeTestData +namespace GraphQL.AspNet.Tests.Execution.Resolvers.InputValueNodeTestData { using System.ComponentModel.DataAnnotations; using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ObjectMethodResolverTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ObjectMethodResolverTests.cs index 2ec88ea96..39b4b4a12 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ObjectMethodResolverTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ObjectMethodResolverTests.cs @@ -7,15 +7,15 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal +namespace GraphQL.AspNet.Tests.Execution.Resolvers { using System; using System.Threading.Tasks; - using GraphQL.AspNet.Internal.Resolvers; + using GraphQL.AspNet.Execution.Resolvers; using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + using GraphQL.AspNet.Tests.Execution.Resolvers.ValueResolversTestData; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; - using GraphQL.AspNet.Tests.Internal.ValueResolversTestData; using NUnit.Framework; [TestFixture] diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ObjectPropertyResolverTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ObjectPropertyResolverTests.cs index 53e06c7c1..0361965cb 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ObjectPropertyResolverTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ObjectPropertyResolverTests.cs @@ -7,17 +7,17 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal +namespace GraphQL.AspNet.Tests.Execution.Resolvers { using System; using System.Threading.Tasks; + using GraphQL.AspNet.Execution.Resolvers; using GraphQL.AspNet.Interfaces.Internal; - using GraphQL.AspNet.Internal.Resolvers; using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Common.Extensions.DiExtensionTestData; + using GraphQL.AspNet.Tests.Execution.Resolvers.ValueResolversTestData; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; - using GraphQL.AspNet.Tests.Internal.ValueResolversTestData; using Moq; using NUnit.Framework; diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ValueResolversTestData/IResolverInterface.cs b/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ValueResolversTestData/IResolverInterface.cs index a1c6b234b..94ea1b717 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ValueResolversTestData/IResolverInterface.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ValueResolversTestData/IResolverInterface.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.ValueResolversTestData +namespace GraphQL.AspNet.Tests.Execution.Resolvers.ValueResolversTestData { public interface IResolverInterface { diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ValueResolversTestData/ResolvableEnum.cs b/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ValueResolversTestData/ResolvableEnum.cs index b6ecd0d1d..8204c1849 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ValueResolversTestData/ResolvableEnum.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ValueResolversTestData/ResolvableEnum.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.ValueResolversTestData +namespace GraphQL.AspNet.Tests.Execution.Resolvers.ValueResolversTestData { public enum ResolvableEnum { diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ValueResolversTestData/ResolverObject.cs b/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ValueResolversTestData/ResolverObject.cs index a4c817a92..f9e395c9a 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ValueResolversTestData/ResolverObject.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ValueResolversTestData/ResolverObject.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.ValueResolversTestData +namespace GraphQL.AspNet.Tests.Execution.Resolvers.ValueResolversTestData { using System; using System.Threading.Tasks; diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ValueResolversTestData/ResolverStructA.cs b/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ValueResolversTestData/ResolverStructA.cs index 74466ac68..e0eb949f5 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ValueResolversTestData/ResolverStructA.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ValueResolversTestData/ResolverStructA.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.ValueResolversTestData +namespace GraphQL.AspNet.Tests.Execution.Resolvers.ValueResolversTestData { public struct ResolverStructA { diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ValueResolversTestData/ResolverStructB.cs b/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ValueResolversTestData/ResolverStructB.cs index 0133dc0e1..0e6149dfc 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ValueResolversTestData/ResolverStructB.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ValueResolversTestData/ResolverStructB.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.ValueResolversTestData +namespace GraphQL.AspNet.Tests.Execution.Resolvers.ValueResolversTestData { public struct ResolverStructB { diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/Response/ResponseWriterTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/Response/ResponseWriterTests.cs index dae825db8..933dffb3b 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/Response/ResponseWriterTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/Response/ResponseWriterTests.cs @@ -20,7 +20,7 @@ namespace GraphQL.AspNet.Tests.Execution.Response using GraphQL.AspNet.Interfaces.Execution; using GraphQL.AspNet.Interfaces.Execution.Response; using GraphQL.AspNet.Schemas; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using Moq; using NUnit.Framework; diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/Response/ResponseWriterTests_NET60.cs b/src/unit-tests/graphql-aspnet-tests/Execution/Response/ResponseWriterTests_NET60.cs index 8937d1f6a..c9bc609fa 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/Response/ResponseWriterTests_NET60.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/Response/ResponseWriterTests_NET60.cs @@ -21,7 +21,7 @@ namespace GraphQL.AspNet.Tests.Execution.Response using GraphQL.AspNet.Interfaces.Execution; using GraphQL.AspNet.Interfaces.Execution.Response; using GraphQL.AspNet.Schemas; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using Moq; using NUnit.Framework; diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/RulesEngine/DirectiveValidationRuleCheckTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/RulesEngine/DirectiveValidationRuleCheckTests.cs index 009f75195..4e19a64a7 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/RulesEngine/DirectiveValidationRuleCheckTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/RulesEngine/DirectiveValidationRuleCheckTests.cs @@ -15,9 +15,9 @@ namespace GraphQL.AspNet.Tests.Execution.RulesEngine using GraphQL.AspNet.Execution.RulesEngine; using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Execution.RulesEngine.DirectiveTestData; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using Moq; using NUnit.Framework; diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/RulesEngine/EnsureValidationRuleUrls.cs b/src/unit-tests/graphql-aspnet-tests/Execution/RulesEngine/EnsureValidationRuleUrls.cs index 46715f2bb..574ba2e57 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/RulesEngine/EnsureValidationRuleUrls.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/RulesEngine/EnsureValidationRuleUrls.cs @@ -16,6 +16,7 @@ namespace GraphQL.AspNet.Tests.Execution.RulesEngine using GraphQL.AspNet.Common; using GraphQL.AspNet.Common.Generics; using GraphQL.AspNet.Interfaces.Execution.RulesEngine; + using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Schemas.TypeSystem.Scalars; using NUnit.Framework; diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeTypeInferenceTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeTypeInferenceTests.cs index af7a2e53b..17b50e064 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeTypeInferenceTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeTypeInferenceTests.cs @@ -10,9 +10,9 @@ namespace GraphQL.AspNet.Tests.Execution { using System.Threading.Tasks; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Execution.TestData.ExecutionPlanTestData; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using NUnit.Framework; [TestFixture] diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/BatchResolverTestData/BatchInterfaceController.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/BatchResolverTestData/BatchInterfaceController.cs index 3a99b1def..13dbf9177 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/BatchResolverTestData/BatchInterfaceController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/BatchResolverTestData/BatchInterfaceController.cs @@ -14,7 +14,8 @@ namespace GraphQL.AspNet.Tests.Execution.TestData.BatchResolverTestData using GraphQL.AspNet.Common; using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Interfaces.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + using GraphQL.AspNet.Tests.Common.Interfaces; using GraphQL.AspNet.Tests.Framework.Interfaces; [GraphRoute("batch")] diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/BatchResolverTestData/BatchObjectController.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/BatchResolverTestData/BatchObjectController.cs index 1b91e5c10..97dd28d42 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/BatchResolverTestData/BatchObjectController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/BatchResolverTestData/BatchObjectController.cs @@ -15,7 +15,7 @@ namespace GraphQL.AspNet.Tests.Execution.TestData.BatchResolverTestData using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Interfaces.Controllers; using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; [GraphRoute("batch")] public class BatchObjectController : GraphController diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/BatchResolverTestData/BatchStructController.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/BatchResolverTestData/BatchStructController.cs index 578ccef3d..485b66845 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/BatchResolverTestData/BatchStructController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/BatchResolverTestData/BatchStructController.cs @@ -15,7 +15,7 @@ namespace GraphQL.AspNet.Tests.Execution.TestData.BatchResolverTestData using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Interfaces.Controllers; using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; [GraphRoute("batch")] public class BatchStructController : GraphController diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/DirectiveProcessorTypeSystemLocationTestData/UniontTestObject.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/DirectiveProcessorTypeSystemLocationTestData/UniontTestObject.cs index 9720daeaa..9c42958f7 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/DirectiveProcessorTypeSystemLocationTestData/UniontTestObject.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/DirectiveProcessorTypeSystemLocationTestData/UniontTestObject.cs @@ -11,7 +11,7 @@ namespace GraphQL.AspNet.Tests.Execution.TestData.DirectiveProcessorTypeSystemLo { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; [ApplyDirective(typeof(LocationTestDirective))] public class UniontTestObject : GraphUnionProxy diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionDirectiveInvocationTestData/ExecutionDirectiveTestController.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionDirectiveInvocationTestData/ExecutionDirectiveTestController.cs index 935abba8c..bb790c2ed 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionDirectiveInvocationTestData/ExecutionDirectiveTestController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionDirectiveInvocationTestData/ExecutionDirectiveTestController.cs @@ -10,7 +10,7 @@ namespace GraphQL.AspNet.Tests.Execution.TestData.ExecutionDirectiveInvocationTe { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class ExecutionDirectiveTestController : GraphController { diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionDirectiveTestData/AdjustBatchDataDirective.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionDirectiveTestData/AdjustBatchDataDirective.cs index 710395d97..4cd5ab89e 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionDirectiveTestData/AdjustBatchDataDirective.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionDirectiveTestData/AdjustBatchDataDirective.cs @@ -18,7 +18,7 @@ namespace GraphQL.AspNet.Tests.Execution.TestData.ExecutionDirectiveTestData using GraphQL.AspNet.Interfaces.Controllers; using GraphQL.AspNet.Interfaces.Execution.QueryPlans.DocumentParts; using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class AdjustBatchDataDirective : GraphDirective { diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionDirectiveTestData/DirectiveTestController.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionDirectiveTestData/DirectiveTestController.cs index b235e89e7..b9cad7fdc 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionDirectiveTestData/DirectiveTestController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionDirectiveTestData/DirectiveTestController.cs @@ -13,7 +13,7 @@ namespace GraphQL.AspNet.Tests.Execution.TestData.ExecutionDirectiveTestData using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Interfaces.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class DirectiveTestController : GraphController { diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionPlanTestData/ArrayAsEnumerableController.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionPlanTestData/ArrayAsEnumerableController.cs index 427eb6a19..32f643119 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionPlanTestData/ArrayAsEnumerableController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionPlanTestData/ArrayAsEnumerableController.cs @@ -12,7 +12,7 @@ namespace GraphQL.AspNet.Tests.Execution.TestData.ExecutionPlanTestData using System.Collections.Generic; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class ArrayAsEnumerableController : GraphController { diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionPlanTestData/ArrayOnReturnObjectMethodController.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionPlanTestData/ArrayOnReturnObjectMethodController.cs index edc1e0ddf..42a577800 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionPlanTestData/ArrayOnReturnObjectMethodController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionPlanTestData/ArrayOnReturnObjectMethodController.cs @@ -11,7 +11,7 @@ namespace GraphQL.AspNet.Tests.Execution.TestData.ExecutionPlanTestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class ArrayOnReturnObjectMethodController : GraphController { diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionPlanTestData/ArrayOnReturnObjectPropertyController.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionPlanTestData/ArrayOnReturnObjectPropertyController.cs index 42db58335..d99687280 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionPlanTestData/ArrayOnReturnObjectPropertyController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionPlanTestData/ArrayOnReturnObjectPropertyController.cs @@ -12,7 +12,7 @@ namespace GraphQL.AspNet.Tests.Execution.TestData.ExecutionPlanTestData using System.Collections.Generic; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class ArrayOnReturnObjectPropertyController : GraphController { diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionPlanTestData/ArrayThroughArrayDeclarationController.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionPlanTestData/ArrayThroughArrayDeclarationController.cs index 6782c1d0f..d984a638f 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionPlanTestData/ArrayThroughArrayDeclarationController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionPlanTestData/ArrayThroughArrayDeclarationController.cs @@ -11,7 +11,7 @@ namespace GraphQL.AspNet.Tests.Execution.TestData.ExecutionPlanTestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class ArrayThroughArrayDeclarationController : GraphController { diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionPlanTestData/ArrayThroughGraphActionAsEnumerableController.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionPlanTestData/ArrayThroughGraphActionAsEnumerableController.cs index 0b86ceb27..7ad6920f1 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionPlanTestData/ArrayThroughGraphActionAsEnumerableController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionPlanTestData/ArrayThroughGraphActionAsEnumerableController.cs @@ -13,7 +13,7 @@ namespace GraphQL.AspNet.Tests.Execution.TestData.ExecutionPlanTestData using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Interfaces.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class ArrayThroughGraphActionAsEnumerableController : GraphController { diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionPlanTestData/ExternalItemCollectionController.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionPlanTestData/ExternalItemCollectionController.cs index 1198aaf6e..3ea0a9179 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionPlanTestData/ExternalItemCollectionController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionPlanTestData/ExternalItemCollectionController.cs @@ -11,7 +11,7 @@ namespace GraphQL.AspNet.Tests.Execution.TestData.ExecutionPlanTestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class ExternalItemCollectionController : GraphController { diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionPlanTestData/InputObjectArrayController.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionPlanTestData/InputObjectArrayController.cs index 2f3386f61..6e0bb9407 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionPlanTestData/InputObjectArrayController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionPlanTestData/InputObjectArrayController.cs @@ -11,7 +11,7 @@ namespace GraphQL.AspNet.Tests.Execution.TestData.ExecutionPlanTestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class InputObjectArrayController : GraphController { diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionPlanTestData/NullableFieldArgumentTestController.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionPlanTestData/NullableFieldArgumentTestController.cs index 9c707b2d1..4523ae8ea 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionPlanTestData/NullableFieldArgumentTestController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionPlanTestData/NullableFieldArgumentTestController.cs @@ -10,7 +10,7 @@ namespace GraphQL.AspNet.Tests.Execution.TestData.ExecutionPlanTestData { using GraphQL.AspNet.Attributes; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class NullableFieldArgumentTestController : GraphIdController { diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionPlanTestData/SimpleExecutionController.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionPlanTestData/SimpleExecutionController.cs index ad01ea95d..9feec1f4c 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionPlanTestData/SimpleExecutionController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionPlanTestData/SimpleExecutionController.cs @@ -18,7 +18,7 @@ namespace GraphQL.AspNet.Tests.Execution.TestData.ExecutionPlanTestData using GraphQL.AspNet.Execution; using GraphQL.AspNet.Interfaces.Controllers; using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; [GraphRoute("simple")] public class SimpleExecutionController : GraphController diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionPlanTestData/TypeExtensionOnTwoPropertyObjectController.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionPlanTestData/TypeExtensionOnTwoPropertyObjectController.cs index f0bd1cb42..f3e6475c3 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionPlanTestData/TypeExtensionOnTwoPropertyObjectController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionPlanTestData/TypeExtensionOnTwoPropertyObjectController.cs @@ -12,7 +12,7 @@ namespace GraphQL.AspNet.Tests.Execution.TestData.ExecutionPlanTestData using System.Collections.Generic; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class TypeExtensionOnTwoPropertyObjectController : GraphController { diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionPlanTestData/UnionController.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionPlanTestData/UnionController.cs index 72a1fc458..6213ff24e 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionPlanTestData/UnionController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/ExecutionPlanTestData/UnionController.cs @@ -12,7 +12,7 @@ namespace GraphQL.AspNet.Tests.Execution.TestData.ExecutionPlanTestData using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Interfaces.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class UnionController : GraphController { diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/InputVariableExecutionTestData/InputValueController.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/InputVariableExecutionTestData/InputValueController.cs index f7fd58f95..0c248c58d 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/InputVariableExecutionTestData/InputValueController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/InputVariableExecutionTestData/InputValueController.cs @@ -13,7 +13,7 @@ namespace GraphQL.AspNet.Tests.Execution.TestData.InputVariableExecutionTestData using System.Linq; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; [GraphRoot] public class InputValueController : GraphController diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/InputVariableExecutionTestData/NullableVariableObjectController.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/InputVariableExecutionTestData/NullableVariableObjectController.cs index fda8ab697..43ef112cb 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/InputVariableExecutionTestData/NullableVariableObjectController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/InputVariableExecutionTestData/NullableVariableObjectController.cs @@ -11,7 +11,7 @@ namespace GraphQL.AspNet.Tests.Execution.TestData.InputVariableExecutionTestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class NullableVariableObjectController : GraphController { diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospecetionInputFieldTestData/NotRequiredNonNullableNotSetClassObject.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospecetionInputFieldTestData/NotRequiredNonNullableNotSetClassObject.cs index 1b5112b36..57404be05 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospecetionInputFieldTestData/NotRequiredNonNullableNotSetClassObject.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospecetionInputFieldTestData/NotRequiredNonNullableNotSetClassObject.cs @@ -11,7 +11,7 @@ namespace GraphQL.AspNet.Tests.Execution.TestData.IntrospecetionInputFieldTestDa { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class NotRequiredNonNullableNotSetClassObject { diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospecetionInputFieldTestData/NotRequiredNotSetClassObject.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospecetionInputFieldTestData/NotRequiredNotSetClassObject.cs index c5fa5f354..05ab61973 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospecetionInputFieldTestData/NotRequiredNotSetClassObject.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospecetionInputFieldTestData/NotRequiredNotSetClassObject.cs @@ -9,7 +9,7 @@ namespace GraphQL.AspNet.Tests.Execution.TestData.IntrospecetionInputFieldTestData { - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class NotRequiredNotSetClassObject { diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospecetionInputFieldTestData/NotRequiredSetClassObject.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospecetionInputFieldTestData/NotRequiredSetClassObject.cs index 2b8772626..339d7cba0 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospecetionInputFieldTestData/NotRequiredSetClassObject.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospecetionInputFieldTestData/NotRequiredSetClassObject.cs @@ -9,7 +9,7 @@ namespace GraphQL.AspNet.Tests.Execution.TestData.IntrospecetionInputFieldTestData { - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class NotRequiredSetClassObject { diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospecetionInputFieldTestData/RequiredClassObject.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospecetionInputFieldTestData/RequiredClassObject.cs index dd5187529..4df9024c4 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospecetionInputFieldTestData/RequiredClassObject.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospecetionInputFieldTestData/RequiredClassObject.cs @@ -10,7 +10,7 @@ namespace GraphQL.AspNet.Tests.Execution.TestData.IntrospecetionInputFieldTestData { using System.ComponentModel.DataAnnotations; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class RequiredClassObject { diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospecetionInputFieldTestData/StructNotRequiredNotSetClassObject.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospecetionInputFieldTestData/StructNotRequiredNotSetClassObject.cs index 18dd7e57f..41f4e2999 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospecetionInputFieldTestData/StructNotRequiredNotSetClassObject.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospecetionInputFieldTestData/StructNotRequiredNotSetClassObject.cs @@ -9,7 +9,7 @@ namespace GraphQL.AspNet.Tests.Execution.TestData.IntrospecetionInputFieldTestData { - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public struct StructNotRequiredNotSetClassObject { diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospecetionInputFieldTestData/StructNotRequiredSetClassObject.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospecetionInputFieldTestData/StructNotRequiredSetClassObject.cs index 0fbc63560..f5558139c 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospecetionInputFieldTestData/StructNotRequiredSetClassObject.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospecetionInputFieldTestData/StructNotRequiredSetClassObject.cs @@ -9,7 +9,7 @@ namespace GraphQL.AspNet.Tests.Execution.TestData.IntrospecetionInputFieldTestData { - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public struct StructNotRequiredSetClassObject { diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospecetionInputFieldTestData/StructRequiredClassObject.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospecetionInputFieldTestData/StructRequiredClassObject.cs index 744115c9b..3c0203ba4 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospecetionInputFieldTestData/StructRequiredClassObject.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospecetionInputFieldTestData/StructRequiredClassObject.cs @@ -10,7 +10,7 @@ namespace GraphQL.AspNet.Tests.Execution.TestData.IntrospecetionInputFieldTestData { using System.ComponentModel.DataAnnotations; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public struct StructRequiredClassObject { diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospectionTestData/ARepeatableDirective.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospectionTestData/ARepeatableDirective.cs index b97829246..506f8740f 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospectionTestData/ARepeatableDirective.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospectionTestData/ARepeatableDirective.cs @@ -12,7 +12,7 @@ namespace GraphQL.AspNet.Tests.Execution.TestData.IntrospectionTestData using GraphQL.AspNet.Directives; using GraphQL.AspNet.Interfaces.Controllers; using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; [Repeatable] public class ARepeatableDirective : GraphDirective diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospectionTestData/InputTestObject.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospectionTestData/InputTestObject.cs index 4df7f9e48..b3829946b 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospectionTestData/InputTestObject.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospectionTestData/InputTestObject.cs @@ -12,7 +12,7 @@ namespace GraphQL.AspNet.Tests.Execution.TestData.IntrospectionTestData using System.ComponentModel; using System.ComponentModel.DataAnnotations; using GraphQL.AspNet.Attributes; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; [GraphType(InputName = "InputObject")] [Description("input obj desc")] diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospectionTestData/IntrospectableObject.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospectionTestData/IntrospectableObject.cs index a9e3513ae..c01c70b29 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospectionTestData/IntrospectableObject.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospectionTestData/IntrospectableObject.cs @@ -10,7 +10,7 @@ namespace GraphQL.AspNet.Tests.Execution.TestData.IntrospectionTestData { using GraphQL.AspNet.Attributes; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class IntrospectableObject { diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospectionTestData/NonRepeatableDirective.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospectionTestData/NonRepeatableDirective.cs index d3b69d1cc..d9a1d84cc 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospectionTestData/NonRepeatableDirective.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospectionTestData/NonRepeatableDirective.cs @@ -12,7 +12,7 @@ namespace GraphQL.AspNet.Tests.Execution.TestData.IntrospectionTestData using GraphQL.AspNet.Directives; using GraphQL.AspNet.Interfaces.Controllers; using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class NonRepeatableDirective : GraphDirective { diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospectionTestData/TypeExtensionDescriptionController.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospectionTestData/TypeExtensionDescriptionController.cs index d005c3988..c661a5bb6 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospectionTestData/TypeExtensionDescriptionController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospectionTestData/TypeExtensionDescriptionController.cs @@ -12,7 +12,7 @@ namespace GraphQL.AspNet.Tests.Execution.TestData.IntrospectionTestData using System.ComponentModel; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class TypeExtensionDescriptionController : GraphController { diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/TypeSystemDirectiveTestData/MarkedUnion.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/TypeSystemDirectiveTestData/MarkedUnion.cs index 8d609f7e8..9a94b55db 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/TypeSystemDirectiveTestData/MarkedUnion.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/TypeSystemDirectiveTestData/MarkedUnion.cs @@ -10,7 +10,7 @@ namespace GraphQL.AspNet.Tests.Execution.TestData.TypeSystemDirectiveTestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; [ApplyDirective(typeof(UnionMarkerDirective))] public class MarkedUnion : GraphUnionProxy diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/UnionTypeExecutionTestData/PersonOrTeacher.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/UnionTypeExecutionTestData/PersonOrTeacher.cs index 6309f11d7..df90c39f5 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/UnionTypeExecutionTestData/PersonOrTeacher.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/UnionTypeExecutionTestData/PersonOrTeacher.cs @@ -11,7 +11,7 @@ namespace GraphQL.AspNet.Tests.Execution.TestData.UnionTypeExecutionTestData using System; using GraphQL.AspNet.Common; using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class PersonOrTeacher : GraphUnionProxy { diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/UnionTypeExecutionTestData/SchoolController.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/UnionTypeExecutionTestData/SchoolController.cs index c681993a6..82d5019a8 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/UnionTypeExecutionTestData/SchoolController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/UnionTypeExecutionTestData/SchoolController.cs @@ -12,7 +12,7 @@ namespace GraphQL.AspNet.Tests.Execution.TestData.UnionTypeExecutionTestData using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Interfaces.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class SchoolController : GraphController { diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TypeExtensionExecutionTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TypeExtensionExecutionTests.cs index 443363b4d..51faefc30 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TypeExtensionExecutionTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TypeExtensionExecutionTests.cs @@ -14,11 +14,11 @@ namespace GraphQL.AspNet.Tests.Execution using System.Threading.Tasks; using GraphQL.AspNet.Execution; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using Moq; using NUnit.Framework; using Microsoft.Extensions.DependencyInjection; using GraphQL.AspNet.Common.Extensions; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Execution.TestData.BatchResolverTestData; [TestFixture] diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TypeSystemDirectiveInvocationTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TypeSystemDirectiveInvocationTests.cs index 0ed5c62ee..edd89b3d3 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TypeSystemDirectiveInvocationTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TypeSystemDirectiveInvocationTests.cs @@ -10,9 +10,9 @@ namespace GraphQL.AspNet.Tests.Execution { using System.Threading.Tasks; using GraphQL.AspNet.Configuration.Exceptions; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Execution.TestData.TypeSystemDirectiveInvocationTestData; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using NUnit.Framework; [TestFixture] diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/UnionTypeExecutionTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/UnionTypeExecutionTests.cs index f4a4fd4fe..f5001ebf0 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/UnionTypeExecutionTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/UnionTypeExecutionTests.cs @@ -10,9 +10,9 @@ namespace GraphQL.AspNet.Tests.Execution { using System; using System.Threading.Tasks; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Execution.TestData.UnionTypeExecutionTestData; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using NUnit.Framework; [TestFixture] diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/VariableExecutionTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/VariableExecutionTests.cs index ab31b83e1..60288ddf8 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/VariableExecutionTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/VariableExecutionTests.cs @@ -13,10 +13,10 @@ namespace GraphQL.AspNet.Tests.Execution using System.ComponentModel.DataAnnotations; using System.Threading.Tasks; using GraphQL.AspNet.Execution; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Execution.TestData.InputVariableExecutionTestData; using GraphQL.AspNet.Tests.Execution.Variables; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/VariableKitchenSinkTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/VariableKitchenSinkTests.cs index 9d1212c29..0f66ea487 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/VariableKitchenSinkTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/VariableKitchenSinkTests.cs @@ -13,9 +13,9 @@ namespace GraphQL.AspNet.Tests.Execution using System.Collections.Generic; using System.Runtime.InteropServices; using System.Threading.Tasks; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Execution.TestData.VariableExecutionTestData; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using Microsoft.Extensions.Hosting; using Moq; using NUnit.Framework; diff --git a/src/unit-tests/graphql-aspnet-tests/Integration/MusicIndustryTests.cs b/src/unit-tests/graphql-aspnet-tests/Integration/MusicIndustryTests.cs index 62b714366..6ffc58c3b 100644 --- a/src/unit-tests/graphql-aspnet-tests/Integration/MusicIndustryTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Integration/MusicIndustryTests.cs @@ -11,8 +11,8 @@ namespace GraphQL.AspNet.Tests.Integration { using System.IO; using System.Threading.Tasks; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using GraphQL.AspNet.Tests.Integration.Model; using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; diff --git a/src/unit-tests/graphql-aspnet-tests/Middleware/DirectiveMiddlewareTestData/PipelineTestDirective.cs b/src/unit-tests/graphql-aspnet-tests/Middleware/DirectiveMiddlewareTestData/PipelineTestDirective.cs index e5988bcc0..55907e9fa 100644 --- a/src/unit-tests/graphql-aspnet-tests/Middleware/DirectiveMiddlewareTestData/PipelineTestDirective.cs +++ b/src/unit-tests/graphql-aspnet-tests/Middleware/DirectiveMiddlewareTestData/PipelineTestDirective.cs @@ -12,7 +12,7 @@ namespace GraphQL.AspNet.Tests.Middleware.DirectiveMiddlewareTestData using GraphQL.AspNet.Directives; using GraphQL.AspNet.Interfaces.Controllers; using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; internal class PipelineTestDirective : GraphDirective { diff --git a/src/unit-tests/graphql-aspnet-tests/Middleware/DirectivePipelineMiddlewareTests.cs b/src/unit-tests/graphql-aspnet-tests/Middleware/DirectivePipelineMiddlewareTests.cs index d9b8636d7..1659f8dac 100644 --- a/src/unit-tests/graphql-aspnet-tests/Middleware/DirectivePipelineMiddlewareTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Middleware/DirectivePipelineMiddlewareTests.cs @@ -16,8 +16,8 @@ namespace GraphQL.AspNet.Tests.Middleware using GraphQL.AspNet.Middleware.DirectiveExecution.Components; using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using GraphQL.AspNet.Tests.Middleware.DirectiveMiddlewareTestData; using NUnit.Framework; diff --git a/src/unit-tests/graphql-aspnet-tests/Middleware/QueryPipelineIntegrationTestData/SimpleExecutionController.cs b/src/unit-tests/graphql-aspnet-tests/Middleware/QueryPipelineIntegrationTestData/SimpleExecutionController.cs index d50589d5f..935d38441 100644 --- a/src/unit-tests/graphql-aspnet-tests/Middleware/QueryPipelineIntegrationTestData/SimpleExecutionController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Middleware/QueryPipelineIntegrationTestData/SimpleExecutionController.cs @@ -17,7 +17,7 @@ namespace GraphQL.AspNet.Tests.Middleware.QueryPipelineIntegrationTestData using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Execution; using GraphQL.AspNet.Interfaces.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; [GraphRoute("simple")] public class SimpleExecutionController : GraphController diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/DefaultTypeTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/DefaultTypeTests.cs index 7f644bf7f..cc4d908cd 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/DefaultTypeTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/DefaultTypeTests.cs @@ -12,6 +12,7 @@ namespace GraphQL.AspNet.Tests.Schemas using System.Linq; using System.Reflection; using GraphQL.AspNet.Engine; + using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Schemas.TypeSystem.Scalars; using NUnit.Framework; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionMethodTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionMethodTemplateTests.cs similarity index 87% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionMethodTemplateTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionMethodTemplateTests.cs index 413790786..f4c3594a8 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionMethodTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionMethodTemplateTests.cs @@ -7,20 +7,19 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.Templating { using System.Linq; using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Execution; using GraphQL.AspNet.Execution.Exceptions; - using GraphQL.AspNet.Interfaces.Execution; using GraphQL.AspNet.Interfaces.Internal; - using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; - using GraphQL.AspNet.Tests.Internal.Templating.ActionTestData; - using GraphQL.AspNet.Tests.Internal.Templating.DirectiveTestData; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ActionTestData; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.DirectiveTestData; using Moq; using NUnit.Framework; @@ -61,8 +60,8 @@ public void ActionTemplate_Parse_BasicPropertySets() Assert.AreEqual("path0", action.Parent.Name); Assert.AreEqual(methodInfo, action.Method); Assert.AreEqual(0, action.Arguments.Count); - Assert.IsFalse(action.Route.IsTopLevelField); - Assert.IsFalse(action.IsAsyncField); + Assert.IsFalse((bool)action.Route.IsTopLevelField); + Assert.IsFalse((bool)action.IsAsyncField); } [Test] @@ -72,7 +71,7 @@ public void ActionTemplate_Parse_MethodMarkedAsOperationIsAssignedARootPath() Assert.AreEqual(SchemaItemCollections.Query, action.Route.RootCollection); Assert.AreEqual(0, action.Arguments.Count); - Assert.IsFalse(action.IsAsyncField); + Assert.IsFalse((bool)action.IsAsyncField); Assert.AreEqual("[query]/path22", action.Route.Path); } @@ -85,9 +84,9 @@ public void ActionTemplate_Parse_WithValidDeclaredUnion_ParsesCorrectly() Assert.IsNotNull(action.UnionProxy); Assert.AreEqual(2, action.UnionProxy.Types.Count); Assert.AreEqual(action.ObjectType, typeof(object)); - Assert.IsTrue(action.TypeExpression.IsListOfItems); - Assert.IsTrue(action.UnionProxy.Types.Contains(typeof(UnionDataA))); - Assert.IsTrue(action.UnionProxy.Types.Contains(typeof(UnionDataB))); + Assert.IsTrue((bool)action.TypeExpression.IsListOfItems); + Assert.IsTrue((bool)action.UnionProxy.Types.Contains(typeof(UnionDataA))); + Assert.IsTrue((bool)action.UnionProxy.Types.Contains(typeof(UnionDataB))); Assert.IsNull(action.UnionProxy.Description); Assert.AreEqual("FragmentData", action.UnionProxy.Name); } @@ -146,7 +145,7 @@ public void ActionTemplate_ReturnTypeOfActionResult_WithDeclaredListDataType_Ren var action = this.CreateActionTemplate(nameof(ActionResultReturnTypeController.ActionResultMethodWithListReturnType)); Assert.AreEqual(typeof(TwoPropertyObject), action.ObjectType); - Assert.IsTrue(action.TypeExpression.IsListOfItems); + Assert.IsTrue((bool)action.TypeExpression.IsListOfItems); } [Test] @@ -190,11 +189,11 @@ public void ActionTemplate_ReturnTypeOfInterface_WithPossibleTypesAttribute_Retr var types = action.RetrieveRequiredTypes(); Assert.IsNotNull(types); - Assert.AreEqual(3, types.Count()); + Assert.AreEqual(3, Enumerable.Count(types)); - Assert.IsTrue(types.Any(x => x.Type == typeof(TestItemA))); - Assert.IsTrue(types.Any(x => x.Type == typeof(TestItemB))); - Assert.IsTrue(types.Any(x => x.Type == typeof(ITestItem))); + Assert.IsTrue(Enumerable.Any(types, x => x.Type == typeof(TestItemA))); + Assert.IsTrue(Enumerable.Any(types, x => x.Type == typeof(TestItemB))); + Assert.IsTrue(Enumerable.Any(types, x => x.Type == typeof(ITestItem))); } [Test] @@ -204,9 +203,9 @@ public void ActionTemplate_ReturnTypeOfInterface_WithoutPossibleTypesAttribute_D var types = action.RetrieveRequiredTypes(); Assert.IsNotNull(types); - Assert.AreEqual(1, types.Count()); + Assert.AreEqual(1, Enumerable.Count(types)); - Assert.IsTrue(types.Any(x => x.Type == typeof(ITestItem))); + Assert.IsTrue(Enumerable.Any(types, x => x.Type == typeof(ITestItem))); } [Test] @@ -253,7 +252,7 @@ public void ActionTemplate_ArrayOnInputParameter_RendersFine() var types = action.RetrieveRequiredTypes(); Assert.IsNotNull(types); - Assert.IsTrue(types.Any(x => x.Type == typeof(string))); + Assert.IsTrue(Enumerable.Any(types, x => x.Type == typeof(string))); Assert.AreEqual(1, action.Arguments.Count); Assert.AreEqual(typeof(TwoPropertyObject[]), action.Arguments[0].DeclaredArgumentType); @@ -265,9 +264,9 @@ public void Parse_AssignedDirective_IsTemplatized() { var action = this.CreateActionTemplate(nameof(ActionMethodWithDirectiveController.Execute)); - Assert.AreEqual(1, action.AppliedDirectives.Count()); + Assert.AreEqual(1, Enumerable.Count(action.AppliedDirectives)); - var appliedDirective = action.AppliedDirectives.First(); + var appliedDirective = Enumerable.First(action.AppliedDirectives); Assert.AreEqual(typeof(DirectiveWithArgs), appliedDirective.DirectiveType); Assert.AreEqual(new object[] { 202, "controller action arg" }, appliedDirective.Arguments); } diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/ActionMethodWithDirectiveController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/ActionMethodWithDirectiveController.cs similarity index 78% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/ActionMethodWithDirectiveController.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/ActionMethodWithDirectiveController.cs index 03606b8b7..438b3a26c 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/ActionMethodWithDirectiveController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/ActionMethodWithDirectiveController.cs @@ -6,11 +6,11 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ActionTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ActionTestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Internal.Templating.DirectiveTestData; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.DirectiveTestData; public class ActionMethodWithDirectiveController : GraphController { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/ActionResultReturnTypeController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/ActionResultReturnTypeController.cs similarity index 90% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/ActionResultReturnTypeController.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/ActionResultReturnTypeController.cs index 89257b75a..3edff47f7 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/ActionResultReturnTypeController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/ActionResultReturnTypeController.cs @@ -7,14 +7,13 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ActionTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ActionTestData { using System.Collections.Generic; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Interfaces.Controllers; - using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; [GraphRoute("path0")] public class ActionResultReturnTypeController : GraphController diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/ArrayInputMethodController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/ArrayInputMethodController.cs similarity index 80% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/ArrayInputMethodController.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/ArrayInputMethodController.cs index 15d3a1da6..ad630eb98 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/ArrayInputMethodController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/ArrayInputMethodController.cs @@ -7,11 +7,11 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ActionTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ActionTestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class ArrayInputMethodController : GraphController { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/ComplexityValueCheckController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/ComplexityValueCheckController.cs similarity index 87% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/ComplexityValueCheckController.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/ComplexityValueCheckController.cs index 774aedef7..7244db342 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/ComplexityValueCheckController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/ComplexityValueCheckController.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ActionTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ActionTestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/ContainerController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/ContainerController.cs similarity index 87% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/ContainerController.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/ContainerController.cs index 7dffe95fb..0cecd177a 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/ContainerController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/ContainerController.cs @@ -7,13 +7,13 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ActionTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ActionTestData { using System.ComponentModel; using System.Threading.Tasks; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; [GraphRoute("path0")] public class ContainerController : GraphController diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/CustomNamedItem.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/CustomNamedItem.cs similarity index 83% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/CustomNamedItem.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/CustomNamedItem.cs index 3d55db3a7..f50372523 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/CustomNamedItem.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/CustomNamedItem.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ActionTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ActionTestData { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/ITestItem.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/ITestItem.cs similarity index 81% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/ITestItem.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/ITestItem.cs index fac10e20a..4e3515542 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/ITestItem.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/ITestItem.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ActionTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ActionTestData { public interface ITestItem { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/IUnionTestDataItem.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/IUnionTestDataItem.cs similarity index 83% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/IUnionTestDataItem.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/IUnionTestDataItem.cs index e53bd61e2..8a35eda2b 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/IUnionTestDataItem.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/IUnionTestDataItem.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ActionTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ActionTestData { public interface IUnionTestDataItem { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/InterfaceReturnTypeController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/InterfaceReturnTypeController.cs similarity index 91% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/InterfaceReturnTypeController.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/InterfaceReturnTypeController.cs index a8fcc76bf..9a0800199 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/InterfaceReturnTypeController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/InterfaceReturnTypeController.cs @@ -7,11 +7,11 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ActionTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ActionTestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class InterfaceReturnTypeController : GraphController { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/OneMethodController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/OneMethodController.cs similarity index 83% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/OneMethodController.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/OneMethodController.cs index 39680972c..04f84f8a8 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/OneMethodController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/OneMethodController.cs @@ -7,12 +7,12 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ActionTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ActionTestData { using System.ComponentModel; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; [GraphRoute("path0")] public class OneMethodController : GraphController diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/ScalarInUnionController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/ScalarInUnionController.cs similarity index 88% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/ScalarInUnionController.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/ScalarInUnionController.cs index 98ebd0fcf..005adc77d 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/ScalarInUnionController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/ScalarInUnionController.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ActionTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ActionTestData { using System; using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/TestItemA.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/TestItemA.cs similarity index 82% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/TestItemA.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/TestItemA.cs index da307edee..6d72ed2e1 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/TestItemA.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/TestItemA.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ActionTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ActionTestData { public class TestItemA : ITestItem { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/TestItemB.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/TestItemB.cs similarity index 82% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/TestItemB.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/TestItemB.cs index e1b6b1701..cffd177a8 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/TestItemB.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/TestItemB.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ActionTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ActionTestData { public class TestItemB : ITestItem { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/UnionDataA.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/UnionDataA.cs similarity index 84% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/UnionDataA.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/UnionDataA.cs index c1d333bd1..b891b5227 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/UnionDataA.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/UnionDataA.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ActionTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ActionTestData { public class UnionDataA : IUnionTestDataItem { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/UnionDataB.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/UnionDataB.cs similarity index 84% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/UnionDataB.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/UnionDataB.cs index ce2ae0721..1fa57e14a 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/UnionDataB.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/UnionDataB.cs @@ -6,7 +6,7 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ActionTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ActionTestData { public class UnionDataB : IUnionTestDataItem { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/UnionTestController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/UnionTestController.cs similarity index 92% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/UnionTestController.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/UnionTestController.cs index 3f634e127..84fae65f2 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/UnionTestController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/UnionTestController.cs @@ -7,14 +7,13 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ActionTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ActionTestData { using System; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Interfaces.Controllers; - using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; [GraphRoute("unionTest")] public class UnionTestController : GraphController diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/UnionTestProxy.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/UnionTestProxy.cs similarity index 91% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/UnionTestProxy.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/UnionTestProxy.cs index e6521469a..5e68cbbe2 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ActionTestData/UnionTestProxy.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/UnionTestProxy.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ActionTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ActionTestData { using System; using System.Collections.Generic; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/AppliedDirectiveTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/AppliedDirectiveTemplateTests.cs similarity index 93% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/AppliedDirectiveTemplateTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/AppliedDirectiveTemplateTests.cs index a22af7caf..152cfef88 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/AppliedDirectiveTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/AppliedDirectiveTemplateTests.cs @@ -6,13 +6,13 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.Templating { using System; using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Interfaces.Internal; - using GraphQL.AspNet.Internal.TypeTemplates; - using GraphQL.AspNet.Tests.Internal.Templating.DirectiveTestData; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.DirectiveTestData; using Moq; using NUnit.Framework; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ArgumentTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ArgumentTemplateTests.cs similarity index 90% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ArgumentTemplateTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ArgumentTemplateTests.cs index 175d3c84e..6e8fc8b56 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ArgumentTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ArgumentTemplateTests.cs @@ -7,8 +7,9 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates { + using System.Collections; using System.Collections.Generic; using System.Linq; using System.Reflection; @@ -16,17 +17,18 @@ namespace GraphQL.AspNet.Tests.Internal.Templating using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Tests.CommonHelpers; - using GraphQL.AspNet.Tests.Internal.Templating.DirectiveTestData; - using GraphQL.AspNet.Tests.Internal.Templating.ParameterTestData; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.DirectiveTestData; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ParameterTestData; using Moq; using NUnit.Framework; [TestFixture] public class ArgumentTemplateTests { - private AspNet.Internal.TypeTemplates.GraphArgumentTemplate ExtractParameterTemplate(string paramName, out ParameterInfo paramInfo) + private GraphArgumentTemplate ExtractParameterTemplate(string paramName, out ParameterInfo paramInfo) { paramInfo = typeof(ParameterTestClass) .GetMethod(nameof(ParameterTestClass.TestMethod)) @@ -45,7 +47,7 @@ private AspNet.Internal.TypeTemplates.GraphArgumentTemplate ExtractParameterTemp nameof(ParameterTestClass.TestMethod))); mockMethod.Setup(x => x.Route).Returns(route); - var argTemplate = new AspNet.Internal.TypeTemplates.GraphArgumentTemplate(mockMethod.Object, paramInfo); + var argTemplate = new GraphArgumentTemplate(mockMethod.Object, paramInfo); argTemplate.Parse(); argTemplate.ValidateOrThrow(); @@ -59,7 +61,7 @@ public void StringParam_ParsesCorrectly() Assert.AreEqual(paramInfo.Name, template.Name); Assert.AreEqual(paramInfo, template.Parameter); Assert.AreEqual(null, template.Description); - Assert.IsEmpty(template.TypeExpression.Wrappers); + Assert.IsEmpty((IEnumerable)template.TypeExpression.Wrappers); Assert.IsNull(template.DefaultValue); Assert.AreEqual($"{nameof(ParameterTestClass)}.{nameof(ParameterTestClass.TestMethod)}.stringArg", template.InternalFullName); Assert.AreEqual("stringArg", template.InternalName); @@ -99,14 +101,14 @@ public void ValueTypeParam_SetsCorrectly() public void NullableTParam_WithNoDefaultValue_SetsFieldOptionsAsNotNull() { var template = this.ExtractParameterTemplate("nullableIntArg", out var paramInfo); - Assert.IsEmpty(template.TypeExpression.Wrappers); + Assert.IsEmpty((IEnumerable)template.TypeExpression.Wrappers); } [Test] public void ReferenceParam_ParsesCorrectly() { var template = this.ExtractParameterTemplate("objectArg", out var paramInfo); - Assert.IsEmpty(template.TypeExpression.Wrappers); + Assert.IsEmpty((IEnumerable)template.TypeExpression.Wrappers); } [Test] @@ -160,7 +162,7 @@ public void StringReference_WithNullDefaultValue_SetsCorrectly() { var template = this.ExtractParameterTemplate("defaultValueStringArg", out var paramInfo); Assert.AreEqual(typeof(string), template.Parameter.ParameterType); - Assert.IsEmpty(template.TypeExpression.Wrappers); + Assert.IsEmpty((IEnumerable)template.TypeExpression.Wrappers); Assert.IsNull(template.DefaultValue); } @@ -169,7 +171,7 @@ public void StringReference_WithASuppliedDefaultValue_SetsCorrectly() { var template = this.ExtractParameterTemplate("defaultValueStringArgWithValue", out var paramInfo); Assert.AreEqual(typeof(string), template.Parameter.ParameterType); - Assert.IsEmpty(template.TypeExpression.Wrappers); + Assert.IsEmpty((IEnumerable)template.TypeExpression.Wrappers); Assert.AreEqual("abc", template.DefaultValue); } @@ -177,7 +179,7 @@ public void StringReference_WithASuppliedDefaultValue_SetsCorrectly() public void NullableTParam_WithDefaultValue_SetsFieldOptionsAsNullable() { var template = this.ExtractParameterTemplate("defaultValueNullableIntArg", out var paramInfo); - Assert.IsEmpty(template.TypeExpression.Wrappers); + Assert.IsEmpty((IEnumerable)template.TypeExpression.Wrappers); Assert.AreEqual(5, template.DefaultValue); } @@ -230,9 +232,9 @@ public void StupidDeepArray_ParsesCorrectTypeExpression() public void Parse_AssignedDirective_IsTemplatized() { var template = this.ExtractParameterTemplate("paramDirective", out var paramInfo); - Assert.AreEqual(1, template.AppliedDirectives.Count()); + Assert.AreEqual(1, Enumerable.Count(template.AppliedDirectives)); - var appliedDirective = template.AppliedDirectives.First(); + var appliedDirective = Enumerable.First(template.AppliedDirectives); Assert.AreEqual(typeof(DirectiveWithArgs), appliedDirective.DirectiveType); Assert.AreEqual(new object[] { 77, "param arg" }, appliedDirective.Arguments); } diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTemplateTests.cs similarity index 65% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTemplateTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTemplateTests.cs index 2dbb3d5ee..7f5feee29 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTemplateTests.cs @@ -7,18 +7,18 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates { + using System.Collections.Generic; using System.Linq; - using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Execution.Exceptions; - using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; - using GraphQL.AspNet.Tests.Internal.Templating.ControllerTestData; - using GraphQL.AspNet.Tests.Internal.Templating.DirectiveTestData; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ControllerTestData; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.DirectiveTestData; using NUnit.Framework; [TestFixture] @@ -53,12 +53,12 @@ public void Parse_OverloadedMethodsOnDifferentRoots_ParsesCorrectly() template.Parse(); template.ValidateOrThrow(); - Assert.AreEqual(3, template.FieldTemplates.Count()); - Assert.AreEqual(2, template.Actions.Count()); - Assert.AreEqual(1, template.Extensions.Count()); - Assert.IsTrue(template.FieldTemplates.ContainsKey($"[mutation]/TwoMethodsDifferentRoots/{nameof(TwoMethodsDifferentRootsController.ActionMethodNoAttributes)}")); - Assert.IsTrue(template.FieldTemplates.ContainsKey($"[query]/TwoMethodsDifferentRoots/{nameof(TwoMethodsDifferentRootsController.ActionMethodNoAttributes)}")); - Assert.IsTrue(template.FieldTemplates.ContainsKey($"[type]/TwoPropertyObject/Property3")); + Assert.AreEqual(3, Enumerable.Count>(template.FieldTemplates)); + Assert.AreEqual(2, Enumerable.Count(template.Actions)); + Assert.AreEqual(1, Enumerable.Count(template.Extensions)); + Assert.IsTrue((bool)template.FieldTemplates.ContainsKey($"[mutation]/TwoMethodsDifferentRoots/{nameof(TwoMethodsDifferentRootsController.ActionMethodNoAttributes)}")); + Assert.IsTrue((bool)template.FieldTemplates.ContainsKey($"[query]/TwoMethodsDifferentRoots/{nameof(TwoMethodsDifferentRootsController.ActionMethodNoAttributes)}")); + Assert.IsTrue((bool)template.FieldTemplates.ContainsKey($"[type]/TwoPropertyObject/Property3")); } [Test] @@ -72,9 +72,9 @@ public void Parse_ReturnArrayOnAction_ParsesCorrectly() template.Parse(); template.ValidateOrThrow(); - Assert.AreEqual(1, template.Actions.Count()); + Assert.AreEqual(1, Enumerable.Count(template.Actions)); - var action = template.Actions.ElementAt(0); + var action = Enumerable.ElementAt(template.Actions, 0); Assert.AreEqual(typeof(string[]), action.DeclaredReturnType); Assert.AreEqual(expectedTypeExpression, action.TypeExpression); } @@ -90,9 +90,9 @@ public void Parse_ArrayOnInputParameter_ParsesCorrectly() template.Parse(); template.ValidateOrThrow(); - Assert.AreEqual(1, template.Actions.Count()); + Assert.AreEqual(1, Enumerable.Count(template.Actions)); - var action = template.Actions.ElementAt(0); + var action = Enumerable.ElementAt(template.Actions, 0); Assert.AreEqual(typeof(string), action.DeclaredReturnType); Assert.AreEqual(1, action.Arguments.Count); Assert.AreEqual(expectedTypeExpression, action.Arguments[0].TypeExpression); @@ -105,9 +105,9 @@ public void Parse_AssignedDirective_IsTemplatized() template.Parse(); template.ValidateOrThrow(); - Assert.AreEqual(1, template.AppliedDirectives.Count()); + Assert.AreEqual(1, Enumerable.Count(template.AppliedDirectives)); - var appliedDirective = template.AppliedDirectives.First(); + var appliedDirective = Enumerable.First(template.AppliedDirectives); Assert.AreEqual(typeof(DirectiveWithArgs), appliedDirective.DirectiveType); Assert.AreEqual(new object[] { 101, "controller arg" }, appliedDirective.Arguments); } @@ -119,9 +119,9 @@ public void Parse_StaticMethodsWithProperGraphFieldDeclarations_AreSkipped() template.Parse(); template.ValidateOrThrow(); - Assert.AreEqual(1, template.Actions.Count()); + Assert.AreEqual(1, Enumerable.Count(template.Actions)); - var action = template.Actions.First(); + var action = Enumerable.First(template.Actions); Assert.AreEqual(nameof(ControllerWithStaticMethod.InstanceMethod), action.Name); } } diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/ArrayInputParamController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/ArrayInputParamController.cs similarity index 80% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/ArrayInputParamController.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/ArrayInputParamController.cs index aace60508..8138b96f1 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/ArrayInputParamController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/ArrayInputParamController.cs @@ -7,11 +7,11 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ControllerTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ControllerTestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class ArrayInputParamController : GraphController { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/ArrayReturnController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/ArrayReturnController.cs similarity index 86% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/ArrayReturnController.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/ArrayReturnController.cs index eeeb8746b..e277b848c 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/ArrayReturnController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/ArrayReturnController.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ControllerTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ControllerTestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/ControllerWithDirective.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/ControllerWithDirective.cs similarity index 74% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/ControllerWithDirective.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/ControllerWithDirective.cs index 9f4e0d537..e01a41c30 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/ControllerWithDirective.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/ControllerWithDirective.cs @@ -7,11 +7,11 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ControllerTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ControllerTestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Internal.Templating.DirectiveTestData; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.DirectiveTestData; [ApplyDirective(typeof(DirectiveWithArgs), 101, "controller arg")] public class ControllerWithDirective : GraphController diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/ControllerWithStaticMethod.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/ControllerWithStaticMethod.cs similarity index 88% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/ControllerWithStaticMethod.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/ControllerWithStaticMethod.cs index 3572c138a..579d77ba6 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/ControllerWithStaticMethod.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/ControllerWithStaticMethod.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ControllerTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ControllerTestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/DeclaredGraphRootController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/DeclaredGraphRootController.cs similarity index 84% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/DeclaredGraphRootController.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/DeclaredGraphRootController.cs index bcadaaeb9..214df388f 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/DeclaredGraphRootController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/DeclaredGraphRootController.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ControllerTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ControllerTestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/InvalidRouteController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/InvalidRouteController.cs similarity index 86% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/InvalidRouteController.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/InvalidRouteController.cs index 1b1b58910..5c797d28f 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/InvalidRouteController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/InvalidRouteController.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ControllerTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ControllerTestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/NoInheritanceFromBaseController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/NoInheritanceFromBaseController.cs similarity index 85% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/NoInheritanceFromBaseController.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/NoInheritanceFromBaseController.cs index cea622ddd..4cc8037bc 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/NoInheritanceFromBaseController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/NoInheritanceFromBaseController.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ControllerTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ControllerTestData { using GraphQL.AspNet.Controllers; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/NoRouteSpecifierController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/NoRouteSpecifierController.cs similarity index 82% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/NoRouteSpecifierController.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/NoRouteSpecifierController.cs index e79cdba70..b883c9ef7 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/NoRouteSpecifierController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/NoRouteSpecifierController.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ControllerTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ControllerTestData { using GraphQL.AspNet.Controllers; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/OneMethodController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/OneMethodController.cs similarity index 80% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/OneMethodController.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/OneMethodController.cs index 6262863ab..f1b78d8e3 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/OneMethodController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/OneMethodController.cs @@ -7,11 +7,11 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ControllerTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ControllerTestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class OneMethodController : GraphController { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/SimpleControllerNoMethods.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/SimpleControllerNoMethods.cs similarity index 86% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/SimpleControllerNoMethods.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/SimpleControllerNoMethods.cs index dbf8010de..69f3c955d 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/SimpleControllerNoMethods.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/SimpleControllerNoMethods.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ControllerTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ControllerTestData { using System.ComponentModel; using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/TwoMethodClashController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/TwoMethodClashController.cs similarity index 86% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/TwoMethodClashController.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/TwoMethodClashController.cs index ef996a8ad..f0d5c27e1 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/TwoMethodClashController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/TwoMethodClashController.cs @@ -7,11 +7,11 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ControllerTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ControllerTestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; /// /// contains an overloaded method without providing specific names for each in the diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/TwoMethodNoClashController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/TwoMethodNoClashController.cs similarity index 86% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/TwoMethodNoClashController.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/TwoMethodNoClashController.cs index def7fc1bc..202ccf850 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/TwoMethodNoClashController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/TwoMethodNoClashController.cs @@ -7,11 +7,11 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ControllerTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ControllerTestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; /// /// contains an overloaded method but DOES provide specific names to create a diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/TwoMethodsDifferentRootsController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/TwoMethodsDifferentRootsController.cs similarity index 89% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/TwoMethodsDifferentRootsController.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/TwoMethodsDifferentRootsController.cs index 7f3c14cce..a0a9e09aa 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ControllerTestData/TwoMethodsDifferentRootsController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/TwoMethodsDifferentRootsController.cs @@ -7,12 +7,12 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ControllerTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ControllerTestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Interfaces.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; /// /// contains an overloaded method without providing specific names for each in the diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveMethodTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveMethodTemplateTests.cs similarity index 93% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveMethodTemplateTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveMethodTemplateTests.cs index 0716cd5fe..838f798f2 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveMethodTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveMethodTemplateTests.cs @@ -7,16 +7,16 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.Templating { using GraphQL.AspNet.Execution; using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Interfaces.Controllers; using GraphQL.AspNet.Interfaces.Internal; - using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Tests.Internal.Templating.DirectiveTestData; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.DirectiveTestData; using Moq; using NUnit.Framework; @@ -43,7 +43,7 @@ public void SimpleDescriptor_AllDefaults_GeneralPropertyCheck() Assert.AreEqual("IGraphActionResult (object source, int arg1, string arg2)", template.MethodSignature); Assert.AreEqual(nameof(SimpleExecutableDirective.Execute), template.Name); Assert.AreEqual($"Simple.{nameof(SimpleExecutableDirective.Execute)}", template.InternalFullName); - Assert.IsTrue(template.IsAsyncField); + Assert.IsTrue((bool)template.IsAsyncField); Assert.AreEqual(typeof(IGraphActionResult), template.ObjectType); Assert.AreEqual(DirectiveLocation.FIELD, template.Locations); Assert.AreEqual(3, template.Arguments.Count); @@ -53,7 +53,7 @@ public void SimpleDescriptor_AllDefaults_GeneralPropertyCheck() Assert.AreEqual(typeof(int), template.Arguments[1].ObjectType); Assert.AreEqual("arg2", template.Arguments[2].Name); Assert.AreEqual(typeof(string), template.Arguments[2].ObjectType); - Assert.IsTrue(template.IsExplicitDeclaration); + Assert.IsTrue((bool)template.IsExplicitDeclaration); Assert.AreEqual(GraphFieldSource.Method, template.FieldSource); Assert.AreEqual(null, template.DeclaredTypeWrappers); diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTemplateTests.cs similarity index 80% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTemplateTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTemplateTests.cs index 07a375946..bc56b1c5a 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTemplateTests.cs @@ -7,14 +7,15 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.Templating { using System.Linq; using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Execution.Exceptions; - using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Tests.Internal.Templating.DirectiveTestData; + using GraphQL.AspNet.Security; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.DirectiveTestData; using NUnit.Framework; [TestFixture] @@ -32,12 +33,12 @@ public void Simpletemplate_AllDefaults_GeneralPropertyCheck() Assert.AreEqual(typeof(SimpleExecutableDirective).FriendlyName(true), template.InternalFullName); Assert.AreEqual("Simple Description", template.Description); Assert.AreEqual(1, template.Methods.Count); - Assert.IsTrue(template.Locations.HasFlag(DirectiveLocation.FIELD)); + Assert.IsTrue((bool)template.Locations.HasFlag(DirectiveLocation.FIELD)); Assert.AreEqual(typeof(SimpleExecutableDirective), template.ObjectType); Assert.AreEqual("[directive]/SimpleExecutable", template.Route.Path); Assert.AreEqual(DirectiveLocation.FIELD, template.Locations); Assert.IsNotNull(template.Methods.FindMetaData(DirectiveLocation.FIELD)); - Assert.IsFalse(template.IsRepeatable); + Assert.IsFalse((bool)template.IsRepeatable); } [Test] @@ -105,7 +106,7 @@ public void RepeatableAttribute_SetsRepeatableProperty() template.Parse(); template.ValidateOrThrow(); - Assert.IsTrue(template.IsRepeatable); + Assert.IsTrue((bool)template.IsRepeatable); } [Test] @@ -117,13 +118,13 @@ public void SecurityPolicices_AreParsedCorrectly() Assert.AreEqual(2, template.SecurityPolicies.Count); - Assert.IsFalse(template.SecurityPolicies.AllowAnonymous); + Assert.IsFalse((bool)template.SecurityPolicies.AllowAnonymous); - Assert.IsTrue(template.SecurityPolicies.ElementAt(0).IsNamedPolicy); - Assert.AreEqual("CustomPolicy", template.SecurityPolicies.ElementAt(0).PolicyName); + Assert.IsTrue(Enumerable.ElementAt(template.SecurityPolicies, 0).IsNamedPolicy); + Assert.AreEqual("CustomPolicy", Enumerable.ElementAt(template.SecurityPolicies, 0).PolicyName); - Assert.IsFalse(template.SecurityPolicies.ElementAt(1).IsNamedPolicy); - CollectionAssert.AreEquivalent(new string[] { "CustomRole1", "CustomRole2" }, template.SecurityPolicies.ElementAt(1).AllowedRoles); + Assert.IsFalse(Enumerable.ElementAt(template.SecurityPolicies, 1).IsNamedPolicy); + CollectionAssert.AreEquivalent(new string[] { "CustomRole1", "CustomRole2" }, Enumerable.ElementAt(template.SecurityPolicies, 1).AllowedRoles); } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/DirectiveWithArgs.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTestData/DirectiveWithArgs.cs similarity index 90% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/DirectiveWithArgs.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTestData/DirectiveWithArgs.cs index 637407cf3..74c0c86dd 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/DirectiveWithArgs.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTestData/DirectiveWithArgs.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.DirectiveTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.DirectiveTestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Directives; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/DirectiveWithDeclaredDirectiveOnMethod.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTestData/DirectiveWithDeclaredDirectiveOnMethod.cs similarity index 91% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/DirectiveWithDeclaredDirectiveOnMethod.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTestData/DirectiveWithDeclaredDirectiveOnMethod.cs index a49b12505..edeb576c5 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/DirectiveWithDeclaredDirectiveOnMethod.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTestData/DirectiveWithDeclaredDirectiveOnMethod.cs @@ -6,7 +6,7 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.DirectiveTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.DirectiveTestData { using System.Threading.Tasks; using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/DirectiveWithDeclaredDirectives.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTestData/DirectiveWithDeclaredDirectives.cs similarity index 91% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/DirectiveWithDeclaredDirectives.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTestData/DirectiveWithDeclaredDirectives.cs index 3985051f6..0a88fec87 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/DirectiveWithDeclaredDirectives.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTestData/DirectiveWithDeclaredDirectives.cs @@ -6,7 +6,7 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.DirectiveTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.DirectiveTestData { using System.Threading.Tasks; using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/DirectiveWithRequirements.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTestData/DirectiveWithRequirements.cs similarity index 83% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/DirectiveWithRequirements.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTestData/DirectiveWithRequirements.cs index 8534fd6c9..bb9d5e6af 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/DirectiveWithRequirements.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTestData/DirectiveWithRequirements.cs @@ -6,13 +6,13 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.DirectiveTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.DirectiveTestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Directives; using GraphQL.AspNet.Interfaces.Controllers; using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class DirectiveWithRequirements : GraphDirective { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/DirectiveWithSecurityRequirements.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTestData/DirectiveWithSecurityRequirements.cs similarity index 90% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/DirectiveWithSecurityRequirements.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTestData/DirectiveWithSecurityRequirements.cs index b54f57f43..7eb58aecb 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/DirectiveWithSecurityRequirements.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTestData/DirectiveWithSecurityRequirements.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.DirectiveTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.DirectiveTestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Directives; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/MismatchedSignaturesDirective.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTestData/MismatchedSignaturesDirective.cs similarity index 91% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/MismatchedSignaturesDirective.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTestData/MismatchedSignaturesDirective.cs index e20933be3..278a5c055 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/MismatchedSignaturesDirective.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTestData/MismatchedSignaturesDirective.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.DirectiveTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.DirectiveTestData { using System.Threading.Tasks; using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/NoLocationAttributeDirective.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTestData/NoLocationAttributeDirective.cs similarity index 87% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/NoLocationAttributeDirective.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTestData/NoLocationAttributeDirective.cs index 48745a824..73ad69a95 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/NoLocationAttributeDirective.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTestData/NoLocationAttributeDirective.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.DirectiveTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.DirectiveTestData { using System.Threading.Tasks; using GraphQL.AspNet.Directives; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/NoLocationsDirective.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTestData/NoLocationsDirective.cs similarity index 87% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/NoLocationsDirective.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTestData/NoLocationsDirective.cs index be2328c3f..99fb127de 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/NoLocationsDirective.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTestData/NoLocationsDirective.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.DirectiveTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.DirectiveTestData { using System.Threading.Tasks; using GraphQL.AspNet.Directives; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/OverlappingLocationsDirective.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTestData/OverlappingLocationsDirective.cs similarity index 90% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/OverlappingLocationsDirective.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTestData/OverlappingLocationsDirective.cs index 3a5375a9f..6e62171ce 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/OverlappingLocationsDirective.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTestData/OverlappingLocationsDirective.cs @@ -6,7 +6,7 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.DirectiveTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.DirectiveTestData { using System.Threading.Tasks; using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/RepeatableDirective.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTestData/RepeatableDirective.cs similarity index 89% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/RepeatableDirective.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTestData/RepeatableDirective.cs index b94909242..90889058a 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/RepeatableDirective.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTestData/RepeatableDirective.cs @@ -6,7 +6,7 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.DirectiveTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.DirectiveTestData { using System.Threading.Tasks; using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/SimpleExecutableDirective.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTestData/SimpleExecutableDirective.cs similarity index 91% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/SimpleExecutableDirective.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTestData/SimpleExecutableDirective.cs index 78c3f5ade..036a55054 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/SimpleExecutableDirective.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTestData/SimpleExecutableDirective.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.DirectiveTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.DirectiveTestData { using System.ComponentModel; using System.Threading.Tasks; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/TestDirectiveMethodTemplateContainer.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTestData/TestDirectiveMethodTemplateContainer.cs similarity index 91% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/TestDirectiveMethodTemplateContainer.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTestData/TestDirectiveMethodTemplateContainer.cs index adb340d55..59967b188 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/TestDirectiveMethodTemplateContainer.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTestData/TestDirectiveMethodTemplateContainer.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.DirectiveTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.DirectiveTestData { using System.Threading.Tasks; using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/TestDirectiveMethodTemplateContainer2.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTestData/TestDirectiveMethodTemplateContainer2.cs similarity index 90% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/TestDirectiveMethodTemplateContainer2.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTestData/TestDirectiveMethodTemplateContainer2.cs index efc365738..26b25906e 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/DirectiveTestData/TestDirectiveMethodTemplateContainer2.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTestData/TestDirectiveMethodTemplateContainer2.cs @@ -7,14 +7,14 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.DirectiveTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.DirectiveTestData { using System.Threading.Tasks; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Directives; using GraphQL.AspNet.Interfaces.Controllers; using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Tests.Framework.Interfaces; + using GraphQL.AspNet.Tests.Common.Interfaces; public class TestDirectiveMethodTemplateContainer2 : GraphDirective { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumGraphTypeTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumGraphTypeTemplateTests.cs similarity index 55% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumGraphTypeTemplateTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumGraphTypeTemplateTests.cs index 63f1a02c2..01c4a6a09 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumGraphTypeTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumGraphTypeTemplateTests.cs @@ -7,13 +7,15 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.Templating { using System; using System.Linq; using GraphQL.AspNet.Execution.Exceptions; - using GraphQL.AspNet.Tests.Internal.Templating.DirectiveTestData; - using GraphQL.AspNet.Tests.Internal.Templating.EnumTestData; + using GraphQL.AspNet.Interfaces.Internal; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.DirectiveTestData; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.EnumTestData; using NUnit.Framework; [TestFixture] @@ -22,14 +24,14 @@ public class EnumGraphTypeTemplateTests [Test] public void Parse_SimpleEnum_AllDefault_ParsesCorrectly() { - var template = new AspNet.Internal.TypeTemplates.EnumGraphTypeTemplate(typeof(SimpleEnum)); + var template = new EnumGraphTypeTemplate(typeof(SimpleEnum)); template.Parse(); template.ValidateOrThrow(); Assert.AreEqual($"{Constants.Routing.ENUM_ROOT}/{nameof(SimpleEnum)}", template.Route.Path); Assert.AreEqual(nameof(SimpleEnum), template.Name); Assert.AreEqual(null, template.Description); - Assert.AreEqual(1, template.Values.Count()); + Assert.AreEqual(1, Enumerable.Count(template.Values)); Assert.AreEqual("Value1", template.Values[0].Name); Assert.AreEqual(null, template.Values[0].Description); } @@ -37,7 +39,7 @@ public void Parse_SimpleEnum_AllDefault_ParsesCorrectly() [Test] public void Parse_EnumWithDescription_ParsesCorrectly() { - var template = new AspNet.Internal.TypeTemplates.EnumGraphTypeTemplate(typeof(EnumWithDescription)); + var template = new EnumGraphTypeTemplate(typeof(EnumWithDescription)); template.Parse(); template.ValidateOrThrow(); @@ -47,7 +49,7 @@ public void Parse_EnumWithDescription_ParsesCorrectly() [Test] public void Parse_EnumWithGraphName_ParsesCorrectly() { - var template = new AspNet.Internal.TypeTemplates.EnumGraphTypeTemplate(typeof(EnumWithGraphName)); + var template = new EnumGraphTypeTemplate(typeof(EnumWithGraphName)); template.Parse(); template.ValidateOrThrow(); @@ -57,20 +59,20 @@ public void Parse_EnumWithGraphName_ParsesCorrectly() [Test] public void Parse_EnumWithDescriptionOnValues_ParsesCorrectly() { - var template = new AspNet.Internal.TypeTemplates.EnumGraphTypeTemplate(typeof(EnumWithDescriptionOnValues)); + var template = new EnumGraphTypeTemplate(typeof(EnumWithDescriptionOnValues)); template.Parse(); template.ValidateOrThrow(); - Assert.IsTrue(template.Values.Any(x => x.Name == "Value1" && x.Description == null)); - Assert.IsTrue(template.Values.Any(x => x.Name == "Value2" && x.Description == "Value2 Description")); - Assert.IsTrue(template.Values.Any(x => x.Name == "Value3" && x.Description == null)); - Assert.IsTrue(template.Values.Any(x => x.Name == "Value4" && x.Description == "Value4 Description")); + Assert.IsTrue(Enumerable.Any(template.Values, x => x.Name == "Value1" && x.Description == null)); + Assert.IsTrue(Enumerable.Any(template.Values, x => x.Name == "Value2" && x.Description == "Value2 Description")); + Assert.IsTrue(Enumerable.Any(template.Values, x => x.Name == "Value3" && x.Description == null)); + Assert.IsTrue(Enumerable.Any(template.Values, x => x.Name == "Value4" && x.Description == "Value4 Description")); } [Test] public void Parse_EnumWithInvalidValueName_ThrowsException() { - var template = new AspNet.Internal.TypeTemplates.EnumGraphTypeTemplate(typeof(EnumWithInvalidValueName)); + var template = new EnumGraphTypeTemplate(typeof(EnumWithInvalidValueName)); template.Parse(); Assert.Throws(() => @@ -82,19 +84,19 @@ public void Parse_EnumWithInvalidValueName_ThrowsException() [Test] public void Parse_EnumWithValueWithGraphName_ParsesCorrectly() { - var template = new AspNet.Internal.TypeTemplates.EnumGraphTypeTemplate(typeof(EnumWithValueWithGraphName)); + var template = new EnumGraphTypeTemplate(typeof(EnumWithValueWithGraphName)); template.Parse(); template.ValidateOrThrow(); - Assert.IsTrue(template.Values.Any(x => x.Name == "Value1")); - Assert.IsTrue(template.Values.Any(x => x.Name == "AnotherName")); - Assert.IsTrue(template.Values.All(x => x.Name != "Value2")); + Assert.IsTrue(Enumerable.Any(template.Values, x => x.Name == "Value1")); + Assert.IsTrue(Enumerable.Any(template.Values, x => x.Name == "AnotherName")); + Assert.IsTrue(Enumerable.All(template.Values, x => x.Name != "Value2")); } [Test] public void Parse_EnumWithValueWithGraphName_ButGraphNameIsInvalid_ThrowsException() { - var template = new AspNet.Internal.TypeTemplates.EnumGraphTypeTemplate(typeof(EnumWithValueWithGraphNameButGraphNameIsInvalid)); + var template = new EnumGraphTypeTemplate(typeof(EnumWithValueWithGraphNameButGraphNameIsInvalid)); template.Parse(); Assert.Throws(() => { @@ -105,20 +107,20 @@ public void Parse_EnumWithValueWithGraphName_ButGraphNameIsInvalid_ThrowsExcepti [Test] public void Parse_EnumWithNonIntBase_ParsesCorrectly() { - var template = new AspNet.Internal.TypeTemplates.EnumGraphTypeTemplate(typeof(EnumFromUInt)); + var template = new EnumGraphTypeTemplate(typeof(EnumFromUInt)); template.Parse(); template.ValidateOrThrow(); Assert.AreEqual(3, template.Values.Count); - Assert.IsTrue(template.Values.Any(x => x.Name == "Value1")); - Assert.IsTrue(template.Values.Any(x => x.Name == "Value2")); - Assert.IsTrue(template.Values.Any(x => x.Name != "Value3")); + Assert.IsTrue(Enumerable.Any(template.Values, x => x.Name == "Value1")); + Assert.IsTrue(Enumerable.Any(template.Values, x => x.Name == "Value2")); + Assert.IsTrue(Enumerable.Any(template.Values, x => x.Name != "Value3")); } [Test] public void Parse_EnumWithDuplciateValues_ThrowsException() { - var template = new AspNet.Internal.TypeTemplates.EnumGraphTypeTemplate(typeof(EnumWithDuplicateValues)); + var template = new EnumGraphTypeTemplate(typeof(EnumWithDuplicateValues)); template.Parse(); Assert.Throws(() => @@ -130,7 +132,7 @@ public void Parse_EnumWithDuplciateValues_ThrowsException() [Test] public void Parse_EnumWithDuplciateValuesFromComposite_ThrowsException() { - var template = new AspNet.Internal.TypeTemplates.EnumGraphTypeTemplate(typeof(EnumWithDuplicateValuesFromComposite)); + var template = new EnumGraphTypeTemplate(typeof(EnumWithDuplicateValuesFromComposite)); template.Parse(); Assert.Throws(() => @@ -145,17 +147,17 @@ public void Parse_EnumWithDuplciateValuesFromComposite_ThrowsException() [TestCase(typeof(EnumFromLong))] public void Parse_EnsureEnumsOfSignedValues(Type type) { - var template = new AspNet.Internal.TypeTemplates.EnumGraphTypeTemplate(type); + var template = new EnumGraphTypeTemplate(type); template.Parse(); template.ValidateOrThrow(); Assert.AreEqual(6, template.Values.Count); - Assert.IsTrue(template.Values.Any(x => x.Name == "Value1")); - Assert.IsTrue(template.Values.Any(x => x.Name == "Value2")); - Assert.IsTrue(template.Values.Any(x => x.Name != "Value3")); - Assert.IsTrue(template.Values.Any(x => x.Name == "Value4")); - Assert.IsTrue(template.Values.Any(x => x.Name == "Value5")); - Assert.IsTrue(template.Values.Any(x => x.Name != "Value6")); + Assert.IsTrue(Enumerable.Any(template.Values, x => x.Name == "Value1")); + Assert.IsTrue(Enumerable.Any(template.Values, x => x.Name == "Value2")); + Assert.IsTrue(Enumerable.Any(template.Values, x => x.Name != "Value3")); + Assert.IsTrue(Enumerable.Any(template.Values, x => x.Name == "Value4")); + Assert.IsTrue(Enumerable.Any(template.Values, x => x.Name == "Value5")); + Assert.IsTrue(Enumerable.Any(template.Values, x => x.Name != "Value6")); } [TestCase(typeof(EnumFromByte))] @@ -164,14 +166,14 @@ public void Parse_EnsureEnumsOfSignedValues(Type type) [TestCase(typeof(EnumFromULong))] public void Parse_EnsureEnumsOfUnSignedValues(Type type) { - var template = new AspNet.Internal.TypeTemplates.EnumGraphTypeTemplate(type); + var template = new EnumGraphTypeTemplate(type); template.Parse(); template.ValidateOrThrow(); Assert.AreEqual(3, template.Values.Count); - Assert.IsTrue(template.Values.Any(x => x.Name == "Value1")); - Assert.IsTrue(template.Values.Any(x => x.Name == "Value2")); - Assert.IsTrue(template.Values.Any(x => x.Name != "Value3")); + Assert.IsTrue(Enumerable.Any(template.Values, x => x.Name == "Value1")); + Assert.IsTrue(Enumerable.Any(template.Values, x => x.Name == "Value2")); + Assert.IsTrue(Enumerable.Any(template.Values, x => x.Name != "Value3")); } [Test] @@ -179,7 +181,7 @@ public void Parse_SignedEnum_CompleteKeySpace_ParsesCorrectly() { // the enum defines EVERY value for its key space // ensure it parses - var template = new AspNet.Internal.TypeTemplates.EnumGraphTypeTemplate(typeof(EnumCompleteSByte)); + var template = new EnumGraphTypeTemplate(typeof(EnumCompleteSByte)); template.Parse(); template.ValidateOrThrow(); @@ -192,7 +194,7 @@ public void Parse_UnsignedEnum_CompleteKeySpace_ParsesCorrectly() { // the enum defines EVERY value for its key space // ensure it parses - var template = new AspNet.Internal.TypeTemplates.EnumGraphTypeTemplate(typeof(EnumCompleteByte)); + var template = new EnumGraphTypeTemplate(typeof(EnumCompleteByte)); template.Parse(); template.ValidateOrThrow(); @@ -203,13 +205,13 @@ public void Parse_UnsignedEnum_CompleteKeySpace_ParsesCorrectly() [Test] public void Parse_AssignedDirective_IsTemplatized() { - var template = new AspNet.Internal.TypeTemplates.EnumGraphTypeTemplate(typeof(EnumWithDirective)); + var template = new EnumGraphTypeTemplate(typeof(EnumWithDirective)); template.Parse(); template.ValidateOrThrow(); - Assert.AreEqual(1, template.AppliedDirectives.Count()); + Assert.AreEqual(1, Enumerable.Count(template.AppliedDirectives)); - var appliedDirective = template.AppliedDirectives.First(); + var appliedDirective = Enumerable.First(template.AppliedDirectives); Assert.AreEqual(typeof(DirectiveWithArgs), appliedDirective.DirectiveType); Assert.AreEqual(new object[] { 5, "bob" }, appliedDirective.Arguments); } @@ -217,16 +219,16 @@ public void Parse_AssignedDirective_IsTemplatized() [Test] public void Parse_EnumOption_AssignedDirective_IsTemplatized() { - var template = new AspNet.Internal.TypeTemplates.EnumGraphTypeTemplate(typeof(EnumWithDirectiveOnOption)); + var template = new EnumGraphTypeTemplate(typeof(EnumWithDirectiveOnOption)); template.Parse(); template.ValidateOrThrow(); - Assert.AreEqual(0, template.AppliedDirectives.Count()); + Assert.AreEqual(0, Enumerable.Count(template.AppliedDirectives)); - var optionTemplate = template.Values.FirstOrDefault(x => x.Name == "Value1"); + var optionTemplate = Enumerable.FirstOrDefault(template.Values, x => x.Name == "Value1"); Assert.AreEqual(0, optionTemplate.AppliedDirectives.Count()); - optionTemplate = template.Values.FirstOrDefault(x => x.Name == "Value2"); + optionTemplate = Enumerable.FirstOrDefault(template.Values, x => x.Name == "Value2"); Assert.AreEqual(1, optionTemplate.AppliedDirectives.Count()); var appliedDirective = optionTemplate.AppliedDirectives.First(); diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/DeprecatedValueEnum.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/DeprecatedValueEnum.cs similarity index 84% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/DeprecatedValueEnum.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/DeprecatedValueEnum.cs index 9288328bf..d6b379a27 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/DeprecatedValueEnum.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/DeprecatedValueEnum.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.EnumTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.EnumTestData { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumCompleteByte.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumCompleteByte.cs similarity index 99% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumCompleteByte.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumCompleteByte.cs index 9fb9da252..33919604b 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumCompleteByte.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumCompleteByte.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.EnumTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.EnumTestData { public enum EnumCompleteByte : byte { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumCompleteSByte.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumCompleteSByte.cs similarity index 99% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumCompleteSByte.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumCompleteSByte.cs index f6a8f9519..49cbf932a 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumCompleteSByte.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumCompleteSByte.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.EnumTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.EnumTestData { public enum EnumCompleteSByte : sbyte { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumFromByte.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumFromByte.cs similarity index 83% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumFromByte.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumFromByte.cs index b6f74fa81..7b51439d6 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumFromByte.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumFromByte.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.EnumTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.EnumTestData { public enum EnumFromByte { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumFromInt.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumFromInt.cs similarity index 85% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumFromInt.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumFromInt.cs index 3c0a76fc9..dac474535 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumFromInt.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumFromInt.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.EnumTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.EnumTestData { public enum EnumFromInt : int { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumFromLong.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumFromLong.cs similarity index 85% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumFromLong.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumFromLong.cs index e5163c112..cf9d4bad5 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumFromLong.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumFromLong.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.EnumTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.EnumTestData { public enum EnumFromLong : long { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumFromSByte.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumFromSByte.cs similarity index 86% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumFromSByte.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumFromSByte.cs index efa1dbf11..914fc91d6 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumFromSByte.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumFromSByte.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.EnumTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.EnumTestData { public enum EnumFromSByte : sbyte { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumFromShort.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumFromShort.cs similarity index 86% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumFromShort.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumFromShort.cs index 0ca1c8324..bfcafc41a 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumFromShort.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumFromShort.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.EnumTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.EnumTestData { public enum EnumFromShort : short { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumFromUInt.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumFromUInt.cs similarity index 83% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumFromUInt.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumFromUInt.cs index c0a733994..c3811f104 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumFromUInt.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumFromUInt.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.EnumTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.EnumTestData { public enum EnumFromUInt : uint { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumFromULong.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumFromULong.cs similarity index 83% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumFromULong.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumFromULong.cs index 508c7179f..984d8116e 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumFromULong.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumFromULong.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.EnumTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.EnumTestData { public enum EnumFromULong : ulong { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumFromUShort.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumFromUShort.cs similarity index 84% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumFromUShort.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumFromUShort.cs index 118dddab0..2d7b6355f 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumFromUShort.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumFromUShort.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.EnumTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.EnumTestData { public enum EnumFromUShort : ushort { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithDescription.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumWithDescription.cs similarity index 84% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithDescription.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumWithDescription.cs index b1cd9e269..0b188c22a 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithDescription.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumWithDescription.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.EnumTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.EnumTestData { using System.ComponentModel; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithDescriptions.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumWithDescriptions.cs similarity index 87% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithDescriptions.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumWithDescriptions.cs index c3edd3e1f..d1862d987 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithDescriptions.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumWithDescriptions.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.EnumTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.EnumTestData { using System.ComponentModel; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithDirective.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumWithDirective.cs similarity index 73% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithDirective.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumWithDirective.cs index dd59f0d70..9b7d51d3d 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithDirective.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumWithDirective.cs @@ -6,10 +6,10 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.EnumTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.EnumTestData { using GraphQL.AspNet.Attributes; - using GraphQL.AspNet.Tests.Internal.Templating.DirectiveTestData; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.DirectiveTestData; [ApplyDirective(typeof(DirectiveWithArgs), 5, "bob")] public enum EnumWithDirective diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithDirectiveOnOption.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumWithDirectiveOnOption.cs similarity index 74% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithDirectiveOnOption.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumWithDirectiveOnOption.cs index cf3c873ef..5237d7a45 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithDirectiveOnOption.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumWithDirectiveOnOption.cs @@ -6,10 +6,10 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.EnumTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.EnumTestData { using GraphQL.AspNet.Attributes; - using GraphQL.AspNet.Tests.Internal.Templating.DirectiveTestData; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.DirectiveTestData; public enum EnumWithDirectiveOnOption { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithDuplicateValues.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumWithDuplicateValues.cs similarity index 84% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithDuplicateValues.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumWithDuplicateValues.cs index 9d72e2119..af34edaab 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithDuplicateValues.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumWithDuplicateValues.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.EnumTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.EnumTestData { public enum EnumWithDuplicateValues { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithDuplicateValuesFromComposite.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumWithDuplicateValuesFromComposite.cs similarity index 86% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithDuplicateValuesFromComposite.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumWithDuplicateValuesFromComposite.cs index 9fa7ee654..3d8668dbd 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithDuplicateValuesFromComposite.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumWithDuplicateValuesFromComposite.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.EnumTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.EnumTestData { public enum EnumWithDuplicateValuesFromComposite { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithGraphName.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumWithGraphName.cs similarity index 84% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithGraphName.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumWithGraphName.cs index af2c95d94..584fd7f87 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithGraphName.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumWithGraphName.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.EnumTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.EnumTestData { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithInvalidValueName.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumWithInvalidValueName.cs similarity index 82% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithInvalidValueName.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumWithInvalidValueName.cs index 4015116d7..0a74f17b6 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithInvalidValueName.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumWithInvalidValueName.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.EnumTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.EnumTestData { public enum EnumWithInvalidValueName { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithValueWithGraphName.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumWithValueWithGraphName.cs similarity index 85% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithValueWithGraphName.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumWithValueWithGraphName.cs index bd1a4290b..871a5b741 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithValueWithGraphName.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumWithValueWithGraphName.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.EnumTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.EnumTestData { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithValueWithGraphNameButGraphNameIsInvalid.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumWithValueWithGraphNameButGraphNameIsInvalid.cs similarity index 85% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithValueWithGraphNameButGraphNameIsInvalid.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumWithValueWithGraphNameButGraphNameIsInvalid.cs index 4d4d7bf80..1231a70eb 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/EnumWithValueWithGraphNameButGraphNameIsInvalid.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumWithValueWithGraphNameButGraphNameIsInvalid.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.EnumTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.EnumTestData { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/SimpleEnum.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/SimpleEnum.cs similarity index 81% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/SimpleEnum.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/SimpleEnum.cs index 7202d3d83..7166578d2 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/EnumTestData/SimpleEnum.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/SimpleEnum.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.EnumTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.EnumTestData { public enum SimpleEnum { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ExtensionMethodTestData/ExtensionMethodController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ExtensionMethodTestData/ExtensionMethodController.cs similarity index 95% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ExtensionMethodTestData/ExtensionMethodController.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ExtensionMethodTestData/ExtensionMethodController.cs index ce647befa..172774e92 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ExtensionMethodTestData/ExtensionMethodController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ExtensionMethodTestData/ExtensionMethodController.cs @@ -7,15 +7,15 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ExtensionMethodTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ExtensionMethodTestData { using System.Collections.Generic; using System.ComponentModel; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Interfaces.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; - using GraphQL.AspNet.Tests.Framework.Interfaces; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + using GraphQL.AspNet.Tests.Common.Interfaces; public class ExtensionMethodController : GraphController { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNameTestData/AttributedClass.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/GraphTypeNameTestData/AttributedClass.cs similarity index 82% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNameTestData/AttributedClass.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/GraphTypeNameTestData/AttributedClass.cs index 57b0965b0..584ba44bf 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNameTestData/AttributedClass.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/GraphTypeNameTestData/AttributedClass.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.GraphTypeNameTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.GraphTypeNameTestData { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNameTestData/AttributedClassInvalidName.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/GraphTypeNameTestData/AttributedClassInvalidName.cs similarity index 82% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNameTestData/AttributedClassInvalidName.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/GraphTypeNameTestData/AttributedClassInvalidName.cs index 0665fa473..b4ff8b207 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNameTestData/AttributedClassInvalidName.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/GraphTypeNameTestData/AttributedClassInvalidName.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.GraphTypeNameTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.GraphTypeNameTestData { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNameTestData/EnumNameTest.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/GraphTypeNameTestData/EnumNameTest.cs similarity index 80% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNameTestData/EnumNameTest.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/GraphTypeNameTestData/EnumNameTest.cs index 4f71da2f7..b93cab4cf 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNameTestData/EnumNameTest.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/GraphTypeNameTestData/EnumNameTest.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.GraphTypeNameTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.GraphTypeNameTestData { public enum EnumNameTest { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNameTestData/EnumNameTestWithTypeName.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/GraphTypeNameTestData/EnumNameTestWithTypeName.cs similarity index 83% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNameTestData/EnumNameTestWithTypeName.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/GraphTypeNameTestData/EnumNameTestWithTypeName.cs index 26831eb85..3043c3aa3 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNameTestData/EnumNameTestWithTypeName.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/GraphTypeNameTestData/EnumNameTestWithTypeName.cs @@ -6,7 +6,7 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.GraphTypeNameTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.GraphTypeNameTestData { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNameTestData/GenericClass.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/GraphTypeNameTestData/GenericClass.cs similarity index 82% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNameTestData/GenericClass.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/GraphTypeNameTestData/GenericClass.cs index e9e35fbbc..816bd907c 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNameTestData/GenericClass.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/GraphTypeNameTestData/GenericClass.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.GraphTypeNameTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.GraphTypeNameTestData { public class GenericClass { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNameTestData/GenericClassWithAttribute.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/GraphTypeNameTestData/GenericClassWithAttribute.cs similarity index 85% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNameTestData/GenericClassWithAttribute.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/GraphTypeNameTestData/GenericClassWithAttribute.cs index 3307c7208..8fe3b7b4f 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNameTestData/GenericClassWithAttribute.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/GraphTypeNameTestData/GenericClassWithAttribute.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.GraphTypeNameTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.GraphTypeNameTestData { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNameTestData/NoAttributeClass.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/GraphTypeNameTestData/NoAttributeClass.cs similarity index 79% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNameTestData/NoAttributeClass.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/GraphTypeNameTestData/NoAttributeClass.cs index 722714955..00899c064 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNameTestData/NoAttributeClass.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/GraphTypeNameTestData/NoAttributeClass.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.GraphTypeNameTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.GraphTypeNameTestData { public class NoAttributeClass { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNameTestData/NoAttributeClassForNewName.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/GraphTypeNameTestData/NoAttributeClassForNewName.cs similarity index 79% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNameTestData/NoAttributeClassForNewName.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/GraphTypeNameTestData/NoAttributeClassForNewName.cs index 022b45601..17b3b4aef 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNameTestData/NoAttributeClassForNewName.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/GraphTypeNameTestData/NoAttributeClassForNewName.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.GraphTypeNameTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.GraphTypeNameTestData { public class NoAttributeClassForNewName { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNamesTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/GraphTypeNamesTests.cs similarity index 95% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNamesTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/GraphTypeNamesTests.cs index 4fe8c75a7..b561c1e18 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/GraphTypeNamesTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/GraphTypeNamesTests.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.Templating { using System; using System.Collections.Generic; @@ -15,10 +15,9 @@ namespace GraphQL.AspNet.Tests.Internal.Templating using GraphQL.AspNet.Common.Generics; using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal; + using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Schemas.TypeSystem.Scalars; - using GraphQL.AspNet.Tests.Internal.Templating.GraphTypeNameTestData; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.GraphTypeNameTestData; using NUnit.Framework; [TestFixture] diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InputGraphFieldTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InputGraphFieldTemplateTests.cs similarity index 91% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InputGraphFieldTemplateTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InputGraphFieldTemplateTests.cs index 1d0ba9da3..c41ac0296 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InputGraphFieldTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InputGraphFieldTemplateTests.cs @@ -7,15 +7,15 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.Templating { using System.Linq; using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Interfaces.Internal; - using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Tests.Internal.Templating.PropertyTestData; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.PropertyTestData; using Moq; using NUnit.Framework; @@ -39,10 +39,10 @@ public void Parse_GeneralPropertyCheck() Assert.AreEqual("[type]/Item0/Name", template.Route.ToString()); Assert.AreEqual("name desc", template.Description); Assert.AreEqual(typeof(string), template.ObjectType); - Assert.IsFalse(template.IsRequired); + Assert.IsFalse((bool)template.IsRequired); Assert.AreEqual("String", template.TypeExpression.ToString()); - Assert.AreEqual(1, template.AppliedDirectives.Count()); - Assert.AreEqual("nameDirective", template.AppliedDirectives.Single().DirectiveName); + Assert.AreEqual(1, Enumerable.Count(template.AppliedDirectives)); + Assert.AreEqual("nameDirective", Enumerable.Single(template.AppliedDirectives).DirectiveName); Assert.AreEqual("Name", template.InternalName); } @@ -62,7 +62,7 @@ public void Parse_IsRequired_IsNotSet() // field does not declare [Required] therefore must // have a default value - Assert.IsFalse(template.IsRequired); + Assert.IsFalse((bool)template.IsRequired); } [Test] @@ -80,7 +80,7 @@ public void Parse_IsRequired_IsSet() template.ValidateOrThrow(); // field does declare [Required] there for cannot have a default value - Assert.IsTrue(template.IsRequired); + Assert.IsTrue((bool)template.IsRequired); } [Test] diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InputObjectTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InputObjectTemplateTests.cs similarity index 96% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InputObjectTemplateTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InputObjectTemplateTests.cs index 097cf2fa7..d803c89d8 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InputObjectTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InputObjectTemplateTests.cs @@ -7,17 +7,18 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates { using System; using System.Collections.Generic; using System.Linq; using GraphQL.AspNet.Execution; using GraphQL.AspNet.Execution.Exceptions; - using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Interfaces.Internal; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Tests.Internal.Templating.DirectiveTestData; - using GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.DirectiveTestData; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests; using NUnit.Framework; [TestFixture] @@ -59,7 +60,7 @@ public void Parse_Object_GeneralPropertySettings_SetCorrectly() Assert.AreEqual(0, template.FieldTemplates.Count()); Assert.AreEqual(TypeKind.INPUT_OBJECT, template.Kind); Assert.AreEqual(nameof(SimpleObjectNoMethods), template.InternalName); - Assert.AreEqual("GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests.SimpleObjectNoMethods", template.InternalFullName); + Assert.AreEqual("GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests.SimpleObjectNoMethods", template.InternalFullName); Assert.AreEqual(0, template.SecurityPolicies.Count); } diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceGraphTypeTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceGraphTypeTemplateTests.cs similarity index 51% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceGraphTypeTemplateTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceGraphTypeTemplateTests.cs index 132ef1845..8ab2c5281 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceGraphTypeTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceGraphTypeTemplateTests.cs @@ -7,13 +7,16 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates { + using System; + using System.Collections.Generic; using System.Linq; using GraphQL.AspNet.Execution.Exceptions; - using GraphQL.AspNet.Internal.TypeTemplates; - using GraphQL.AspNet.Tests.Internal.Templating.DirectiveTestData; - using GraphQL.AspNet.Tests.Internal.Templating.InterfaceTestData; + using GraphQL.AspNet.Interfaces.Internal; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.DirectiveTestData; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.InterfaceTestData; using NUnit.Framework; [TestFixture] @@ -30,7 +33,7 @@ public void Parse_FromInterface_GeneralPropertySettings_SetCorrectly() Assert.AreEqual("[type]/ISimpleInterface", template.Route.Path); Assert.AreEqual(null, template.Description); Assert.AreEqual(typeof(ISimpleInterface), template.ObjectType); - Assert.AreEqual(2, template.FieldTemplates.Count()); + Assert.AreEqual(2, Enumerable.Count>(template.FieldTemplates)); } [Test] @@ -49,9 +52,9 @@ public void Parse_AssignedDirective_IsTemplatized() template.Parse(); template.ValidateOrThrow(); - Assert.AreEqual(1, template.AppliedDirectives.Count()); + Assert.AreEqual(1, Enumerable.Count(template.AppliedDirectives)); - var appliedDirective = template.AppliedDirectives.First(); + var appliedDirective = Enumerable.First(template.AppliedDirectives); Assert.AreEqual(typeof(DirectiveWithArgs), appliedDirective.DirectiveType); Assert.AreEqual(new object[] { 8, "big face" }, appliedDirective.Arguments); } @@ -66,13 +69,13 @@ public void Parse_ImplementedInterfaces_AreCaptured() Assert.IsNotNull(template); Assert.AreEqual("[type]/ITestableInterfaceImplementation", template.Route.Path); Assert.AreEqual(typeof(ITestableInterfaceImplementation), template.ObjectType); - Assert.AreEqual(5, template.DeclaredInterfaces.Count()); + Assert.AreEqual(5, Enumerable.Count(template.DeclaredInterfaces)); - Assert.IsTrue(template.DeclaredInterfaces.Contains(typeof(IInterface1))); - Assert.IsTrue(template.DeclaredInterfaces.Contains(typeof(IInterface2))); - Assert.IsTrue(template.DeclaredInterfaces.Contains(typeof(IInterface3))); - Assert.IsTrue(template.DeclaredInterfaces.Contains(typeof(INestedInterface1))); - Assert.IsTrue(template.DeclaredInterfaces.Contains(typeof(INestedInterface2))); + Assert.IsTrue(Enumerable.Contains(template.DeclaredInterfaces, typeof(IInterface1))); + Assert.IsTrue(Enumerable.Contains(template.DeclaredInterfaces, typeof(IInterface2))); + Assert.IsTrue(Enumerable.Contains(template.DeclaredInterfaces, typeof(IInterface3))); + Assert.IsTrue(Enumerable.Contains(template.DeclaredInterfaces, typeof(INestedInterface1))); + Assert.IsTrue(Enumerable.Contains(template.DeclaredInterfaces, typeof(INestedInterface2))); } [Test] @@ -85,10 +88,10 @@ public void Parse_InheritedUndeclaredMethodField_IsNotIncluded() // PropFieldOnInterface, MethodFieldOnInterface // base items are ignored Assert.AreEqual(2, template.FieldTemplates.Count); - Assert.IsTrue(template.FieldTemplates.Any(x => string.Equals(x.Value.Name, nameof(InterfaceThatInheritsUndeclaredMethodField.PropFieldOnInterface), System.StringComparison.OrdinalIgnoreCase))); - Assert.IsTrue(template.FieldTemplates.Any(x => string.Equals(x.Value.Name, nameof(InterfaceThatInheritsUndeclaredMethodField.MethodFieldOnInterface), System.StringComparison.OrdinalIgnoreCase))); - Assert.AreEqual(1, template.DeclaredInterfaces.Count()); - Assert.IsTrue(template.DeclaredInterfaces.Contains(typeof(InterfaceWithUndeclaredInterfaceField))); + Assert.IsTrue(Enumerable.Any>(template.FieldTemplates, x => string.Equals(x.Value.Name, nameof(InterfaceThatInheritsUndeclaredMethodField.PropFieldOnInterface), System.StringComparison.OrdinalIgnoreCase))); + Assert.IsTrue(Enumerable.Any>(template.FieldTemplates, x => string.Equals(x.Value.Name, nameof(InterfaceThatInheritsUndeclaredMethodField.MethodFieldOnInterface), System.StringComparison.OrdinalIgnoreCase))); + Assert.AreEqual(1, Enumerable.Count(template.DeclaredInterfaces)); + Assert.IsTrue(Enumerable.Contains(template.DeclaredInterfaces, typeof(InterfaceWithUndeclaredInterfaceField))); } [Test] @@ -99,11 +102,11 @@ public void Parse_InheritedDeclaredMethodField_IsNotIncluded() template.ValidateOrThrow(); Assert.AreEqual(2, template.FieldTemplates.Count); - Assert.IsTrue(template.FieldTemplates.Any(x => string.Equals(x.Value.Name, nameof(InterfaceThatInheritsDeclaredMethodField.PropFieldOnInterface), System.StringComparison.OrdinalIgnoreCase))); - Assert.IsTrue(template.FieldTemplates.Any(x => string.Equals(x.Value.Name, nameof(InterfaceThatInheritsDeclaredMethodField.MethodFieldOnInterface), System.StringComparison.OrdinalIgnoreCase))); + Assert.IsTrue(Enumerable.Any>(template.FieldTemplates, x => string.Equals(x.Value.Name, nameof(InterfaceThatInheritsDeclaredMethodField.PropFieldOnInterface), System.StringComparison.OrdinalIgnoreCase))); + Assert.IsTrue(Enumerable.Any>(template.FieldTemplates, x => string.Equals(x.Value.Name, nameof(InterfaceThatInheritsDeclaredMethodField.MethodFieldOnInterface), System.StringComparison.OrdinalIgnoreCase))); - Assert.AreEqual(1, template.DeclaredInterfaces.Count()); - Assert.IsTrue(template.DeclaredInterfaces.Contains(typeof(InterfaceWithDeclaredInterfaceField))); + Assert.AreEqual(1, Enumerable.Count(template.DeclaredInterfaces)); + Assert.IsTrue(Enumerable.Contains(template.DeclaredInterfaces, typeof(InterfaceWithDeclaredInterfaceField))); } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/IInterface1.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceTestData/IInterface1.cs similarity index 80% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/IInterface1.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceTestData/IInterface1.cs index 29f1a6758..d11757b52 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/IInterface1.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceTestData/IInterface1.cs @@ -6,7 +6,7 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.InterfaceTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.InterfaceTestData { public interface IInterface1 : INestedInterface1 { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/IInterface2.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceTestData/IInterface2.cs similarity index 81% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/IInterface2.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceTestData/IInterface2.cs index 94851c712..06b4f84c1 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/IInterface2.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceTestData/IInterface2.cs @@ -6,7 +6,7 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.InterfaceTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.InterfaceTestData { public interface IInterface2 : INestedInterface1, IInterface3 { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/IInterface3.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceTestData/IInterface3.cs similarity index 79% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/IInterface3.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceTestData/IInterface3.cs index e926c8a56..077816ce3 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/IInterface3.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceTestData/IInterface3.cs @@ -6,7 +6,7 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.InterfaceTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.InterfaceTestData { public interface IInterface3 { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/IInterfaceWithDirective.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceTestData/IInterfaceWithDirective.cs similarity index 73% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/IInterfaceWithDirective.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceTestData/IInterfaceWithDirective.cs index 5087c1ca7..bad0d6911 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/IInterfaceWithDirective.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceTestData/IInterfaceWithDirective.cs @@ -6,10 +6,10 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.InterfaceTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.InterfaceTestData { using GraphQL.AspNet.Attributes; - using GraphQL.AspNet.Tests.Internal.Templating.DirectiveTestData; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.DirectiveTestData; [ApplyDirective(typeof(DirectiveWithArgs), 8, "big face")] public interface IInterfaceWithDirective diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/INestedInterface1.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceTestData/INestedInterface1.cs similarity index 80% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/INestedInterface1.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceTestData/INestedInterface1.cs index ddfcbf202..68e2ca73d 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/INestedInterface1.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceTestData/INestedInterface1.cs @@ -6,7 +6,7 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.InterfaceTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.InterfaceTestData { public interface INestedInterface1 : INestedInterface2 { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/INestedInterface2.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceTestData/INestedInterface2.cs similarity index 80% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/INestedInterface2.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceTestData/INestedInterface2.cs index 8dc18e916..f8cc2d4cc 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/INestedInterface2.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceTestData/INestedInterface2.cs @@ -6,7 +6,7 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.InterfaceTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.InterfaceTestData { public interface INestedInterface2 { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/ISimpleInterface.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceTestData/ISimpleInterface.cs similarity index 85% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/ISimpleInterface.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceTestData/ISimpleInterface.cs index 71dcae0fa..f466adc95 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/ISimpleInterface.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceTestData/ISimpleInterface.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.InterfaceTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.InterfaceTestData { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/ITestableInterfaceImplementation.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceTestData/ITestableInterfaceImplementation.cs similarity index 81% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/ITestableInterfaceImplementation.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceTestData/ITestableInterfaceImplementation.cs index d8ba9d336..1a1ba2153 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/ITestableInterfaceImplementation.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceTestData/ITestableInterfaceImplementation.cs @@ -6,7 +6,7 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.InterfaceTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.InterfaceTestData { public interface ITestableInterfaceImplementation : IInterface1, IInterface2 { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/InterfaceThatInheritsDeclaredMethodField.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceTestData/InterfaceThatInheritsDeclaredMethodField.cs similarity index 85% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/InterfaceThatInheritsDeclaredMethodField.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceTestData/InterfaceThatInheritsDeclaredMethodField.cs index 99d5a17b5..411f974b9 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/InterfaceThatInheritsDeclaredMethodField.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceTestData/InterfaceThatInheritsDeclaredMethodField.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.InterfaceTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.InterfaceTestData { public interface InterfaceThatInheritsDeclaredMethodField : InterfaceWithDeclaredInterfaceField { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/InterfaceThatInheritsUndeclaredMethodField.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceTestData/InterfaceThatInheritsUndeclaredMethodField.cs similarity index 82% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/InterfaceThatInheritsUndeclaredMethodField.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceTestData/InterfaceThatInheritsUndeclaredMethodField.cs index 1827b13d0..3d23bc006 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/InterfaceThatInheritsUndeclaredMethodField.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceTestData/InterfaceThatInheritsUndeclaredMethodField.cs @@ -7,10 +7,8 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.InterfaceTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.InterfaceTestData { - using GraphQL.AspNet.Attributes; - public interface InterfaceThatInheritsUndeclaredMethodField : InterfaceWithUndeclaredInterfaceField { string PropFieldOnInterface { get; set; } diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/InterfaceWithDeclaredInterfaceField.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceTestData/InterfaceWithDeclaredInterfaceField.cs similarity index 86% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/InterfaceWithDeclaredInterfaceField.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceTestData/InterfaceWithDeclaredInterfaceField.cs index 301e24f8c..7185e2ecb 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/InterfaceWithDeclaredInterfaceField.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceTestData/InterfaceWithDeclaredInterfaceField.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.InterfaceTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.InterfaceTestData { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/InterfaceWithUndeclaredInterfaceField.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceTestData/InterfaceWithUndeclaredInterfaceField.cs similarity index 84% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/InterfaceWithUndeclaredInterfaceField.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceTestData/InterfaceWithUndeclaredInterfaceField.cs index c8469182d..9dc6db8c5 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/InterfaceTestData/InterfaceWithUndeclaredInterfaceField.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceTestData/InterfaceWithUndeclaredInterfaceField.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.InterfaceTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.InterfaceTestData { public interface InterfaceWithUndeclaredInterfaceField { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/MethodGraphFieldTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplateTests.cs similarity index 89% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/MethodGraphFieldTemplateTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplateTests.cs index 108a2af99..7c0728e7c 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/MethodGraphFieldTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplateTests.cs @@ -7,25 +7,26 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating +namespace GraphQL.AspNet.Tests.Schemas.Generation.Templating { using System.Linq; using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; - using GraphQL.AspNet.Tests.Internal.Templating.DirectiveTestData; - using GraphQL.AspNet.Tests.Internal.Templating.MethodTestData; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.DirectiveTestData; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.MethodTestData; using Moq; using NUnit.Framework; [TestFixture] public class MethodGraphFieldTemplateTests { - private AspNet.Internal.TypeTemplates.MethodGraphFieldTemplate CreateMethodTemplate(string methodName) + private MethodGraphFieldTemplate CreateMethodTemplate(string methodName) { var obj = new Mock(); obj.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/Item0")); @@ -33,7 +34,7 @@ private AspNet.Internal.TypeTemplates.MethodGraphFieldTemplate CreateMethodTempl var parent = obj.Object; var methodInfo = typeof(TObject).GetMethod(methodName); - var template = new AspNet.Internal.TypeTemplates.MethodGraphFieldTemplate(parent, methodInfo, TypeKind.OBJECT); + var template = new MethodGraphFieldTemplate(parent, methodInfo, TypeKind.OBJECT); template.Parse(); template.ValidateOrThrow(); return template; @@ -48,7 +49,7 @@ public void DefaultValuesCheck() var parent = obj.Object; var methodInfo = typeof(MethodClass).GetMethod(nameof(MethodClass.SimpleMethodNoAttributes)); - var template = new AspNet.Internal.TypeTemplates.MethodGraphFieldTemplate(parent, methodInfo, TypeKind.OBJECT); + var template = new MethodGraphFieldTemplate(parent, methodInfo, TypeKind.OBJECT); template.Parse(); template.ValidateOrThrow(); @@ -183,9 +184,9 @@ public void Parse_AssignedDirective_IsTemplatized() var parent = obj.Object; var template = this.CreateMethodTemplate(nameof(MethodClassWithDirective.Counter)); - Assert.AreEqual(1, template.AppliedDirectives.Count()); + Assert.AreEqual(1, Enumerable.Count(template.AppliedDirectives)); - var appliedDirective = template.AppliedDirectives.First(); + var appliedDirective = Enumerable.First(template.AppliedDirectives); Assert.AreEqual(typeof(DirectiveWithArgs), appliedDirective.DirectiveType); Assert.AreEqual(new object[] { 44, "method arg" }, appliedDirective.Arguments); } @@ -200,12 +201,12 @@ public void DefaultNonNullableParameter_NotMarkedRequired() var parent = obj.Object; var template = this.CreateMethodTemplate(nameof(MethodClass.DefaultNonNullableParameter)); - Assert.AreEqual(0, template.AppliedDirectives.Count()); + Assert.AreEqual(0, Enumerable.Count(template.AppliedDirectives)); Assert.AreEqual(1, template.Arguments.Count); var arg = template.Arguments[0]; - Assert.IsTrue(arg.HasDefaultValue); + Assert.IsTrue((bool)arg.HasDefaultValue); Assert.AreEqual(5, arg.DefaultValue); } diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/MethodTestData/ArrayMethodObject.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/MethodTestData/ArrayMethodObject.cs similarity index 78% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/MethodTestData/ArrayMethodObject.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/MethodTestData/ArrayMethodObject.cs index 5323fb855..a29dd0fd3 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/MethodTestData/ArrayMethodObject.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/MethodTestData/ArrayMethodObject.cs @@ -7,10 +7,10 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.MethodTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.MethodTestData { using GraphQL.AspNet.Attributes; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class ArrayMethodObject { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/MethodTestData/MethodClass.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/MethodTestData/MethodClass.cs similarity index 93% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/MethodTestData/MethodClass.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/MethodTestData/MethodClass.cs index f7e9f635e..e05b714f8 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/MethodTestData/MethodClass.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/MethodTestData/MethodClass.cs @@ -7,16 +7,14 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.MethodTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.MethodTestData { using System.Collections.Generic; using System.ComponentModel; using System.Threading.Tasks; using GraphQL.AspNet.Attributes; - using GraphQL.AspNet.Interfaces.Controllers; - using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; - using GraphQL.AspNet.Tests.Framework.Interfaces; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + using GraphQL.AspNet.Tests.Common.Interfaces; public class MethodClass { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/MethodTestData/MethodClassWithDirective.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/MethodTestData/MethodClassWithDirective.cs similarity index 75% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/MethodTestData/MethodClassWithDirective.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/MethodTestData/MethodClassWithDirective.cs index f559532be..c8e279133 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/MethodTestData/MethodClassWithDirective.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/MethodTestData/MethodClassWithDirective.cs @@ -7,10 +7,10 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.MethodTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.MethodTestData { using GraphQL.AspNet.Attributes; - using GraphQL.AspNet.Tests.Internal.Templating.DirectiveTestData; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.DirectiveTestData; public class MethodClassWithDirective { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectGraphTypeTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectGraphTypeTemplateTests.cs similarity index 97% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectGraphTypeTemplateTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectGraphTypeTemplateTests.cs index de2ced3f2..0d280f40b 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectGraphTypeTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectGraphTypeTemplateTests.cs @@ -7,22 +7,21 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates { using System; using System.Collections.Generic; using System.Linq; using System.Reflection; - using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Execution; using GraphQL.AspNet.Execution.Exceptions; - using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; - using GraphQL.AspNet.Tests.Internal.Templating.DirectiveTestData; - using GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.DirectiveTestData; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests; using NUnit.Framework; [TestFixture] diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/CustomStruct.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/CustomStruct.cs similarity index 81% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/CustomStruct.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/CustomStruct.cs index 5da76a453..b20c9b475 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/CustomStruct.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/CustomStruct.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests { public struct CustomStruct { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/DescriptionObject.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/DescriptionObject.cs similarity index 83% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/DescriptionObject.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/DescriptionObject.cs index 95569f0ec..69ca9bf73 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/DescriptionObject.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/DescriptionObject.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests { using System.ComponentModel; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/DescriptionStruct.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/DescriptionStruct.cs similarity index 83% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/DescriptionStruct.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/DescriptionStruct.cs index 7e71d7d8d..b9cdb8594 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/DescriptionStruct.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/DescriptionStruct.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests { using System.ComponentModel; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ForceSkippedStruct.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ForceSkippedStruct.cs similarity index 85% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ForceSkippedStruct.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ForceSkippedStruct.cs index db2ea3110..77405da66 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ForceSkippedStruct.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ForceSkippedStruct.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ForcedSkippedObject.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ForcedSkippedObject.cs similarity index 85% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ForcedSkippedObject.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ForcedSkippedObject.cs index d9dccdbf9..3f1727755 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ForcedSkippedObject.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ForcedSkippedObject.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/IInputObject.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/IInputObject.cs similarity index 82% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/IInputObject.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/IInputObject.cs index ea3af61f8..357f74ce9 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/IInputObject.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/IInputObject.cs @@ -6,7 +6,7 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests { public interface IInputObject { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/InputNameObject.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/InputNameObject.cs similarity index 83% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/InputNameObject.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/InputNameObject.cs index 30556bd5a..48fb9e623 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/InputNameObject.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/InputNameObject.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/InputObjectIWithTaskProperty.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/InputObjectIWithTaskProperty.cs similarity index 85% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/InputObjectIWithTaskProperty.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/InputObjectIWithTaskProperty.cs index 93a82b595..b00f217d7 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/InputObjectIWithTaskProperty.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/InputObjectIWithTaskProperty.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests { using System.Threading.Tasks; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/InputObjectWithDirective.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/InputObjectWithDirective.cs similarity index 74% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/InputObjectWithDirective.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/InputObjectWithDirective.cs index c80715041..7777de2f6 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/InputObjectWithDirective.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/InputObjectWithDirective.cs @@ -6,10 +6,10 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests { using GraphQL.AspNet.Attributes; - using GraphQL.AspNet.Tests.Internal.Templating.DirectiveTestData; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.DirectiveTestData; [ApplyDirective(typeof(DirectiveWithArgs), 33, "input object arg")] public class InputObjectWithDirective diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/InputObjectWithDuplicateProperty.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/InputObjectWithDuplicateProperty.cs similarity index 85% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/InputObjectWithDuplicateProperty.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/InputObjectWithDuplicateProperty.cs index 49a9c8a21..b81a2c77f 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/InputObjectWithDuplicateProperty.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/InputObjectWithDuplicateProperty.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/InputObjectWithGraphActionProperty.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/InputObjectWithGraphActionProperty.cs similarity index 85% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/InputObjectWithGraphActionProperty.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/InputObjectWithGraphActionProperty.cs index 7a752ff94..5225c1b7a 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/InputObjectWithGraphActionProperty.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/InputObjectWithGraphActionProperty.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests { using GraphQL.AspNet.Interfaces.Controllers; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/InputObjectWithInterfaceProperty.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/InputObjectWithInterfaceProperty.cs similarity index 84% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/InputObjectWithInterfaceProperty.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/InputObjectWithInterfaceProperty.cs index c3859038d..3d4d173c1 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/InputObjectWithInterfaceProperty.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/InputObjectWithInterfaceProperty.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests { public class InputObjectWithInterfaceProperty { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/InputObjectWithUnionProxyProperty.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/InputObjectWithUnionProxyProperty.cs similarity index 85% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/InputObjectWithUnionProxyProperty.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/InputObjectWithUnionProxyProperty.cs index 0f503b8a5..cbec99a5b 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/InputObjectWithUnionProxyProperty.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/InputObjectWithUnionProxyProperty.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests { using GraphQL.AspNet.Interfaces.Schema; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectThatInheritsExplicitMethodField.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ObjectThatInheritsExplicitMethodField.cs similarity index 86% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectThatInheritsExplicitMethodField.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ObjectThatInheritsExplicitMethodField.cs index ceb09a837..da5efc7ac 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectThatInheritsExplicitMethodField.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ObjectThatInheritsExplicitMethodField.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectThatInheritsNonExplicitMethodField.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ObjectThatInheritsNonExplicitMethodField.cs similarity index 81% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectThatInheritsNonExplicitMethodField.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ObjectThatInheritsNonExplicitMethodField.cs index fc19eedd0..61e4fc6f6 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectThatInheritsNonExplicitMethodField.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ObjectThatInheritsNonExplicitMethodField.cs @@ -7,10 +7,8 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests { - using GraphQL.AspNet.Attributes; - public class ObjectThatInheritsNonExplicitMethodField : ObjectWithNonExplicitMethodField { public int FieldOnObject(int param2) diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectWithDeconstructor.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ObjectWithDeconstructor.cs similarity index 82% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectWithDeconstructor.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ObjectWithDeconstructor.cs index 4d8f8b750..b62f11e91 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectWithDeconstructor.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ObjectWithDeconstructor.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests { public class ObjectWithDeconstructor { @@ -15,7 +15,7 @@ public class ObjectWithDeconstructor public void Deconstruct(out string prop1) { - prop1 = Property1; + prop1 = this.Property1; } public override string ToString() diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectWithDirective.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ObjectWithDirective.cs similarity index 74% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectWithDirective.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ObjectWithDirective.cs index 1eb178bcd..ce5234fa1 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectWithDirective.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ObjectWithDirective.cs @@ -6,10 +6,10 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests { using GraphQL.AspNet.Attributes; - using GraphQL.AspNet.Tests.Internal.Templating.DirectiveTestData; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.DirectiveTestData; [ApplyDirective(typeof(DirectiveWithArgs), 1, "object arg")] public class ObjectWithDirective diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectWithExplicitMethodField.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ObjectWithExplicitMethodField.cs similarity index 85% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectWithExplicitMethodField.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ObjectWithExplicitMethodField.cs index b9c8be378..b94b67ed1 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectWithExplicitMethodField.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ObjectWithExplicitMethodField.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectWithInvalidNonDeclaredMethods.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ObjectWithInvalidNonDeclaredMethods.cs similarity index 92% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectWithInvalidNonDeclaredMethods.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ObjectWithInvalidNonDeclaredMethods.cs index 52cb3b8a6..311feab64 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectWithInvalidNonDeclaredMethods.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ObjectWithInvalidNonDeclaredMethods.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests { using System.Collections.Generic; using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectWithMutationOperation.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ObjectWithMutationOperation.cs similarity index 87% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectWithMutationOperation.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ObjectWithMutationOperation.cs index 7b8d4809b..4c7935c06 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectWithMutationOperation.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ObjectWithMutationOperation.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectWithNoSetters.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ObjectWithNoSetters.cs similarity index 84% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectWithNoSetters.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ObjectWithNoSetters.cs index bf0078d58..30f2df450 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectWithNoSetters.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ObjectWithNoSetters.cs @@ -6,7 +6,7 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests { public class ObjectWithNoSetters { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectWithNonExplicitMethodField.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ObjectWithNonExplicitMethodField.cs similarity index 80% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectWithNonExplicitMethodField.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ObjectWithNonExplicitMethodField.cs index fddc319bb..95ccbe753 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectWithNonExplicitMethodField.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ObjectWithNonExplicitMethodField.cs @@ -7,10 +7,8 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests { - using GraphQL.AspNet.Attributes; - public class ObjectWithNonExplicitMethodField { public int FieldOnBaseObject(int param1) diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectWithStatics.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ObjectWithStatics.cs similarity index 90% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectWithStatics.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ObjectWithStatics.cs index b685010a0..b2c931c1b 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/ObjectWithStatics.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ObjectWithStatics.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/OneMarkedMethod.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/OneMarkedMethod.cs similarity index 87% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/OneMarkedMethod.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/OneMarkedMethod.cs index ec4063330..15bc38a0b 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/OneMarkedMethod.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/OneMarkedMethod.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/OneMarkedProperty.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/OneMarkedProperty.cs similarity index 85% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/OneMarkedProperty.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/OneMarkedProperty.cs index cd01d7bbf..76cfa144b 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/OneMarkedProperty.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/OneMarkedProperty.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/RequiredConstructor.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/RequiredConstructor.cs similarity index 84% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/RequiredConstructor.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/RequiredConstructor.cs index 0f3ebdb25..d97652a02 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/RequiredConstructor.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/RequiredConstructor.cs @@ -6,7 +6,7 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests { public class RequiredConstructor { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/SimpleObjectNoMethods.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/SimpleObjectNoMethods.cs similarity index 80% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/SimpleObjectNoMethods.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/SimpleObjectNoMethods.cs index 2eb9c1b14..d0970025d 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/SimpleObjectNoMethods.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/SimpleObjectNoMethods.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests { public class SimpleObjectNoMethods { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/SimpleObjectScalar.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/SimpleObjectScalar.cs similarity index 82% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/SimpleObjectScalar.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/SimpleObjectScalar.cs index 39ff86b7c..9b6d0138d 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/SimpleObjectScalar.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/SimpleObjectScalar.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests { public class SimpleObjectScalar { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/SimpleScalarObjectGraphType.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/SimpleScalarObjectGraphType.cs similarity index 90% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/SimpleScalarObjectGraphType.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/SimpleScalarObjectGraphType.cs index bf23db971..46ed73141 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/SimpleScalarObjectGraphType.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/SimpleScalarObjectGraphType.cs @@ -7,10 +7,9 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests { using System; - using GraphQL.AspNet.Common; using GraphQL.AspNet.Schemas.TypeSystem.Scalars; public class SimpleScalarObjectGraphType : ScalarGraphTypeBase diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/SimpleScalarStruct.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/SimpleScalarStruct.cs similarity index 82% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/SimpleScalarStruct.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/SimpleScalarStruct.cs index 075715026..3785f57d7 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/SimpleScalarStruct.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/SimpleScalarStruct.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests { public struct SimpleScalarStruct { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/SimpleScalarStructGraphType.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/SimpleScalarStructGraphType.cs similarity index 90% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/SimpleScalarStructGraphType.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/SimpleScalarStructGraphType.cs index 162f7e03b..8a6fb2002 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/SimpleScalarStructGraphType.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/SimpleScalarStructGraphType.cs @@ -7,10 +7,9 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests { using System; - using GraphQL.AspNet.Common; using GraphQL.AspNet.Schemas.TypeSystem.Scalars; public class SimpleScalarStructGraphType : ScalarGraphTypeBase diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/SimpleStructNoMethods.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/SimpleStructNoMethods.cs similarity index 80% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/SimpleStructNoMethods.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/SimpleStructNoMethods.cs index 2d7d35dc9..dcbc2194b 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/SimpleStructNoMethods.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/SimpleStructNoMethods.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests { public struct SimpleStructNoMethods { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/StructOneMarkedMethod.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/StructOneMarkedMethod.cs similarity index 87% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/StructOneMarkedMethod.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/StructOneMarkedMethod.cs index 2710c54ae..30859e123 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/StructOneMarkedMethod.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/StructOneMarkedMethod.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/StructOneMarkedProperty.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/StructOneMarkedProperty.cs similarity index 85% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/StructOneMarkedProperty.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/StructOneMarkedProperty.cs index 65bb1b788..0dfddb953 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/StructOneMarkedProperty.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/StructOneMarkedProperty.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/StructTwoMethodsWithSameName.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/StructTwoMethodsWithSameName.cs similarity index 88% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/StructTwoMethodsWithSameName.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/StructTwoMethodsWithSameName.cs index db5196728..7843edda8 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/StructTwoMethodsWithSameName.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/StructTwoMethodsWithSameName.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/StructTwoMethodsWithSameNameWithAttributeDiff.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/StructTwoMethodsWithSameNameWithAttributeDiff.cs similarity index 88% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/StructTwoMethodsWithSameNameWithAttributeDiff.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/StructTwoMethodsWithSameNameWithAttributeDiff.cs index f23c44d84..f92fccd40 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/StructTwoMethodsWithSameNameWithAttributeDiff.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/StructTwoMethodsWithSameNameWithAttributeDiff.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/StructWithInvalidNonDeclaredMethods.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/StructWithInvalidNonDeclaredMethods.cs similarity index 92% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/StructWithInvalidNonDeclaredMethods.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/StructWithInvalidNonDeclaredMethods.cs index 8402317c1..c85ae04ee 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/StructWithInvalidNonDeclaredMethods.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/StructWithInvalidNonDeclaredMethods.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests { using System.Collections.Generic; using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/StructWithNoSetters.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/StructWithNoSetters.cs similarity index 84% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/StructWithNoSetters.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/StructWithNoSetters.cs index 61c7acf1f..08db2d059 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/StructWithNoSetters.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/StructWithNoSetters.cs @@ -6,7 +6,7 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests { public struct StructWithNoSetters { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/TwoMethodsWithSameName.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/TwoMethodsWithSameName.cs similarity index 88% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/TwoMethodsWithSameName.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/TwoMethodsWithSameName.cs index 15265fa73..d7d15029b 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/TwoMethodsWithSameName.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/TwoMethodsWithSameName.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/TwoMethodsWithSameNameWithAttributeDiff.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/TwoMethodsWithSameNameWithAttributeDiff.cs similarity index 88% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/TwoMethodsWithSameNameWithAttributeDiff.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/TwoMethodsWithSameNameWithAttributeDiff.cs index cce879993..a9291f58c 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/TwoMethodsWithSameNameWithAttributeDiff.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/TwoMethodsWithSameNameWithAttributeDiff.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/TypeWithArrayProperty.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/TypeWithArrayProperty.cs similarity index 74% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/TypeWithArrayProperty.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/TypeWithArrayProperty.cs index 23d537511..dcf7221df 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ObjectTypeTests/TypeWithArrayProperty.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/TypeWithArrayProperty.cs @@ -7,9 +7,9 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ObjectTypeTests +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests { - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class TypeWithArrayProperty { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ParameterTestData/ParameterTestClass.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ParameterTestData/ParameterTestClass.cs similarity index 93% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ParameterTestData/ParameterTestClass.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ParameterTestData/ParameterTestClass.cs index 7f57f08db..5962ce9c5 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/ParameterTestData/ParameterTestClass.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ParameterTestData/ParameterTestClass.cs @@ -9,14 +9,13 @@ // ReSharper disable InconsistentNaming // ReSharper disable UnusedParameter.Global -namespace GraphQL.AspNet.Tests.Internal.Templating.ParameterTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ParameterTestData { using System.Collections.Generic; using System.ComponentModel; using GraphQL.AspNet.Attributes; - using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Tests.CommonHelpers; - using GraphQL.AspNet.Tests.Internal.Templating.DirectiveTestData; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.DirectiveTestData; public class ParameterTestClass { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyGraphFieldTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyGraphFieldTemplateTests.cs similarity index 93% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyGraphFieldTemplateTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyGraphFieldTemplateTests.cs index 95a2f2c78..bd7d31e6b 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyGraphFieldTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyGraphFieldTemplateTests.cs @@ -7,21 +7,20 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.Templating { using System.Collections.Generic; using System.Linq; - using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Execution.Exceptions; - using GraphQL.AspNet.Internal; using GraphQL.AspNet.Interfaces.Internal; - using GraphQL.AspNet.Internal.TypeTemplates; using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; - using GraphQL.AspNet.Tests.Internal.Templating.DirectiveTestData; - using GraphQL.AspNet.Tests.Internal.Templating.PropertyTestData; + using GraphQL.AspNet.Security; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.DirectiveTestData; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.PropertyTestData; using Moq; using NUnit.Framework; @@ -105,7 +104,7 @@ public void Parse_SecurityPolices_AreAdded() template.Parse(); template.ValidateOrThrow(); - Assert.AreEqual(1, template.SecurityPolicies.Count()); + Assert.AreEqual(1, Enumerable.Count(template.SecurityPolicies)); } [Test] @@ -227,9 +226,9 @@ public void Parse_AssignedDirective_IsTemplatized() var template = new PropertyGraphFieldTemplate(parent, propInfo, TypeKind.OBJECT); template.Parse(); template.ValidateOrThrow(); - Assert.AreEqual(1, template.AppliedDirectives.Count()); + Assert.AreEqual(1, Enumerable.Count(template.AppliedDirectives)); - var appliedDirective = template.AppliedDirectives.First(); + var appliedDirective = Enumerable.First(template.AppliedDirectives); Assert.AreEqual(typeof(DirectiveWithArgs), appliedDirective.DirectiveType); Assert.AreEqual(new object[] { 55, "property arg" }, appliedDirective.Arguments); } diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyTestData/ArrayKeyValuePairObject.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyTestData/ArrayKeyValuePairObject.cs similarity index 84% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyTestData/ArrayKeyValuePairObject.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyTestData/ArrayKeyValuePairObject.cs index 3494b60dd..497af0412 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyTestData/ArrayKeyValuePairObject.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyTestData/ArrayKeyValuePairObject.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.PropertyTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.PropertyTestData { using System.Collections.Generic; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyTestData/ArrayPropertyObject.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyTestData/ArrayPropertyObject.cs similarity index 74% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyTestData/ArrayPropertyObject.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyTestData/ArrayPropertyObject.cs index 2549b7275..5d0be82c5 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyTestData/ArrayPropertyObject.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyTestData/ArrayPropertyObject.cs @@ -7,9 +7,9 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.PropertyTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.PropertyTestData { - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class ArrayPropertyObject { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyTestData/IPropInterface.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyTestData/IPropInterface.cs similarity index 81% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyTestData/IPropInterface.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyTestData/IPropInterface.cs index 3ba2a0097..4d3bc69ee 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyTestData/IPropInterface.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyTestData/IPropInterface.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.PropertyTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.PropertyTestData { public interface IPropInterface { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyTestData/NoGetterOnProperty.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyTestData/NoGetterOnProperty.cs similarity index 84% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyTestData/NoGetterOnProperty.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyTestData/NoGetterOnProperty.cs index 24b3933b1..730161c7c 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyTestData/NoGetterOnProperty.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyTestData/NoGetterOnProperty.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.PropertyTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.PropertyTestData { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyTestData/PropAuthorizeAttribute.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyTestData/PropAuthorizeAttribute.cs similarity index 85% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyTestData/PropAuthorizeAttribute.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyTestData/PropAuthorizeAttribute.cs index 7dd6bc891..7bc20c4d8 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyTestData/PropAuthorizeAttribute.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyTestData/PropAuthorizeAttribute.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.PropertyTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.PropertyTestData { using System; using Microsoft.AspNetCore.Authorization; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyTestData/PropertyClassWithDirective.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyTestData/PropertyClassWithDirective.cs similarity index 74% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyTestData/PropertyClassWithDirective.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyTestData/PropertyClassWithDirective.cs index 76fa7ca7c..40ab0902f 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyTestData/PropertyClassWithDirective.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyTestData/PropertyClassWithDirective.cs @@ -6,10 +6,10 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.PropertyTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.PropertyTestData { using GraphQL.AspNet.Attributes; - using GraphQL.AspNet.Tests.Internal.Templating.DirectiveTestData; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.DirectiveTestData; public class PropertyClassWithDirective { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyTestData/PropertyProxy.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyTestData/PropertyProxy.cs similarity index 82% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyTestData/PropertyProxy.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyTestData/PropertyProxy.cs index 7abbf00b1..cedb375f4 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyTestData/PropertyProxy.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyTestData/PropertyProxy.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.PropertyTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.PropertyTestData { using GraphQL.AspNet.Schemas.TypeSystem; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyTestData/SimplePropertyObject.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyTestData/SimplePropertyObject.cs similarity index 94% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyTestData/SimplePropertyObject.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyTestData/SimplePropertyObject.cs index 294089e10..f941fe7fe 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/PropertyTestData/SimplePropertyObject.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyTestData/SimplePropertyObject.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.PropertyTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.PropertyTestData { using System.Collections.Generic; using System.ComponentModel; @@ -15,7 +15,6 @@ namespace GraphQL.AspNet.Tests.Internal.Templating.PropertyTestData using System.Threading.Tasks; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers.ActionResults; - using GraphQL.AspNet.Schemas.TypeSystem; public class SimplePropertyObject { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/TypeExtensionFieldTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/TypeExtensionFieldTemplateTests.cs similarity index 96% rename from src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/TypeExtensionFieldTemplateTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/TypeExtensionFieldTemplateTests.cs index 6f947719a..7e62435ef 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/Templating/TypeExtensionFieldTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/TypeExtensionFieldTemplateTests.cs @@ -7,25 +7,25 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates { using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Execution; using GraphQL.AspNet.Execution.Exceptions; - using GraphQL.AspNet.Interfaces.Execution; using GraphQL.AspNet.Interfaces.Internal; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; - using GraphQL.AspNet.Tests.Framework.Interfaces; - using GraphQL.AspNet.Tests.Internal.Templating.ExtensionMethodTestData; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + using GraphQL.AspNet.Tests.Common.Interfaces; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ExtensionMethodTestData; using Moq; using NUnit.Framework; [TestFixture] public class TypeExtensionFieldTemplateTests { - private AspNet.Internal.TypeTemplates.GraphTypeExtensionFieldTemplate CreateExtensionTemplate(string actionName) + private GraphTypeExtensionFieldTemplate CreateExtensionTemplate(string actionName) where TControllerType : GraphController { var mockController = new Mock(); @@ -35,7 +35,7 @@ private AspNet.Internal.TypeTemplates.GraphTypeExtensionFieldTemplate CreateExte mockController.Setup(x => x.ObjectType).Returns(typeof(TControllerType)); var methodInfo = typeof(TControllerType).GetMethod(actionName); - var template = new AspNet.Internal.TypeTemplates.GraphTypeExtensionFieldTemplate(mockController.Object, methodInfo); + var template = new GraphTypeExtensionFieldTemplate(mockController.Object, methodInfo); template.Parse(); template.ValidateOrThrow(); diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GraphFieldCloningTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GraphFieldCloningTests.cs index 39e61a7ec..64ace5ee0 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/GraphFieldCloningTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GraphFieldCloningTests.cs @@ -11,15 +11,16 @@ namespace GraphQL.AspNet.Tests.Schemas { using System.Collections.Generic; using System.Linq; + using GraphQL.AspNet.Execution; using GraphQL.AspNet.Execution.Parsing.NodeBuilders; using GraphQL.AspNet.Interfaces.Execution; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal.TypeTemplates; using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Security; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using Microsoft.AspNetCore.Authorization; using Moq; using NUnit.Framework; @@ -129,7 +130,7 @@ public void PropertyField_PropertyCheck() "Prop1", typeof(TwoPropertyObject), typeof(List), - AspNet.Execution.FieldResolutionMode.PerSourceItem, + FieldResolutionMode.PerSourceItem, resolver.Object, polices, appliedDirectives); @@ -150,7 +151,7 @@ public void PropertyField_PropertyCheck() field.IsDeprecated = true; field.DeprecationReason = "Because I said so"; field.Publish = false; - field.FieldSource = AspNet.Internal.TypeTemplates.GraphFieldSource.Method; + field.FieldSource = GraphFieldSource.Method; var clonedParent = new Mock(); clonedParent.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/BobType")); diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GraphTypeExpressionTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GraphTypeExpressionTests.cs index 6b4df0498..fd893cd34 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/GraphTypeExpressionTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GraphTypeExpressionTests.cs @@ -13,7 +13,7 @@ namespace GraphQL.AspNet.Tests.Schemas using System.Collections.Generic; using System.Linq; using GraphQL.AspNet.Schemas; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using NUnit.Framework; using MGT = GraphQL.AspNet.Schemas.TypeSystem.MetaGraphTypes; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GraphValidationTestData/ControllerWithNoSecurityPolicies.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GraphValidationTestData/ControllerWithNoSecurityPolicies.cs index c65b26ea2..7a3cfca0e 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/GraphValidationTestData/ControllerWithNoSecurityPolicies.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GraphValidationTestData/ControllerWithNoSecurityPolicies.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.GraphValidationTestData +namespace GraphQL.AspNet.Tests.Schemas.GraphValidationTestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GraphValidationTestData/ControllerWithSecurityPolicies.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GraphValidationTestData/ControllerWithSecurityPolicies.cs index b20266943..0fd5469c6 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/GraphValidationTestData/ControllerWithSecurityPolicies.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GraphValidationTestData/ControllerWithSecurityPolicies.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.GraphValidationTestData +namespace GraphQL.AspNet.Tests.Schemas.GraphValidationTestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GraphValidationTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GraphValidationTests.cs index ab6edb4db..735c2f398 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/GraphValidationTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GraphValidationTests.cs @@ -7,16 +7,17 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal +namespace GraphQL.AspNet.Tests.Schemas { using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using GraphQL.AspNet.Execution.Exceptions; - using GraphQL.AspNet.Internal; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; - using GraphQL.AspNet.Tests.Internal.GraphValidationTestData; + using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + using GraphQL.AspNet.Tests.Schemas.GraphValidationTestData; + using Microsoft.AspNetCore.Authorization; using NUnit.Framework; [TestFixture] @@ -128,7 +129,7 @@ public void EliminateWrappersFromCoreType( public void RetrieveSecurityPolicies_NullAttributeProvider_YieldsNoPolicies() { var policies = GraphValidation.RetrieveSecurityPolicies(null); - Assert.AreEqual(0, policies.Count()); + Assert.AreEqual(0, Enumerable.Count(policies)); } [Test] @@ -137,7 +138,7 @@ public void RetrieveSecurityPolicies_MethodWithNoSecurityPolicies_ReturnsEmptyEn var info = typeof(ControllerWithNoSecurityPolicies).GetMethod(nameof(ControllerWithNoSecurityPolicies.SomeMethod)); var policies = GraphValidation.RetrieveSecurityPolicies(info); - Assert.AreEqual(0, policies.Count()); + Assert.AreEqual(0, Enumerable.Count(policies)); } [Test] @@ -146,7 +147,7 @@ public void RetrieveSecurityPolicies_MethodWithSecurityPolicies_ReturnsOneItem() var info = typeof(ControllerWithSecurityPolicies).GetMethod(nameof(ControllerWithSecurityPolicies.SomeMethod)); var policies = GraphValidation.RetrieveSecurityPolicies(info); - Assert.AreEqual(1, policies.Count()); + Assert.AreEqual(1, Enumerable.Count(policies)); } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/IntrospectionDefaultValueTestData/TestEnum.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/IntrospectionDefaultValueTestData/TestEnum.cs index c42ea4584..3bc3b4409 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/IntrospectionDefaultValueTestData/TestEnum.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/IntrospectionDefaultValueTestData/TestEnum.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.IntrospectionDefaultValueTestData +namespace GraphQL.AspNet.Tests.Schemas.IntrospectionDefaultValueTestData { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/IntrospectionDefaultValueTestData/TestEnumNoDefaultValue.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/IntrospectionDefaultValueTestData/TestEnumNoDefaultValue.cs index 4ac8593ac..6eef27898 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/IntrospectionDefaultValueTestData/TestEnumNoDefaultValue.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/IntrospectionDefaultValueTestData/TestEnumNoDefaultValue.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.IntrospectionDefaultValueTestData +namespace GraphQL.AspNet.Tests.Schemas.IntrospectionDefaultValueTestData { public enum TestEnumNoDefaultValue { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/IntrospectionDefaultValueTestData/TestEnumNotIncludedDefault.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/IntrospectionDefaultValueTestData/TestEnumNotIncludedDefault.cs index 0f5f4bd08..ece3561d7 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/IntrospectionDefaultValueTestData/TestEnumNotIncludedDefault.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/IntrospectionDefaultValueTestData/TestEnumNotIncludedDefault.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.IntrospectionDefaultValueTestData +namespace GraphQL.AspNet.Tests.Schemas.IntrospectionDefaultValueTestData { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/IntrospectionDefaultValueValidationTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/IntrospectionDefaultValueValidationTests.cs index 2d1b24d77..c1a41dfad 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/IntrospectionDefaultValueValidationTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/IntrospectionDefaultValueValidationTests.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal +namespace GraphQL.AspNet.Tests.Schemas { using System.Collections.Generic; using GraphQL.AspNet.Execution; @@ -17,9 +17,9 @@ namespace GraphQL.AspNet.Tests.Internal using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Schemas.TypeSystem.Introspection.Model; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; - using GraphQL.AspNet.Tests.Internal.IntrospectionDefaultValueTestData; + using GraphQL.AspNet.Tests.Schemas.IntrospectionDefaultValueTestData; using Moq; using NUnit.Framework; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaLanguageGeneratorTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaLanguageGeneratorTests.cs index 21688fb59..d93253421 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaLanguageGeneratorTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaLanguageGeneratorTests.cs @@ -20,8 +20,8 @@ namespace GraphQL.AspNet.Tests.Schemas using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Schemas.TypeSystem.Scalars; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using GraphQL.AspNet.Tests.Schemas.QueryLanguageTestData; using NUnit.Framework; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/ArrayInputAndReturnController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/ArrayInputAndReturnController.cs index 40b34a27e..679b65617 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/ArrayInputAndReturnController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/ArrayInputAndReturnController.cs @@ -11,7 +11,7 @@ namespace GraphQL.AspNet.Tests.Schemas.SchemaTestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class ArrayInputAndReturnController : GraphController { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/ArrayMethodObject.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/ArrayMethodObject.cs index 802eabedd..7ae4dab28 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/ArrayMethodObject.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/ArrayMethodObject.cs @@ -10,7 +10,7 @@ namespace GraphQL.AspNet.Tests.Schemas.SchemaTestData { using GraphQL.AspNet.Attributes; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class ArrayMethodObject { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/ArrayObjectInputController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/ArrayObjectInputController.cs index 24d09ed52..12377e123 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/ArrayObjectInputController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/ArrayObjectInputController.cs @@ -11,7 +11,7 @@ namespace GraphQL.AspNet.Tests.Schemas.SchemaTestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class ArrayObjectInputController : GraphController { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/ArrayPropertyObject.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/ArrayPropertyObject.cs index 7552e9afc..57e327d33 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/ArrayPropertyObject.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/ArrayPropertyObject.cs @@ -9,7 +9,7 @@ namespace GraphQL.AspNet.Tests.Schemas.SchemaTestData { - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class ArrayPropertyObject { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/ArrayReturnController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/ArrayReturnController.cs index 9254d1f2c..47fc588e2 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/ArrayReturnController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/ArrayReturnController.cs @@ -11,7 +11,7 @@ namespace GraphQL.AspNet.Tests.Schemas.SchemaTestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class ArrayReturnController : GraphController { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/ArrayReturnDeclarationController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/ArrayReturnDeclarationController.cs index 0d223cc0b..bf0414125 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/ArrayReturnDeclarationController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/ArrayReturnDeclarationController.cs @@ -12,7 +12,7 @@ namespace GraphQL.AspNet.Tests.Schemas.SchemaTestData using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Interfaces.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class ArrayReturnDeclarationController : GraphController { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/ControllerWithDirectAndIndirectTypeExtension.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/ControllerWithDirectAndIndirectTypeExtension.cs index fd89dd2e4..76ca4db94 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/ControllerWithDirectAndIndirectTypeExtension.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/ControllerWithDirectAndIndirectTypeExtension.cs @@ -11,7 +11,8 @@ namespace GraphQL.AspNet.Tests.Schemas.SchemaTestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + using GraphQL.AspNet.Tests.Common.Interfaces; using GraphQL.AspNet.Tests.Framework.Interfaces; public class ControllerWithDirectAndIndirectTypeExtension : GraphController diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/DictionaryMethodObject.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/DictionaryMethodObject.cs index 8ba0df02f..a23fadbc4 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/DictionaryMethodObject.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/DictionaryMethodObject.cs @@ -12,7 +12,7 @@ namespace GraphQL.AspNet.Tests.Schemas.SchemaTestData using System.Collections.Generic; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class DictionaryMethodObject : GraphController { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/GenericObjectTypeWithGraphTypeName.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/GenericObjectTypeWithGraphTypeName.cs index 4ecb07cfd..877914cce 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/GenericObjectTypeWithGraphTypeName.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/GenericObjectTypeWithGraphTypeName.cs @@ -10,7 +10,7 @@ namespace GraphQL.AspNet.Tests.Schemas.SchemaTestData { using GraphQL.AspNet.Attributes; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; [GraphType(InputName = "OtherName")] public class GenericObjectTypeWithGraphTypeName : TwoPropertyGenericObject diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/KitchenSinkController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/KitchenSinkController.cs index 975b2960e..a55b7fb95 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/KitchenSinkController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/KitchenSinkController.cs @@ -15,8 +15,8 @@ namespace GraphQL.AspNet.Tests.Schemas.SchemaTestData using System.Threading.Tasks; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.CommonHelpers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; [GraphRoute("path0/path1")] [Description("Kitchen sinks are great")] diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/NestedQueryMethodController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/NestedQueryMethodController.cs index 38b40b87f..3fd4c0c88 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/NestedQueryMethodController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/NestedQueryMethodController.cs @@ -12,7 +12,7 @@ namespace GraphQL.AspNet.Tests.Schemas.SchemaTestData using System; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; [GraphRoute("path0")] public class NestedQueryMethodController : GraphController diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/PocoWithInterfaceArgument.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/PocoWithInterfaceArgument.cs index 3f6923695..4751d9b89 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/PocoWithInterfaceArgument.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/PocoWithInterfaceArgument.cs @@ -10,6 +10,7 @@ namespace GraphQL.AspNet.Tests.Schemas.SchemaTestData { using GraphQL.AspNet.Attributes; + using GraphQL.AspNet.Tests.Common.Interfaces; using GraphQL.AspNet.Tests.Framework.Interfaces; public class PocoWithInterfaceArgument diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/SimpleMethodController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/SimpleMethodController.cs index f277b4f45..fac602c25 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/SimpleMethodController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/SimpleMethodController.cs @@ -11,7 +11,7 @@ namespace GraphQL.AspNet.Tests.Schemas.SchemaTestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; /// /// A simple controller utilzing all default values with no overrides. diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/TypeExtensionController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/TypeExtensionController.cs index e85012958..038438cf3 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/TypeExtensionController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTestData/TypeExtensionController.cs @@ -11,7 +11,7 @@ namespace GraphQL.AspNet.Tests.Schemas.SchemaTestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class TypeExtensionController : GraphController { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTypeCollectionInterefaceImplementationTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTypeCollectionInterefaceImplementationTests.cs index 096859a8d..765071038 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTypeCollectionInterefaceImplementationTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTypeCollectionInterefaceImplementationTests.cs @@ -11,7 +11,6 @@ namespace GraphQL.AspNet.Tests.Schemas using System; using System.Collections.Generic; using System.Linq; - using GraphQL.AspNet.Engine.TypeMakers; using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Schemas.TypeSystem; @@ -20,8 +19,8 @@ namespace GraphQL.AspNet.Tests.Schemas using GraphQL.AspNet.Tests.Schemas.SchemaTestData.InterfaceRegistrationTestData; using NUnit.Framework; using GraphQL.AspNet.Schemas.Generation; - using GraphQL.AspNet.Internal.TypeTemplates; using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using Microsoft.AspNetCore.Hosting.Server; using GraphQL.AspNet.Tests.CommonHelpers; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTypeCollectionTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTypeCollectionTests.cs index b3145c9d8..4b7d782f3 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTypeCollectionTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTypeCollectionTests.cs @@ -12,23 +12,23 @@ namespace GraphQL.AspNet.Tests.Schemas using System; using System.Collections.Generic; using System.Linq; - using GraphQL.AspNet.Engine.TypeMakers; using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Schemas.TypeSystem.TypeCollections; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using GraphQL.AspNet.Tests.Schemas.GraphTypeCollectionTestData; using GraphQL.AspNet.Tests.Schemas.SchemaTestData; using NUnit.Framework; using GraphQL.AspNet.Tests.Framework.Interfaces; using GraphQL.AspNet.Schemas.Generation; using GraphQL.AspNet.Schemas.Generation.TypeMakers; - using GraphQL.AspNet.Internal.TypeTemplates; using Microsoft.AspNetCore.Hosting.Server; using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + using GraphQL.AspNet.Tests.Common.Interfaces; using GraphQL.AspNet.Tests.CommonHelpers; [TestFixture] diff --git a/src/unit-tests/graphql-aspnet-tests/Security/MappedQuery_AuthorizationTests.cs b/src/unit-tests/graphql-aspnet-tests/Security/MappedQuery_AuthorizationTests.cs index 038d1f804..96ffe305b 100644 --- a/src/unit-tests/graphql-aspnet-tests/Security/MappedQuery_AuthorizationTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Security/MappedQuery_AuthorizationTests.cs @@ -13,8 +13,8 @@ namespace GraphQL.AspNet.Tests.Security using System.Threading.Tasks; using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Execution; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using NUnit.Framework; [TestFixture] diff --git a/src/unit-tests/graphql-aspnet-tests/Security/PerFieldAuthorizationTests.cs b/src/unit-tests/graphql-aspnet-tests/Security/PerFieldAuthorizationTests.cs index 1d45d3ba3..8d10c3ded 100644 --- a/src/unit-tests/graphql-aspnet-tests/Security/PerFieldAuthorizationTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Security/PerFieldAuthorizationTests.cs @@ -13,8 +13,8 @@ namespace GraphQL.AspNet.Tests.Security using System.Threading.Tasks; using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Security; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using GraphQL.AspNet.Tests.Security.SecurtyGroupData; using NUnit.Framework; diff --git a/src/unit-tests/graphql-aspnet-tests/Security/PerRequestAuthorizationTests.cs b/src/unit-tests/graphql-aspnet-tests/Security/PerRequestAuthorizationTests.cs index 43c4cbd55..fa5c5351d 100644 --- a/src/unit-tests/graphql-aspnet-tests/Security/PerRequestAuthorizationTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Security/PerRequestAuthorizationTests.cs @@ -14,7 +14,7 @@ namespace GraphQL.AspNet.Tests.Security using GraphQL.AspNet.Security; using GraphQL.AspNet.Tests.Framework; using GraphQL.AspNet.Common.Extensions; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using NUnit.Framework; using GraphQL.AspNet.Tests.Security.SecurtyGroupData; diff --git a/src/unit-tests/graphql-aspnet-tests/Security/SecurtyGroupData/PerFieldCounterController.cs b/src/unit-tests/graphql-aspnet-tests/Security/SecurtyGroupData/PerFieldCounterController.cs index 76a82ae51..e831107ca 100644 --- a/src/unit-tests/graphql-aspnet-tests/Security/SecurtyGroupData/PerFieldCounterController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Security/SecurtyGroupData/PerFieldCounterController.cs @@ -11,7 +11,7 @@ namespace GraphQL.AspNet.Tests.Security.SecurtyGroupData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using Microsoft.AspNetCore.Authorization; public class PerFieldCounterController : GraphController diff --git a/src/unit-tests/graphql-aspnet-tests/Security/SecurtyGroupData/PerRequestCounterController.cs b/src/unit-tests/graphql-aspnet-tests/Security/SecurtyGroupData/PerRequestCounterController.cs index a798cd019..5e0eccc5a 100644 --- a/src/unit-tests/graphql-aspnet-tests/Security/SecurtyGroupData/PerRequestCounterController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Security/SecurtyGroupData/PerRequestCounterController.cs @@ -11,7 +11,7 @@ namespace GraphQL.AspNet.Tests.Security.SecurtyGroupData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using Microsoft.AspNetCore.Authorization; public class PerRequestCounterController : GraphController diff --git a/src/unit-tests/graphql-aspnet-tests/Security/SecurtyGroupData/SecuredController.cs b/src/unit-tests/graphql-aspnet-tests/Security/SecurtyGroupData/SecuredController.cs index 196b61dc7..778f853a9 100644 --- a/src/unit-tests/graphql-aspnet-tests/Security/SecurtyGroupData/SecuredController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Security/SecurtyGroupData/SecuredController.cs @@ -11,7 +11,7 @@ namespace GraphQL.AspNet.Tests.Security.SecurtyGroupData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using Microsoft.AspNetCore.Authorization; public class SecuredController : GraphController diff --git a/src/unit-tests/graphql-aspnet-tests/ServerExtensions/MutlipartRequests/BatchGraphQLHttpResponseWriterTests.cs b/src/unit-tests/graphql-aspnet-tests/ServerExtensions/MutlipartRequests/BatchGraphQLHttpResponseWriterTests.cs index 733009d5a..52f3b9301 100644 --- a/src/unit-tests/graphql-aspnet-tests/ServerExtensions/MutlipartRequests/BatchGraphQLHttpResponseWriterTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/ServerExtensions/MutlipartRequests/BatchGraphQLHttpResponseWriterTests.cs @@ -20,8 +20,8 @@ namespace GraphQL.AspNet.Tests.ServerExtensions.MutlipartRequests using GraphQL.AspNet.Interfaces.Execution; using GraphQL.AspNet.Schemas; using GraphQL.AspNet.ServerExtensions.MultipartRequests.Web; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; using Moq; diff --git a/src/unit-tests/graphql-aspnet-tests/ServerExtensions/MutlipartRequests/ConfigTests.cs b/src/unit-tests/graphql-aspnet-tests/ServerExtensions/MutlipartRequests/ConfigTests.cs index ac3c3ed1c..79d3b75c4 100644 --- a/src/unit-tests/graphql-aspnet-tests/ServerExtensions/MutlipartRequests/ConfigTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/ServerExtensions/MutlipartRequests/ConfigTests.cs @@ -14,6 +14,7 @@ namespace GraphQL.AspNet.Tests.ServerExtensions.MutlipartRequests using System.Text; using System.Threading.Tasks; using GraphQL.AspNet.Common.Extensions; + using GraphQL.AspNet.Common.JsonNodes; using GraphQL.AspNet.Schemas; using GraphQL.AspNet.ServerExtensions.MultipartRequests; using GraphQL.AspNet.ServerExtensions.MultipartRequests.Configuration; diff --git a/src/unit-tests/graphql-aspnet-tests/ServerExtensions/MutlipartRequests/MultipartRequestGraphQLHttpProcessorTests.cs b/src/unit-tests/graphql-aspnet-tests/ServerExtensions/MutlipartRequests/MultipartRequestGraphQLHttpProcessorTests.cs index a6b494444..f7b236a53 100644 --- a/src/unit-tests/graphql-aspnet-tests/ServerExtensions/MutlipartRequests/MultipartRequestGraphQLHttpProcessorTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/ServerExtensions/MutlipartRequests/MultipartRequestGraphQLHttpProcessorTests.cs @@ -29,8 +29,8 @@ namespace GraphQL.AspNet.Tests.ServerExtensions.MutlipartRequests using GraphQL.AspNet.ServerExtensions.MultipartRequests.Interfaces; using GraphQL.AspNet.ServerExtensions.MultipartRequests.Schema; using GraphQL.AspNet.ServerExtensions.MultipartRequests.Web; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using GraphQL.AspNet.Tests.ServerExtensions.MutlipartRequests.TestData; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; diff --git a/src/unit-tests/graphql-aspnet-tests/ServerExtensions/MutlipartRequests/TestData/MultiPartFileController.cs b/src/unit-tests/graphql-aspnet-tests/ServerExtensions/MutlipartRequests/TestData/MultiPartFileController.cs index cb3ef7dec..7e177e26b 100644 --- a/src/unit-tests/graphql-aspnet-tests/ServerExtensions/MutlipartRequests/TestData/MultiPartFileController.cs +++ b/src/unit-tests/graphql-aspnet-tests/ServerExtensions/MutlipartRequests/TestData/MultiPartFileController.cs @@ -15,7 +15,7 @@ namespace GraphQL.AspNet.Tests.ServerExtensions.MutlipartRequests.TestData using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; using GraphQL.AspNet.ServerExtensions.MultipartRequests.Model; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class MultiPartFileController : GraphController { diff --git a/src/unit-tests/graphql-aspnet-tests/Web/CancelTokenTests.cs b/src/unit-tests/graphql-aspnet-tests/Web/CancelTokenTests.cs index afdbdc241..fd90ee043 100644 --- a/src/unit-tests/graphql-aspnet-tests/Web/CancelTokenTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Web/CancelTokenTests.cs @@ -18,8 +18,8 @@ namespace GraphQL.AspNet.Tests.Web using System.Threading.Tasks; using GraphQL.AspNet.Engine; using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using GraphQL.AspNet.Tests.Web.CancelTokenTestData; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; diff --git a/src/unit-tests/graphql-aspnet-tests/Web/GetRequestTests.cs b/src/unit-tests/graphql-aspnet-tests/Web/GetRequestTests.cs index 81a0d9cac..d521893d9 100644 --- a/src/unit-tests/graphql-aspnet-tests/Web/GetRequestTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Web/GetRequestTests.cs @@ -17,8 +17,8 @@ namespace GraphQL.AspNet.Tests.Web using System.Web; using GraphQL.AspNet.Engine; using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; using GraphQL.AspNet.Tests.Web.CancelTokenTestData; using GraphQL.AspNet.Tests.Web.WebTestData; using Microsoft.AspNetCore.Http; diff --git a/src/unit-tests/graphql-aspnet-tests/Web/WebTestData/ExternalItemCollectionController.cs b/src/unit-tests/graphql-aspnet-tests/Web/WebTestData/ExternalItemCollectionController.cs index 9a624e60d..65f0f0069 100644 --- a/src/unit-tests/graphql-aspnet-tests/Web/WebTestData/ExternalItemCollectionController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Web/WebTestData/ExternalItemCollectionController.cs @@ -11,7 +11,7 @@ namespace GraphQL.AspNet.Tests.Web.WebTestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class ExternalItemCollectionController : GraphController { diff --git a/src/unit-tests/graphql-aspnet-tests/Web/WebTestData/ItemInjectorHttpProcessor.cs b/src/unit-tests/graphql-aspnet-tests/Web/WebTestData/ItemInjectorHttpProcessor.cs index 919fe985a..2eb09ab90 100644 --- a/src/unit-tests/graphql-aspnet-tests/Web/WebTestData/ItemInjectorHttpProcessor.cs +++ b/src/unit-tests/graphql-aspnet-tests/Web/WebTestData/ItemInjectorHttpProcessor.cs @@ -17,7 +17,7 @@ namespace GraphQL.AspNet.Tests.Web.WebTestData using GraphQL.AspNet.Interfaces.Execution; using GraphQL.AspNet.Interfaces.Logging; using GraphQL.AspNet.Schemas; - using GraphQL.AspNet.Tests.Framework.CommonHelpers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; public class ItemInjectorHttpProcessor : DefaultGraphQLHttpProcessor { From cb8b44e13107b77405246133e9dddb7cf291a218 Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Wed, 12 Jul 2023 18:00:25 -0700 Subject: [PATCH 32/63] WIP, clean up --- .../Execution/ExecutionArgumentCollection.cs | 2 +- .../Interfaces/ITestServerBuilder{TSchema}.cs | 6 ++++++ .../TestServerBuilder{TSchema}.cs | 12 ++++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/graphql-aspnet/Execution/ExecutionArgumentCollection.cs b/src/graphql-aspnet/Execution/ExecutionArgumentCollection.cs index 90974ebe8..e4a1a4725 100644 --- a/src/graphql-aspnet/Execution/ExecutionArgumentCollection.cs +++ b/src/graphql-aspnet/Execution/ExecutionArgumentCollection.cs @@ -116,7 +116,7 @@ public object[] PrepareArguments(IGraphFieldResolverMetaData resolverMetadata) object passedValue = this.ResolveParameterValue(parameter); - var schemaListItem = false; + bool schemaListItem; if (parameter.ArgumentModifiers.IsPartOfTheSchema()) { // additional checks and coersion if this the value is diff --git a/src/unit-tests/graphql-aspnet-testframework/Interfaces/ITestServerBuilder{TSchema}.cs b/src/unit-tests/graphql-aspnet-testframework/Interfaces/ITestServerBuilder{TSchema}.cs index 938ed6259..eccf25c9d 100644 --- a/src/unit-tests/graphql-aspnet-testframework/Interfaces/ITestServerBuilder{TSchema}.cs +++ b/src/unit-tests/graphql-aspnet-testframework/Interfaces/ITestServerBuilder{TSchema}.cs @@ -31,6 +31,12 @@ public interface ITestServerBuilder : ITestServerBuilder, IServiceColle /// TestServerBuilder<TSchema>. ITestServerBuilder AddTestComponent(IGraphQLTestFrameworkComponent component); + /// + ITestServerBuilder AddGraphType(TypeKind? typeKind = null); + + /// + ITestServerBuilder AddGraphType(Type type, TypeKind? typeKind = null); + /// ITestServerBuilder AddType(TypeKind? typeKind = null); diff --git a/src/unit-tests/graphql-aspnet-testframework/TestServerBuilder{TSchema}.cs b/src/unit-tests/graphql-aspnet-testframework/TestServerBuilder{TSchema}.cs index f56925d74..d25d24c31 100644 --- a/src/unit-tests/graphql-aspnet-testframework/TestServerBuilder{TSchema}.cs +++ b/src/unit-tests/graphql-aspnet-testframework/TestServerBuilder{TSchema}.cs @@ -127,6 +127,18 @@ public ITestServerBuilder AddTestComponent(IGraphQLTestFrameworkCompone return this; } + /// + public virtual ITestServerBuilder AddGraphType(TypeKind? typeKind = null) + { + return this.AddType(typeof(TType), typeKind, null); + } + + /// + public virtual ITestServerBuilder AddGraphType(Type type, TypeKind? typeKind = null) + { + return this.AddType(type, typeKind, null); + } + /// public virtual ITestServerBuilder AddType(TypeKind? typeKind = null) { From 8febe44e597b03f9f7af8658d7d3b76e1daefd11 Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Fri, 14 Jul 2023 19:49:38 -0700 Subject: [PATCH 33/63] WIP, unit tests for GlobalTypes class --- src/graphql-aspnet/Constants.cs | 16 +- .../TypeTemplates/AppliedDirectiveTemplate.cs | 4 +- .../TypeTemplates/GraphArgumentTemplate.cs | 2 +- .../TypeTemplates/GraphFieldTemplateBase.cs | 2 +- .../TypeTemplates/GraphTypeTemplateBase.cs | 4 +- .../TypeTemplates/ScalarGraphTypeTemplate.cs | 54 +++- .../TypeTemplates/UnionGraphTypeTemplate.cs | 39 ++- src/graphql-aspnet/Schemas/GraphValidation.cs | 38 +-- ...{GlobalTypes.cs => GlobalTypes_Scalars.cs} | 61 ++--- .../Schemas/TypeSystem/GlobalTypes_Unions.cs | 141 ++++++++++ .../TypeSystem/GraphArgumentModifiers.cs | 25 +- .../Schemas/TypeSystem/TypeKindExtensions.cs | 27 -- .../TypeSystem/UnregisteredGraphField.cs | 2 +- .../Schemas/EnumValueCollectionTests.cs | 90 ++++++ .../TypeTemplates/ArgumentTemplateTests.cs | 9 + .../TypeTemplates/ControllerTemplateTests.cs | 4 +- .../MethodGraphFieldTemplateTests.cs | 4 +- .../ObjectGraphTypeTemplateTests.cs | 4 +- .../ParameterTestData/ParameterTestClass.cs | 3 + .../PropertyGraphFieldTemplateTests.cs | 6 +- .../ScalarGraphTypeTemplateTests.cs | 68 +++++ .../ScalarTestData/MyTestObject.cs | 15 + .../ScalarTestData/MyTestScalar.cs | 89 ++++++ .../UnionGraphTypeTemplateTests.cs | 55 ++++ .../UnionTestData/ValidTestUnion.cs | 25 ++ .../Schemas/GlobalTypeTests.cs | 258 ++++++++++++++++++ .../InvalidGraphTypeNameScalar.cs | 32 +++ .../InvalidNameUnionProxy.cs | 24 ++ .../InvalidParentAppliedDirectivesScalar.cs | 81 ++++++ .../GlobalTypesTestData/NoNameOnScalar.cs | 32 +++ .../GlobalTypesTestData/NoNameUnionProxy.cs | 25 ++ .../GlobalTypesTestData/NoObjectTypeScalar.cs | 80 ++++++ .../NoParameterelessConstructorProxy.cs | 24 ++ .../NoParameterlessConstructorScalar.cs | 31 +++ .../NoSourceResolverScalar.cs | 82 ++++++ .../NoUnionMembersProxy.cs | 22 ++ .../GlobalTypesTestData/NoValueTypeScalar.cs | 81 ++++++ .../NotScalarKindScalar.cs | 90 ++++++ .../NullAppliedDirectivesScalar.cs | 81 ++++++ .../NullTypesUnionProxy.cs | 37 +++ .../ObjectTypeIsNullableScalar.cs | 81 ++++++ .../GlobalTypesTestData/ValidUnionProxy.cs | 24 ++ .../Schemas/GraphValidationTests.cs | 10 + 43 files changed, 1725 insertions(+), 157 deletions(-) rename src/graphql-aspnet/Schemas/TypeSystem/{GlobalTypes.cs => GlobalTypes_Scalars.cs} (88%) create mode 100644 src/graphql-aspnet/Schemas/TypeSystem/GlobalTypes_Unions.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ScalarGraphTypeTemplateTests.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ScalarTestData/MyTestObject.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ScalarTestData/MyTestScalar.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/UnionGraphTypeTemplateTests.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/UnionTestData/ValidTestUnion.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypeTests.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/InvalidGraphTypeNameScalar.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/InvalidNameUnionProxy.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/InvalidParentAppliedDirectivesScalar.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NoNameOnScalar.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NoNameUnionProxy.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NoObjectTypeScalar.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NoParameterelessConstructorProxy.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NoParameterlessConstructorScalar.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NoSourceResolverScalar.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NoUnionMembersProxy.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NoValueTypeScalar.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NotScalarKindScalar.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NullAppliedDirectivesScalar.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NullTypesUnionProxy.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/ObjectTypeIsNullableScalar.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/ValidUnionProxy.cs diff --git a/src/graphql-aspnet/Constants.cs b/src/graphql-aspnet/Constants.cs index 634b885c6..43c5b9142 100644 --- a/src/graphql-aspnet/Constants.cs +++ b/src/graphql-aspnet/Constants.cs @@ -35,6 +35,19 @@ static Constants() { } + /// + /// Other constants that don't fit into a category. + /// + public static class Other + { + /// + /// When a type expression for a field or argument is first parsed, the graph type name is + /// set to this value as a placeholder until such a time as the actual, case-sensitive graph type name + /// is determined. + /// + public const string DEFAULT_TYPE_EXPRESSION_TYPE_NAME = "Type"; + } + /// /// Constants related to the graphql logging framework. /// @@ -211,11 +224,8 @@ public static class ScalarNames public const string ID = "ID"; public const string SHORT = "Short"; public const string USHORT = "UShort"; - -#if NET6_0_OR_GREATER public const string DATEONLY = "DateOnly"; public const string TIMEONLY = "TimeOnly"; -#endif } /// diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/AppliedDirectiveTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/AppliedDirectiveTemplate.cs index fd06b5132..2e9347e22 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/AppliedDirectiveTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/AppliedDirectiveTemplate.cs @@ -107,12 +107,12 @@ public virtual IAppliedDirective CreateAppliedDirective() } /// - public Type DirectiveType { get; } + public Type DirectiveType { get; init; } /// public string DirectiveName { get; private set; } /// - public object[] Arguments { get; } + public object[] Arguments { get; init; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphArgumentTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphArgumentTemplate.cs index bb8b68d02..7ab533e55 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphArgumentTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphArgumentTemplate.cs @@ -121,7 +121,7 @@ public virtual void Parse() // set appropriate meta data about this parameter for inclusion in the type system this.TypeExpression = GraphTypeExpression.FromType(this.DeclaredArgumentType, this.DeclaredTypeWrappers); - this.TypeExpression = this.TypeExpression.CloneTo("Type"); + this.TypeExpression = this.TypeExpression.CloneTo(Constants.Other.DEFAULT_TYPE_EXPRESSION_TYPE_NAME); // when this argument accepts the same data type as the data returned by its owners target source type // i.e. if the source data supplied to the field for resolution is the same as this argument diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphFieldTemplateBase.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphFieldTemplateBase.cs index 549e9d33a..7e484e29f 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphFieldTemplateBase.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphFieldTemplateBase.cs @@ -84,7 +84,7 @@ protected override void ParseTemplateDefinition() var objectType = GraphValidation.EliminateWrappersFromCoreType(this.DeclaredReturnType); var typeExpression = GraphTypeExpression.FromType(this.DeclaredReturnType, this.DeclaredTypeWrappers); - typeExpression = typeExpression.CloneTo("Type"); + typeExpression = typeExpression.CloneTo(Constants.Other.DEFAULT_TYPE_EXPRESSION_TYPE_NAME); // ------------------------------------ // Gather Possible Types and/or union definition diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphTypeTemplateBase.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphTypeTemplateBase.cs index 3a46d6e03..ca540e6f5 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphTypeTemplateBase.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphTypeTemplateBase.cs @@ -60,9 +60,9 @@ protected override void ParseTemplateDefinition() public abstract TypeKind Kind { get; } /// - public TemplateDeclarationRequirements? DeclarationRequirements => _fieldDeclarationOverrides; + public virtual TemplateDeclarationRequirements? DeclarationRequirements => _fieldDeclarationOverrides; /// - public bool Publish { get; private set; } + public virtual bool Publish { get; private set; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/ScalarGraphTypeTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/ScalarGraphTypeTemplate.cs index e5e59e88e..643d11531 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/ScalarGraphTypeTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/ScalarGraphTypeTemplate.cs @@ -10,9 +10,13 @@ namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates { using System; + using System.Collections.Generic; + using System.Linq; using GraphQL.AspNet.Common; + using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Execution; using GraphQL.AspNet.Interfaces.Internal; + using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Security; @@ -23,6 +27,7 @@ namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates public class ScalarGraphTypeTemplate : GraphTypeTemplateBase, IScalarGraphTypeTemplate { private readonly Type _scalarType; + private IScalarGraphType _instance; /// /// Initializes a new instance of the class. @@ -33,6 +38,7 @@ public ScalarGraphTypeTemplate(Type typeToTemplate) { Validation.ThrowIfNull(typeToTemplate, nameof(typeToTemplate)); _scalarType = GlobalTypes.FindBuiltInScalarType(typeToTemplate) ?? typeToTemplate; + _instance = GlobalTypes.CreateScalarInstance(_scalarType); } /// @@ -40,20 +46,35 @@ protected override void ParseTemplateDefinition() { base.ParseTemplateDefinition(); - var instance = GlobalTypes.CreateScalarInstance(this.ScalarType); - - if (instance != null) + if (_instance != null) { - this.Route = new SchemaItemPath(SchemaItemPath.Join(SchemaItemCollections.Types, instance.Name)); - this.ObjectType = instance.ObjectType; + this.Route = new SchemaItemPath(SchemaItemPath.Join(SchemaItemCollections.Types, _instance.Name)); + this.ObjectType = _instance.ObjectType; } } /// public override void ValidateOrThrow() { - base.ValidateOrThrow(); GlobalTypes.ValidateScalarTypeOrThrow(this.ScalarType); + base.ValidateOrThrow(); + } + + /// + protected override IEnumerable ParseAppliedDiretives() + { + if (_instance != null) + { + return _instance.AppliedDirectives.Select(x => new AppliedDirectiveTemplate( + this, + x.DirectiveName, + x.ArgumentValues) + { + DirectiveType = x.DirectiveType, + }); + } + + return Enumerable.Empty(); } /// @@ -63,10 +84,27 @@ public override void ValidateOrThrow() public override TypeKind Kind => TypeKind.SCALAR; /// - public override string InternalFullName => _scalarType.Name; + public override string InternalFullName => _instance?.InternalFullName; /// - public override string InternalName => _scalarType.Name; + public override string InternalName => _scalarType?.Name; + + /// + public override string Name => _instance?.Name; + + /// + public override string Description + { + get + { + return _instance?.Description; + } + + protected set + { + // description is fixed to that in the scalar instance. + } + } /// public Type ScalarType => _scalarType; diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/UnionGraphTypeTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/UnionGraphTypeTemplate.cs index 52663bbcf..6f8d60424 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/UnionGraphTypeTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/UnionGraphTypeTemplate.cs @@ -11,6 +11,7 @@ namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates { using System; using GraphQL.AspNet.Common; + using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Common.Generics; using GraphQL.AspNet.Execution; using GraphQL.AspNet.Execution.Exceptions; @@ -26,6 +27,7 @@ namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates public class UnionGraphTypeTemplate : GraphTypeTemplateBase, IUnionGraphTypeTemplate { private readonly Type _proxyType; + private IGraphUnionProxy _instance; /// /// Initializes a new instance of the class. @@ -34,8 +36,8 @@ public class UnionGraphTypeTemplate : GraphTypeTemplateBase, IUnionGraphTypeTemp public UnionGraphTypeTemplate(Type proxyType) : base(proxyType) { - Validation.ThrowIfNull(proxyType, nameof(proxyType)); _proxyType = proxyType; + this.ObjectType = null; } /// @@ -47,12 +49,11 @@ protected override void ParseTemplateDefinition() { if (_proxyType != null) { - var instance = InstanceFactory.CreateInstance(_proxyType) as IGraphUnionProxy; - if (instance != null) + _instance = InstanceFactory.CreateInstance(_proxyType) as IGraphUnionProxy; + if (_instance != null) { - this.Route = new SchemaItemPath(SchemaItemPath.Join(SchemaItemCollections.Types, instance.Name)); - this.ObjectType = null; + this.Route = new SchemaItemPath(SchemaItemPath.Join(SchemaItemCollections.Types, _instance.Name)); } } } @@ -65,33 +66,31 @@ protected override void ParseTemplateDefinition() public override void ValidateOrThrow() { base.ValidateOrThrow(); - if (_proxyType == null) - { - throw new GraphTypeDeclarationException( - "Unable to create a union graph type template from a null supplied proxy type."); - } - - if (!Validation.IsCastable(_proxyType)) - { - throw new GraphTypeDeclarationException( - $"The type {_proxyType.FriendlyGraphTypeName()} does not implement {nameof(IGraphUnionProxy)}. All " + - $"types being used as a declaration of a union must implement {nameof(IGraphUnionProxy)}."); - } + GlobalTypes.ValidateUnionProxyOrThrow(_proxyType); } /// - public override AppliedSecurityPolicyGroup SecurityPolicies { get; } + public override AppliedSecurityPolicyGroup SecurityPolicies => null; /// - public override TypeKind Kind => TypeKind.SCALAR; + public override string Name => _instance?.Name; /// - public override string InternalFullName => _proxyType?.Name; + public override string Description => _instance?.Description; + + /// + public override TypeKind Kind => TypeKind.UNION; + + /// + public override string InternalFullName => _proxyType?.FriendlyName(true); /// public override string InternalName => _proxyType?.Name; /// public Type ProxyType => _proxyType; + + /// + public override bool Publish => _instance?.Publish ?? false; } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/GraphValidation.cs b/src/graphql-aspnet/Schemas/GraphValidation.cs index 18e331c0b..2ac8731d0 100644 --- a/src/graphql-aspnet/Schemas/GraphValidation.cs +++ b/src/graphql-aspnet/Schemas/GraphValidation.cs @@ -43,41 +43,6 @@ public static IEnumerable RetrieveSecurityPolicies(ICustomAttrib return attributeProvider.GetCustomAttributes(false).OfType(); } - /// - /// Determines whether the given type is parsable and usable by this graphql library. - /// - /// The type to parse. - /// true if the type is parsable; otherwise, false. - public static bool IsParseableType(Type type) - { - if (Validation.IsCastable(type)) - return false; - - return GraphValidation.IsValidGraphType(type); - } - - /// - /// Resolves the of the provided concrete type. If provided, the override - /// value will be used by default if the type does not represent a reserved . If an override value is supplied - /// but the type cannot be corerced into said kind an exception is thrown. - /// - /// The type to check. - /// The override value to use. Pass null to attempt default resolution. - /// TypeKind. - public static TypeKind ResolveTypeKindOrThrow(Type type, TypeKind? overrideValue = null) - { - var outKind = ResolveTypeKind(type, overrideValue); - if (overrideValue.HasValue && outKind != overrideValue.Value && !overrideValue.Value.CanBecome(outKind)) - { - throw new GraphTypeDeclarationException( - $"The concrete type '{type.FriendlyName()}' was to be resolved as a graph type of kind '{overrideValue.Value}' but " + - $"can only be assigned as '{outKind.ToString()}'", - type); - } - - return outKind; - } - /// /// Attempts to classify the provided to determine its /// (enum, scalar, object etc.). If provided, the override @@ -205,6 +170,9 @@ public static void EnsureGraphNameOrThrow(string internalName, string nameToTest /// true if the supplied name represents a valid graph name; otherwise, false. public static bool IsValidGraphName(string nameToTest) { + if (nameToTest == null) + return false; + return Constants.RegExPatterns.NameRegex.IsMatch(nameToTest); } diff --git a/src/graphql-aspnet/Schemas/TypeSystem/GlobalTypes.cs b/src/graphql-aspnet/Schemas/TypeSystem/GlobalTypes_Scalars.cs similarity index 88% rename from src/graphql-aspnet/Schemas/TypeSystem/GlobalTypes.cs rename to src/graphql-aspnet/Schemas/TypeSystem/GlobalTypes_Scalars.cs index ba068c271..f5a59869c 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/GlobalTypes.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/GlobalTypes_Scalars.cs @@ -11,7 +11,6 @@ namespace GraphQL.AspNet.Schemas.TypeSystem { using System; using System.Collections.Generic; - using System.Reflection; using GraphQL.AspNet.Common; using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Common.Generics; @@ -22,17 +21,19 @@ namespace GraphQL.AspNet.Schemas.TypeSystem /// /// A map of .NET types and their related built in scalar types and unions. /// - public static class GlobalTypes + public static partial class GlobalTypes { private static readonly Dictionary _scalarGraphTypeTypesByConcreteType; private static readonly Dictionary _scalarsByName; private static readonly HashSet _fixedNamedScalars; + private static readonly HashSet _allBuiltInScalars; static GlobalTypes() { _scalarGraphTypeTypesByConcreteType = new Dictionary(); _scalarsByName = new Dictionary(StringComparer.OrdinalIgnoreCase); _fixedNamedScalars = new HashSet(); + _allBuiltInScalars = new HashSet(); // specification defined scalars (cannot be altered) ValidateAndRegisterBuiltInScalar(true); @@ -64,17 +65,15 @@ private static void ValidateAndRegisterBuiltInScalar(bool isFixedName = false where T : IScalarGraphType { var instance = CreateScalarInstanceOrThrow(typeof(T)); - if (_scalarGraphTypeTypesByConcreteType.ContainsKey(instance.ObjectType)) + if (_scalarGraphTypeTypesByConcreteType.TryGetValue(instance.ObjectType, out Type registeredType1)) { - var registeredType = _scalarGraphTypeTypesByConcreteType[instance.ObjectType]; throw new GraphTypeDeclarationException( $"The scalar '{typeof(T).FriendlyName()}' is attempting to register a known type of '{instance.ObjectType.FriendlyName()}' but it is " + - $"already reserved by the scalar '{registeredType.FriendlyName()}'. Built in scalar type mappings must be unique."); + $"already reserved by the scalar '{registeredType1.FriendlyName()}'. Built in scalar type mappings must be unique."); } - if (_scalarsByName.ContainsKey(instance.Name)) + if (_scalarsByName.TryGetValue(instance.Name, out Type registeredType)) { - var registeredType = _scalarsByName[instance.Name]; throw new GraphTypeDeclarationException( $"The scalar '{typeof(T).FriendlyName()}' is attempting to register with the name '{instance.Name}' but it is " + $"already reserved by the scalar '{registeredType.FriendlyName()}'. Built in scalar type names must be globally unique."); @@ -83,6 +82,7 @@ private static void ValidateAndRegisterBuiltInScalar(bool isFixedName = false _scalarGraphTypeTypesByConcreteType.Add(instance.ObjectType, typeof(T)); _scalarsByName.Add(instance.Name, typeof(T)); + _allBuiltInScalars.Add(typeof(T)); if (isFixedName) _fixedNamedScalars.Add(typeof(T)); } @@ -114,8 +114,11 @@ public static Type FindBuiltInScalarType(Type typeToCheck) eliminateNullableT: true); } - if (_scalarGraphTypeTypesByConcreteType.ContainsKey(typeToCheck)) - return _scalarGraphTypeTypesByConcreteType[typeToCheck]; + if (_scalarGraphTypeTypesByConcreteType.TryGetValue(typeToCheck, out Type type)) + return type; + + if (_allBuiltInScalars.Contains(typeToCheck)) + return typeToCheck; return null; } @@ -163,9 +166,8 @@ public static bool CanBeRenamed(string scalarName) // if the name represents a globally defined scalar // and if that scalar is declared as a fixed name // then don't allow it to be renamed named - if (_scalarsByName.ContainsKey(scalarName)) + if (_scalarsByName.TryGetValue(scalarName, out Type scalarType)) { - var scalarType = _scalarsByName[scalarName]; return !_fixedNamedScalars.Contains(scalarType); } @@ -202,7 +204,13 @@ public static void ValidateScalarTypeOrThrow(IScalarGraphType graphType) /// System.ValueTuple<System.Boolean, IScalarGraphType>. private static (bool IsValid, IScalarGraphType Instance) CreateAndValidateScalarType(Type scalarType, bool shouldThrow = true) { - Validation.ThrowIfNull(scalarType, nameof(scalarType)); + if (scalarType == null) + { + if (!shouldThrow) + return (false, null); + + throw new GraphTypeDeclarationException("~null~ is an invalid scalar type"); + } if (!Validation.IsCastable(scalarType)) { @@ -249,7 +257,7 @@ private static (bool IsValid, IScalarGraphType Instance) ValidateScalarType(ISca if (!shouldThrow) return (false, null); throw new GraphTypeDeclarationException( - $"The scalar must supply a name that that conforms to the standard rules for GraphQL. (Regex: {Constants.RegExPatterns.NameRegex})"); + $"The scalar {graphType.GetType().FriendlyName()} must supply a name that that conforms to the standard rules for GraphQL. (Regex: {Constants.RegExPatterns.NameRegex})"); } if (graphType.Kind != TypeKind.SCALAR) @@ -347,33 +355,6 @@ public static IScalarGraphType CreateScalarInstance(Type scalarType) return isValid ? instance : null; } - /// - /// attempts to instnatiate the provided type as a union proxy. - /// - /// Type of the proxy to create. - /// IGraphUnionProxy. - public static IGraphUnionProxy CreateUnionProxyFromType(Type proxyType) - { - if (proxyType == null) - return null; - - IGraphUnionProxy proxy = null; - if (Validation.IsCastable(proxyType)) - { - var paramlessConstructor = proxyType.GetConstructor(BindingFlags.Instance | BindingFlags.Public, null, Type.EmptyTypes, null); - if (paramlessConstructor == null) - { - throw new GraphTypeDeclarationException( - $"The union proxy type '{proxyType.FriendlyName()}' could not be instantiated. " + - "All union proxy types must declare a parameterless constructor."); - } - - proxy = InstanceFactory.CreateInstance(proxyType) as IGraphUnionProxy; - } - - return proxy; - } - /// /// Gets the list of concrete types that represent all internally defined, global scalars. /// diff --git a/src/graphql-aspnet/Schemas/TypeSystem/GlobalTypes_Unions.cs b/src/graphql-aspnet/Schemas/TypeSystem/GlobalTypes_Unions.cs new file mode 100644 index 000000000..a43a4e77e --- /dev/null +++ b/src/graphql-aspnet/Schemas/TypeSystem/GlobalTypes_Unions.cs @@ -0,0 +1,141 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Schemas.TypeSystem +{ + using System; + using System.Reflection; + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Common.Extensions; + using GraphQL.AspNet.Common.Generics; + using GraphQL.AspNet.Execution.Exceptions; + using GraphQL.AspNet.Interfaces.Schema; + + /// + /// A map of .NET types and their related built in scalar types and unions. + /// + public static partial class GlobalTypes + { + /// + /// Validates that the type can be instantiated as a union proxy. Throws an exception if it cannot. + /// + /// The Type of the proxy to test. + public static void ValidateUnionProxyOrThrow(Type proxyType) + { + CreateAndValidateUnionProxyType(proxyType, true); + } + + /// + /// Validates that the provided union proxy is valid. If it is not, an exception is thrown. + /// + /// The union proxy instance to test. + public static void ValidateUnionProxyOrThrow(IGraphUnionProxy unionProxy) + { + ValidateUnionProxy(unionProxy, true); + } + + /// + /// Validates that the union proxy type provided is usable as a union within an object graph. + /// + /// The proxy type to validate. + /// if set to true this method should an exception when + /// an invalid proxy is checked. If set to false then false is returned when an invalid proxy is checked. + /// true if the proxy is valid, false otherwise. + private static (bool IsValid, IGraphUnionProxy Instance) CreateAndValidateUnionProxyType(Type proxyType, bool shouldThrow) + { + if (proxyType == null) + { + if (!shouldThrow) + return (false, null); + + throw new GraphTypeDeclarationException("~null~ is an invalid union proxy type."); + } + + if (!Validation.IsCastable(proxyType)) + { + if (!shouldThrow) + return (false, null); + + throw new GraphTypeDeclarationException( + $"The type {proxyType.FriendlyGraphTypeName()} does not implement {nameof(IGraphUnionProxy)}. All " + + $"types being used as a declaration of a union must implement {nameof(IGraphUnionProxy)}."); + } + + var paramlessConstructor = proxyType.GetConstructor(BindingFlags.Instance | BindingFlags.Public, null, Type.EmptyTypes, null); + if (paramlessConstructor == null) + { + if (!shouldThrow) + return (false, null); + throw new GraphTypeDeclarationException( + $"The union proxy type '{proxyType.FriendlyName()}' could not be instantiated. " + + "All union proxy types must declare a parameterless constructor."); + } + + var proxy = InstanceFactory.CreateInstance(proxyType) as IGraphUnionProxy; + return ValidateUnionProxy(proxy, shouldThrow); + } + + private static (bool IsValid, IGraphUnionProxy Instance) ValidateUnionProxy(IGraphUnionProxy proxy, bool shouldThrow) + { + Validation.ThrowIfNull(proxy, nameof(proxy)); + + if (!GraphValidation.IsValidGraphName(proxy.Name)) + { + if (!shouldThrow) + return (false, null); + throw new GraphTypeDeclarationException( + $"The union proxy {proxy.GetType().FriendlyName()} must supply a name that that conforms to the standard rules for GraphQL. (Regex: {Constants.RegExPatterns.NameRegex})"); + } + + if (proxy.Types == null || proxy.Types.Count < 1) + { + if (!shouldThrow) + return (false, null); + + throw new GraphTypeDeclarationException( + $"The union proxy {proxy.GetType().FriendlyName()} must declare at least one valid Type to be a part of the union."); + } + + return (true, proxy); + } + + /// + /// Determines whether the provided type represents an object that is a properly constructed scalar graph type. + /// + /// The type to check. + /// true if the type represents a valid scalar; otherwise, false. + public static bool IsValidUnionProxyType(Type typeToCheck) + { + return CreateAndValidateUnionProxyType(typeToCheck, false).IsValid; + } + + /// + /// Attempts to instnatiate the provided type as a union proxy. If the proxy type is invalid, null is returned. + /// + /// + /// Use to check for correctness. + /// + /// Type of the proxy to create. + /// IGraphUnionProxy. + public static IGraphUnionProxy CreateUnionProxyFromType(Type proxyType) + { + var (isValid, result) = CreateAndValidateUnionProxyType(proxyType, false); + return isValid ? result : null; + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiers.cs b/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiers.cs index 6f0fe49ea..e879c3876 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiers.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiers.cs @@ -9,10 +9,16 @@ namespace GraphQL.AspNet.Schemas.TypeSystem { + using System; + /// /// A set of modifiers and flags that can be assigned to individual arguments on graph fields to modify their behavior /// during execution. /// + /// + /// This enumeration was originally intended to be a bitwise flag but was changed with v2.0 was changed to be + /// a set of distinct values. The power of 2 increments was preserved for backwards compatiability. + /// public enum GraphArgumentModifiers { // implementation note, this used to be a [Flags] enum @@ -23,30 +29,33 @@ public enum GraphArgumentModifiers /// None = 0, - // The Value 1 was deprecated and removed. Its value will not be re-used + // The Value '1' was deprecated and removed. Its value will not be re-used // to ensure no cross contamination of old code in referencing libraries. /// - /// This parameter is declared to contain the result of the resolved parent field. + /// This parameter is declared to contain the result of the value returned from the parent field's resolver. Applicable to + /// type extension and batch extension action methods. /// ParentFieldResult = 2, /// - /// This parameter is declared to be populated with the overall cancellation token + /// This parameter is declared to be a cancellation token /// governing the request or the default token if none was supplied on said request. /// CancellationToken = 4, /// - /// This parameter is declared to be resolved via a DI Container injection. It WILL NEVER be exposed - /// on the object graph. + /// This parameter is declared to be resolved via dependency injection. It will NEVER be exposed + /// on the object graph. If the type represented by this parameter is not servable via a scoped + /// instance, an exception will occur and the target query will not be resolved. /// ExplicitInjected = 8, /// - /// This parameter is declared to be resolved as an argument to a graph field. It WILL ALWAYS be - /// exposed on the object graph. If the argument cannot be exposed because of a rule violation the - /// schema will fail to build. + /// This parameter is declared to be resolved as an argument to a graph field. It will ALWAYS be + /// exposed on the object graph. If the type represented by this parameter cannot be served from the object graph + /// an exception will occur and the schema will fail to generate. This can occur, for instance, if it is an interface, + /// or if the type was explicitly excluded from the graph via attributions. /// ExplicitSchemaItem = 16, } diff --git a/src/graphql-aspnet/Schemas/TypeSystem/TypeKindExtensions.cs b/src/graphql-aspnet/Schemas/TypeSystem/TypeKindExtensions.cs index fe2120d3f..10fef7ebb 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/TypeKindExtensions.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/TypeKindExtensions.cs @@ -14,33 +14,6 @@ namespace GraphQL.AspNet.Schemas.TypeSystem /// public static class TypeKindExtensions { - /// - /// Determines whether this is allowed to be transformed into the provided kind. - /// - /// The kind to check. - /// The kind to become. - /// true if this instance can become the specified kind to become; otherwise, false. - internal static bool CanBecome(this TypeKind kind, TypeKind kindToBecome) - { - switch (kind) - { - case TypeKind.INTERFACE: - return kindToBecome == TypeKind.ENUM || kindToBecome == TypeKind.SCALAR || kindToBecome == TypeKind.OBJECT; - - case TypeKind.OBJECT: - return kindToBecome == TypeKind.ENUM || kindToBecome == TypeKind.SCALAR || kindToBecome == TypeKind.INTERFACE; - - case TypeKind.INPUT_OBJECT: - return kindToBecome == TypeKind.ENUM || kindToBecome == TypeKind.SCALAR; - - case TypeKind.NONE: - return true; - - default: - return false; - } - } - /// /// Determines whether the given kind of graph type is a valid leaf. /// diff --git a/src/graphql-aspnet/Schemas/TypeSystem/UnregisteredGraphField.cs b/src/graphql-aspnet/Schemas/TypeSystem/UnregisteredGraphField.cs index 8df0f369f..68e4ecb4c 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/UnregisteredGraphField.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/UnregisteredGraphField.cs @@ -68,7 +68,7 @@ public override int GetHashCode() /// A comparer to evaluate the equality of two to prevent /// duplicate registrations of extension fields. /// - public class UnregisteredGraphFieldComparer : IEqualityComparer + private class UnregisteredGraphFieldComparer : IEqualityComparer { /// /// Determines whether the specified objects are equal. diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/EnumValueCollectionTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/EnumValueCollectionTests.cs index ed8de7e9b..f01cfa636 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/EnumValueCollectionTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/EnumValueCollectionTests.cs @@ -83,6 +83,26 @@ public void FindEnumValue(EnumValueTestEnum testValue, bool doesValidate, bool s Assert.IsNull(result); } + [Test] + public void FindEnumValue_NullPassed_RetunsNull() + { + var owner = new Mock(); + owner.Setup(x => x.Name).Returns("graphType"); + owner.Setup(x => x.ValidateObject(It.IsAny())).Returns(true); + owner.Setup(x => x.ObjectType).Returns(typeof(EnumValueTestEnum)); + + var enumValue = new Mock(); + enumValue.Setup(x => x.Name).Returns("VALUE1"); + enumValue.Setup(x => x.InternalValue).Returns(EnumValueTestEnum.Value1); + enumValue.Setup(x => x.InternalLabel).Returns(EnumValueTestEnum.Value1.ToString()); + + var collection = new EnumValueCollection(owner.Object); + collection.Add(enumValue.Object); + + var result = collection.FindByEnumValue(null); + Assert.IsNull(result); + } + [TestCase("VALUE1", true)] [TestCase("ValUE1", true)] // not case sensitive [TestCase("VALUE2", false)] @@ -136,5 +156,75 @@ public void ThisByName(string name, bool shouldBeFound) }); } } + + [TestCase("VALUE1", true)] + [TestCase("VALUE2", false)] + public void TryGetValue(string name, bool shouldBeFound) + { + var owner = new Mock(); + owner.Setup(x => x.Name).Returns("graphType"); + owner.Setup(x => x.ObjectType).Returns(typeof(EnumValueTestEnum)); + + var enumValue = new Mock(); + enumValue.Setup(x => x.Name).Returns("VALUE1"); + enumValue.Setup(x => x.InternalValue).Returns(EnumValueTestEnum.Value1); + enumValue.Setup(x => x.InternalLabel).Returns(EnumValueTestEnum.Value1.ToString()); + + var collection = new EnumValueCollection(owner.Object); + collection.Add(enumValue.Object); + + var result = collection.TryGetValue(name, out var item); + if(shouldBeFound) + { + Assert.IsTrue(result); + Assert.IsNotNull(item); + Assert.AreEqual(enumValue.Object, item); + } + else + { + Assert.IsFalse(result); + Assert.IsNull(item); + } + } + + [Test] + public void Remove_ValidValueIsRemoved() + { + var owner = new Mock(); + owner.Setup(x => x.Name).Returns("graphType"); + owner.Setup(x => x.ObjectType).Returns(typeof(EnumValueTestEnum)); + + var enumValue = new Mock(); + enumValue.Setup(x => x.Name).Returns("VALUE1"); + enumValue.Setup(x => x.InternalValue).Returns(EnumValueTestEnum.Value1); + enumValue.Setup(x => x.InternalLabel).Returns(EnumValueTestEnum.Value1.ToString()); + + var collection = new EnumValueCollection(owner.Object); + collection.Add(enumValue.Object); + + Assert.AreEqual(1, collection.Count); + collection.Remove("VALUE1"); + Assert.AreEqual(0, collection.Count); + } + + [Test] + public void Remove_InvalidValueIsIgnored() + { + var owner = new Mock(); + owner.Setup(x => x.Name).Returns("graphType"); + owner.Setup(x => x.ObjectType).Returns(typeof(EnumValueTestEnum)); + + var enumValue = new Mock(); + enumValue.Setup(x => x.Name).Returns("VALUE1"); + enumValue.Setup(x => x.InternalValue).Returns(EnumValueTestEnum.Value1); + enumValue.Setup(x => x.InternalLabel).Returns(EnumValueTestEnum.Value1.ToString()); + + var collection = new EnumValueCollection(owner.Object); + collection.Add(enumValue.Object); + + Assert.AreEqual(1, collection.Count); + collection.Remove("VALUE1DDD"); + Assert.AreEqual(1, collection.Count); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ArgumentTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ArgumentTemplateTests.cs index 6e8fc8b56..cd17b4328 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ArgumentTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ArgumentTemplateTests.cs @@ -292,5 +292,14 @@ public void IncompatiableTypeExpressionNullToNotNull_ThrowsException() var template = this.ExtractParameterTemplate("incompatiableTypeExpressionNullToNotNull", out var paramInfo); }); } + + [Test] + public void ArgumentAttributedasFromGraphQLAndFromServices_ThrowsException() + { + Assert.Throws(() => + { + var template = this.ExtractParameterTemplate("doubleDeclaredObject", out var paramInfo); + }); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTemplateTests.cs index 7f5feee29..508cc9abd 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTemplateTests.cs @@ -65,7 +65,7 @@ public void Parse_OverloadedMethodsOnDifferentRoots_ParsesCorrectly() public void Parse_ReturnArrayOnAction_ParsesCorrectly() { var expectedTypeExpression = new GraphTypeExpression( - "Type", + Constants.Other.DEFAULT_TYPE_EXPRESSION_TYPE_NAME, MetaGraphTypes.IsList); var template = new GraphControllerTemplate(typeof(ArrayReturnController)); @@ -83,7 +83,7 @@ public void Parse_ReturnArrayOnAction_ParsesCorrectly() public void Parse_ArrayOnInputParameter_ParsesCorrectly() { var expectedTypeExpression = new GraphTypeExpression( - "Type", + Constants.Other.DEFAULT_TYPE_EXPRESSION_TYPE_NAME, MetaGraphTypes.IsList); var template = new GraphControllerTemplate(typeof(ArrayInputParamController)); diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplateTests.cs index 7c0728e7c..bafa99156 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplateTests.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Schemas.Generation.Templating +namespace GraphQL.AspNet.Tests.Schemas.Generation { using System.Linq; using GraphQL.AspNet.Common.Extensions; @@ -160,7 +160,7 @@ public void ArrayFromMethod_YieldsTemplate() obj.Setup(x => x.InternalFullName).Returns("Item0"); var expectedTypeExpression = new GraphTypeExpression( - "Type", + Constants.Other.DEFAULT_TYPE_EXPRESSION_TYPE_NAME, MetaGraphTypes.IsList); var parent = obj.Object; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectGraphTypeTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectGraphTypeTemplateTests.cs index 0d280f40b..5f03281be 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectGraphTypeTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectGraphTypeTemplateTests.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates +namespace GraphQL.AspNet.Tests.Schemas.Generation { using System; using System.Collections.Generic; @@ -295,7 +295,7 @@ public void Parse_ArrayProperty_ExtractsListOfCoreType() Assert.AreEqual(1, template.FieldTemplates.Count); var expectedTypeExpression = new GraphTypeExpression( - "Type", + Constants.Other.DEFAULT_TYPE_EXPRESSION_TYPE_NAME, MetaGraphTypes.IsList); Assert.AreEqual(1, template.FieldTemplates.Count()); diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ParameterTestData/ParameterTestClass.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ParameterTestData/ParameterTestClass.cs index 5962ce9c5..5b77ab3d3 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ParameterTestData/ParameterTestClass.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ParameterTestData/ParameterTestClass.cs @@ -14,8 +14,10 @@ namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ParameterTestDat using System.Collections.Generic; using System.ComponentModel; using GraphQL.AspNet.Attributes; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.CommonHelpers; using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.DirectiveTestData; + using Microsoft.AspNetCore.Mvc; public class ParameterTestClass { @@ -46,6 +48,7 @@ public int TestMethod( [FromGraphQL(TypeExpression = "[Type]")] int incompatiableTypeExpressionListToSingle, [FromGraphQL(TypeExpression = "Type!")] int[] incompatiableTypeExpressionSingleToList, [FromGraphQL(TypeExpression = "Type")] int incompatiableTypeExpressionNullToNotNull, // nullable expression, actual type is not nullable + [FromGraphQL] [FromServices] TwoPropertyObject doubleDeclaredObject, Person defaultValueObjectArg = null, string defaultValueStringArg = null, string defaultValueStringArgWithValue = "abc", diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyGraphFieldTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyGraphFieldTemplateTests.cs index bd7d31e6b..453221743 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyGraphFieldTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyGraphFieldTemplateTests.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.Templating +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates { using System.Collections.Generic; using System.Linq; @@ -171,7 +171,7 @@ public void Parse_BasicObject_PropertyReturnsArray_YieldsTemplate() obj.Setup(x => x.InternalFullName).Returns("Item0"); var expectedTypeExpression = new GraphTypeExpression( - "Type", + Constants.Other.DEFAULT_TYPE_EXPRESSION_TYPE_NAME, MetaGraphTypes.IsList); var parent = obj.Object; @@ -193,7 +193,7 @@ public void Parse_BasicObject_PropertyReturnsArrayOfKeyValuePair_YieldsTemplate( obj.Setup(x => x.InternalFullName).Returns("Item0"); var expectedTypeExpression = new GraphTypeExpression( - "Type", // expression is expected to be unnamed at the template level + Constants.Other.DEFAULT_TYPE_EXPRESSION_TYPE_NAME, // expression is expected to be unnamed at the template level MetaGraphTypes.IsList, MetaGraphTypes.IsNotNull); // structs can't be null diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ScalarGraphTypeTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ScalarGraphTypeTemplateTests.cs new file mode 100644 index 000000000..c8806b0b0 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ScalarGraphTypeTemplateTests.cs @@ -0,0 +1,68 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates +{ + using System.Linq; + using GraphQL.AspNet.Directives.Global; + using GraphQL.AspNet.Execution.Exceptions; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; + using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Schemas.TypeSystem.Scalars; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ScalarTestData; + using NuGet.Frameworks; + using NUnit.Framework; + + [TestFixture] + public class ScalarGraphTypeTemplateTests + { + [Test] + public void ValidScalar_PropertyCheck() + { + var template = new ScalarGraphTypeTemplate(typeof(MyTestScalar)); + template.Parse(); + template.ValidateOrThrow(); + + Assert.AreEqual(TypeKind.SCALAR, template.Kind); + Assert.AreEqual("myScalar", template.Name); + Assert.AreEqual("[type]/myScalar", template.Route.Path); + Assert.AreEqual("myScalar Desc", template.Description); + Assert.IsTrue(template.Publish); + Assert.AreEqual("My.Test.Scalar", template.InternalFullName); + Assert.AreEqual(typeof(MyTestScalar), template.ScalarType); + Assert.AreEqual(nameof(MyTestScalar), template.InternalName); + Assert.AreEqual(typeof(MyTestObject), template.ObjectType); + Assert.IsFalse(template.DeclarationRequirements.HasValue); + + Assert.AreEqual(2, template.AppliedDirectives.Count()); + Assert.AreEqual("myDirective", template.AppliedDirectives.First().DirectiveName); + Assert.IsNull(template.AppliedDirectives.First().DirectiveType); + Assert.AreEqual(1, template.AppliedDirectives.First().Arguments.Count()); + Assert.AreEqual("arg1", template.AppliedDirectives.First().Arguments.First().ToString()); + + Assert.IsNull(template.AppliedDirectives.Skip(1).First().DirectiveName); + Assert.AreEqual(typeof(SkipDirective), template.AppliedDirectives.Skip(1).First().DirectiveType); + Assert.AreEqual(1, template.AppliedDirectives.Skip(1).First().Arguments.Count()); + Assert.AreEqual("argA", template.AppliedDirectives.Skip(1).First().Arguments.First().ToString()); + } + + [Test] + public void InValidScalar_ThrowsExceptionOnValidate() + { + var template = new ScalarGraphTypeTemplate(typeof(TwoPropertyObject)); + template.Parse(); + + Assert.Throws(() => + { + template.ValidateOrThrow(); + }); + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ScalarTestData/MyTestObject.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ScalarTestData/MyTestObject.cs new file mode 100644 index 000000000..e974dab94 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ScalarTestData/MyTestObject.cs @@ -0,0 +1,15 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ScalarTestData +{ + public class MyTestObject + { + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ScalarTestData/MyTestScalar.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ScalarTestData/MyTestScalar.cs new file mode 100644 index 000000000..f5be9c9de --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ScalarTestData/MyTestScalar.cs @@ -0,0 +1,89 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ScalarTestData +{ + using System; + using GraphQL.AspNet.Attributes; + using GraphQL.AspNet.Directives.Global; + using GraphQL.AspNet.Execution; + using GraphQL.AspNet.Interfaces.Execution; + using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Schemas.Structural; + using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Schemas.TypeSystem.Scalars; + using Moq; + + [ApplyDirective("directive1")] + public class MyTestScalar : IScalarGraphType + { + public MyTestScalar() + { + this.Kind = TypeKind.SCALAR; + this.SpecifiedByUrl = "http://mytestsclar.org"; + this.ValueType = ScalarValueType.Boolean; + this.Name = "myScalar"; + this.Description = "myScalar Desc"; + this.Route = new SchemaItemPath(SchemaItemCollections.Scalars, this.Name); + this.InternalFullName = "My.Test.Scalar"; + this.ObjectType = typeof(MyTestObject); + this.SourceResolver = new Mock().Object; + this.Publish = true; + + var dir = new AppliedDirectiveCollection(this); + dir.Add(new AppliedDirective("myDirective", "arg1")); + dir.Add(new AppliedDirective(typeof(SkipDirective), "argA")); + this.AppliedDirectives = dir; + } + + public ScalarValueType ValueType { get; } + + public ILeafValueResolver SourceResolver { get; set; } + + public string SpecifiedByUrl { get; set; } + + public TypeKind Kind { get; } + + public bool Publish { get; set; } + + public bool IsVirtual { get; } + + public Type ObjectType { get; } + + public string InternalFullName { get; } + + public SchemaItemPath Route { get; } + + public IAppliedDirectiveCollection AppliedDirectives { get; } + + public string Name { get; } + + public string Description { get; set; } + + public IScalarGraphType Clone(string newName) + { + throw new NotImplementedException(); + } + + public object Serialize(object item) + { + throw new NotImplementedException(); + } + + public string SerializeToQueryLanguage(object item) + { + throw new NotImplementedException(); + } + + public bool ValidateObject(object item) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/UnionGraphTypeTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/UnionGraphTypeTemplateTests.cs new file mode 100644 index 000000000..2e1492ef7 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/UnionGraphTypeTemplateTests.cs @@ -0,0 +1,55 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates +{ + using System; + using System.Security.Cryptography; + using GraphQL.AspNet.Common.Extensions; + using GraphQL.AspNet.Execution.Exceptions; + using GraphQL.AspNet.Interfaces.Internal; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; + using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.UnionTestData; + using NUnit.Framework; + + [TestFixture] + public class UnionGraphTypeTemplateTests + { + [Test] + public void NotAProxy_ThrowsException() + { + var instance = new UnionGraphTypeTemplate(typeof(TwoPropertyObject)); + instance.Parse(); + + Assert.Throws(() => + { + instance.ValidateOrThrow(); + }); + } + + [Test] + public void ValidateProxy_ParsesCorrectly() + { + var instance = new UnionGraphTypeTemplate(typeof(ValidTestUnion)); + + instance.Parse(); + instance.ValidateOrThrow(); + + Assert.AreEqual(TypeKind.UNION, instance.Kind); + Assert.AreEqual("ValidUnion", instance.Name); + Assert.AreEqual("My Union Desc", instance.Description); + Assert.AreEqual(typeof(ValidTestUnion).FriendlyName(true), instance.InternalFullName); + Assert.AreEqual("ValidTestUnion", typeof(ValidTestUnion).Name); + Assert.AreEqual(typeof(ValidTestUnion), instance.ProxyType); + Assert.IsTrue(instance.Publish); + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/UnionTestData/ValidTestUnion.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/UnionTestData/ValidTestUnion.cs new file mode 100644 index 000000000..007760433 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/UnionTestData/ValidTestUnion.cs @@ -0,0 +1,25 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.UnionTestData +{ + using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + + public class ValidTestUnion : GraphUnionProxy + { + public ValidTestUnion() + { + this.Name = "ValidUnion"; + this.Description = "My Union Desc"; + this.Types.Add(typeof(TwoPropertyObject)); + this.Types.Add(typeof(TwoPropertyObjectV2)); + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypeTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypeTests.cs new file mode 100644 index 000000000..3f4d929a8 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypeTests.cs @@ -0,0 +1,258 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas +{ + using System; + using System.Linq; + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Execution.Exceptions; + using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Schemas.TypeSystem.Scalars; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + using GraphQL.AspNet.Tests.Schemas.GlobalTypesTestData; + using Microsoft.AspNetCore.Mvc.ApplicationParts; + using NUnit.Framework; + + public class GlobalTypeTests + { + [Test] + public void AllInternalScalarsExistInGlobalCollection() + { + // sanity check to ensure wireups are correct + var types = typeof(IntScalarType).Assembly + .GetTypes() + .Where(x => Validation.IsCastable(x) + && !x.IsAbstract + && x.FullName.StartsWith("GraphQL.AspNet.Schemas.TypeSystem.Scalars")); + + foreach (var type in types) + { + Assert.IsTrue(GlobalTypes.IsBuiltInScalar(type), $"{type.Name} is not declared as built in but should be"); + } + } + + [TestCase("Int", true)] + [TestCase("int", true)] // test for case-insensitiveness + [TestCase("INT", true)] + [TestCase("Float", true)] + [TestCase("Boolean", true)] + [TestCase("String", true)] + [TestCase("Id", true)] + [TestCase("Long", true)] + [TestCase("UInt", true)] + [TestCase("ULong", true)] + [TestCase("Double", true)] + [TestCase("Decimal", true)] + [TestCase("DateTimeOffset", true)] + [TestCase("DateTime", true)] + [TestCase("DateOnly", true)] + [TestCase("TimeOnly", true)] + [TestCase("Byte", true)] + [TestCase("SignedByte", true)] + [TestCase("Short", true)] + [TestCase("UShort", true)] + [TestCase("Guid", true)] + [TestCase("Uri", true)] + + [TestCase("NotAScalar", false)] + [TestCase(null, false)] + public static void BuiltInScalarNames(string name, bool isBuiltIn) + { + Assert.AreEqual(isBuiltIn, GlobalTypes.IsBuiltInScalar(name)); + } + + [TestCase("Int", false)] + [TestCase("Float", false)] + [TestCase("Boolean", false)] + [TestCase("String", false)] + [TestCase("Id", false)] + [TestCase("Long", true)] + [TestCase("UInt", true)] + [TestCase("ULong", true)] + [TestCase("Double", true)] + [TestCase("Decimal", true)] + [TestCase("DateTimeOffset", true)] + [TestCase("DateTime", true)] + [TestCase("DateOnly", true)] + [TestCase("TimeOnly", true)] + [TestCase("Byte", true)] + [TestCase("SignedByte", true)] + [TestCase("Short", true)] + [TestCase("UShort", true)] + [TestCase("Guid", true)] + [TestCase("Uri", true)] + [TestCase(null, true)] + public static void CanBeRenamed(string name, bool canBeRenamed) + { + Assert.AreEqual(canBeRenamed, GlobalTypes.CanBeRenamed(name)); + } + + [TestCase(typeof(int), typeof(IntScalarType))] + [TestCase(typeof(TwoPropertyObject), null)] + [TestCase(null, null)] + public static void FindBuiltInScalarType(Type typeToTest, Type expectedOutput) + { + var result = GlobalTypes.FindBuiltInScalarType(typeToTest); + Assert.AreEqual(expectedOutput, result); + } + + [TestCase(typeof(IntScalarType), false)] + [TestCase(null, true)] // no type provided + [TestCase(typeof(NoParameterlessConstructorScalar), true)] + [TestCase(typeof(TwoPropertyObject), true)] // does not implement iScalarGraphType + [TestCase(typeof(InvalidGraphTypeNameScalar), true)] + [TestCase(typeof(NoNameOnScalar), true)] + [TestCase(typeof(NoObjectTypeScalar), true)] + [TestCase(typeof(NotScalarKindScalar), true)] + [TestCase(typeof(ObjectTypeIsNullableScalar), true)] + [TestCase(typeof(NoSourceResolverScalar), true)] + [TestCase(typeof(NoValueTypeScalar), true)] + [TestCase(typeof(NullAppliedDirectivesScalar), true)] + [TestCase(typeof(InvalidParentAppliedDirectivesScalar), true)] + public static void ValidateScalarorThrow(Type typeToTest, bool shouldThrow) + { + try + { + GlobalTypes.ValidateScalarTypeOrThrow(typeToTest); + } + catch (GraphTypeDeclarationException) + { + if (shouldThrow) + return; + + Assert.Fail("Threw when it shouldnt"); + } + catch (Exception ex) + { + Assert.Fail("Threw invalid exception type"); + } + + if (!shouldThrow) + return; + + Assert.Fail("Didn't throw when it should"); + } + + [TestCase(typeof(IntScalarType), true)] + [TestCase(null, false)] // no type provided + [TestCase(typeof(NoParameterlessConstructorScalar), false)] + [TestCase(typeof(TwoPropertyObject), false)] // does not implement iScalarGraphType + [TestCase(typeof(InvalidGraphTypeNameScalar), false)] + [TestCase(typeof(NoNameOnScalar), false)] + [TestCase(typeof(NoObjectTypeScalar), false)] + [TestCase(typeof(NotScalarKindScalar), false)] + [TestCase(typeof(ObjectTypeIsNullableScalar), false)] + [TestCase(typeof(NoSourceResolverScalar), false)] + [TestCase(typeof(NoValueTypeScalar), false)] + [TestCase(typeof(NullAppliedDirectivesScalar), false)] + [TestCase(typeof(InvalidParentAppliedDirectivesScalar), false)] + public static void IsValidScalar(Type typeToTest, bool isValid) + { + var result = GlobalTypes.IsValidScalarType(typeToTest); + Assert.AreEqual(isValid, result); + } + + [Test] + public static void ValdidateScalarType_ByScalarInstance_ValidScalar() + { + // shoudl not throw + var instance = new IntScalarType(); + GlobalTypes.ValidateScalarTypeOrThrow(instance); + } + + [Test] + public static void ValdidateScalarType_ByScalarInstance_InvalidScalar() + { + // shoudl not throw + var instance = new NoNameOnScalar(); + Assert.Throws(() => + { + GlobalTypes.ValidateScalarTypeOrThrow(instance); + }); + } + + [TestCase(null, true)] + [TestCase(typeof(TwoPropertyObject), true)] // not a union proxy + [TestCase(typeof(NoParameterelessConstructorProxy), true)] + [TestCase(typeof(NoNameUnionProxy), true)] + [TestCase(typeof(InvalidNameUnionProxy), true)] + [TestCase(typeof(NoUnionMembersProxy), true)] + [TestCase(typeof(NullTypesUnionProxy), true)] + [TestCase(typeof(ValidUnionProxy), false)] + public void ValidateUnionProxyOrThrow(Type typeToTest, bool shouldThrow) + { + try + { + GlobalTypes.ValidateUnionProxyOrThrow(typeToTest); + } + catch (GraphTypeDeclarationException) + { + if (shouldThrow) + return; + + Assert.Fail("Threw when it shouldnt"); + } + catch (Exception ex) + { + Assert.Fail("Threw invalid exception type"); + } + + if (!shouldThrow) + return; + + Assert.Fail("Didn't throw when it should"); + } + + [TestCase(null, false)] + [TestCase(typeof(TwoPropertyObject), false )] // not a union proxy + [TestCase(typeof(NoParameterelessConstructorProxy), false)] + [TestCase(typeof(NoNameUnionProxy), false)] + [TestCase(typeof(InvalidNameUnionProxy), false)] + [TestCase(typeof(NoUnionMembersProxy), false)] + [TestCase(typeof(NullTypesUnionProxy), false)] + [TestCase(typeof(ValidUnionProxy), true)] + public void IsValidUnionProxyType(Type typeToTest, bool isValid) + { + var result = GlobalTypes.IsValidUnionProxyType(typeToTest); + Assert.AreEqual(isValid, result); + } + + [Test] + public void ValidateUnionProxyOrThrow_ByInstance_ValidProxy() + { + // should not throw + GlobalTypes.ValidateUnionProxyOrThrow(new ValidUnionProxy()); + } + + [Test] + public void ValidateUnionProxyOrThrow_ByInstance_InvalidProxy() + { + // should not throw + Assert.Throws(() => + { + GlobalTypes.ValidateUnionProxyOrThrow(new NoNameUnionProxy()); + }); + } + + [TestCase(typeof(ValidUnionProxy), true)] + [TestCase(null, false)] + [TestCase(typeof(NoNameUnionProxy), false)] + public void CreateUnionTypeFromProxy(Type proxyType, bool shouldReturnValue) + { + var reslt = GlobalTypes.CreateUnionProxyFromType(proxyType); + + if (shouldReturnValue) + Assert.IsNotNull(reslt); + else + Assert.IsNull(reslt); + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/InvalidGraphTypeNameScalar.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/InvalidGraphTypeNameScalar.cs new file mode 100644 index 000000000..d26907195 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/InvalidGraphTypeNameScalar.cs @@ -0,0 +1,32 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.GlobalTypesTestData +{ + using System; + using GraphQL.AspNet.Schemas.TypeSystem.Scalars; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + + public class InvalidGraphTypeNameScalar : ScalarGraphTypeBase + { + public InvalidGraphTypeNameScalar() + : base("name", typeof(TwoPropertyObject)) + { + this.Name = "Not#$aName"; + this.ValueType = ScalarValueType.String; + } + + public override ScalarValueType ValueType { get; } + + public override object Resolve(ReadOnlySpan data) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/InvalidNameUnionProxy.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/InvalidNameUnionProxy.cs new file mode 100644 index 000000000..bcba875db --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/InvalidNameUnionProxy.cs @@ -0,0 +1,24 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.GlobalTypesTestData +{ + using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + + public class InvalidNameUnionProxy : GraphUnionProxy + { + public InvalidNameUnionProxy() + { + this.Name = "NotaGraphName#*$(@#$"; + this.Types.Add(typeof(TwoPropertyObject)); + this.Types.Add(typeof(TwoPropertyObjectV2)); + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/InvalidParentAppliedDirectivesScalar.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/InvalidParentAppliedDirectivesScalar.cs new file mode 100644 index 000000000..ddbe3b124 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/InvalidParentAppliedDirectivesScalar.cs @@ -0,0 +1,81 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.GlobalTypesTestData +{ + using System; + using GraphQL.AspNet.Interfaces.Execution; + using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Schemas.Structural; + using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Schemas.TypeSystem.Scalars; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + using Moq; + + public class InvalidParentAppliedDirectivesScalar : IScalarGraphType + { + public InvalidParentAppliedDirectivesScalar() + { + this.Name = "ValidName"; + this.ValueType = ScalarValueType.String; + this.SourceResolver = new Mock().Object; + this.ObjectType = typeof(TwoPropertyStruct); + this.AppliedDirectives = new AppliedDirectiveCollection(new Mock().Object); + } + + public ScalarValueType ValueType { get; } + + public ILeafValueResolver SourceResolver { get; set; } + + public string SpecifiedByUrl { get; set; } + + public TypeKind Kind => TypeKind.SCALAR; + + public bool Publish { get; set; } + + public bool IsVirtual { get; } + + public Type ObjectType { get; } + + public string InternalFullName { get; } + + public SchemaItemPath Route { get; } + + public IAppliedDirectiveCollection AppliedDirectives { get; } + + public string Name { get; } + + public string Description { get; set; } + + public IScalarGraphType Clone(string newName) + { + throw new NotImplementedException(); + } + + public object Resolve(ReadOnlySpan data) + { + throw new NotImplementedException(); + } + + public object Serialize(object item) + { + throw new NotImplementedException(); + } + + public string SerializeToQueryLanguage(object item) + { + throw new NotImplementedException(); + } + + public bool ValidateObject(object item) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NoNameOnScalar.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NoNameOnScalar.cs new file mode 100644 index 000000000..aaba6db30 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NoNameOnScalar.cs @@ -0,0 +1,32 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.GlobalTypesTestData +{ + using System; + using GraphQL.AspNet.Schemas.TypeSystem.Scalars; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + + public class NoNameOnScalar : ScalarGraphTypeBase + { + public NoNameOnScalar() + : base("something", typeof(TwoPropertyObject)) + { + this.Name = null; + this.ValueType = ScalarValueType.String; + } + + public override ScalarValueType ValueType { get; } + + public override object Resolve(ReadOnlySpan data) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NoNameUnionProxy.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NoNameUnionProxy.cs new file mode 100644 index 000000000..7d3b5c161 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NoNameUnionProxy.cs @@ -0,0 +1,25 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.GlobalTypesTestData +{ + using Castle.Components.DictionaryAdapter; + using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + + public class NoNameUnionProxy : GraphUnionProxy + { + public NoNameUnionProxy() + { + this.Name = null; + this.Types.Add(typeof(TwoPropertyObject)); + this.Types.Add(typeof(TwoPropertyObjectV2)); + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NoObjectTypeScalar.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NoObjectTypeScalar.cs new file mode 100644 index 000000000..381b8f329 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NoObjectTypeScalar.cs @@ -0,0 +1,80 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.GlobalTypesTestData +{ + using System; + using GraphQL.AspNet.Interfaces.Execution; + using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Schemas.Structural; + using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Schemas.TypeSystem.Scalars; + using Moq; + + public class NoObjectTypeScalar : IScalarGraphType + { + public NoObjectTypeScalar() + { + this.Name = "ValidName"; + this.ValueType = ScalarValueType.String; + this.SourceResolver = new Mock().Object; + this.ObjectType = null; + this.AppliedDirectives = new AppliedDirectiveCollection(this); + } + + public ScalarValueType ValueType { get; } + + public ILeafValueResolver SourceResolver { get; set; } + + public string SpecifiedByUrl { get; set; } + + public TypeKind Kind => TypeKind.SCALAR; + + public bool Publish { get; set; } + + public bool IsVirtual { get; } + + public Type ObjectType { get; } + + public string InternalFullName { get; } + + public SchemaItemPath Route { get; } + + public IAppliedDirectiveCollection AppliedDirectives { get; } + + public string Name { get; } + + public string Description { get; set; } + + public IScalarGraphType Clone(string newName) + { + throw new NotImplementedException(); + } + + public object Resolve(ReadOnlySpan data) + { + throw new NotImplementedException(); + } + + public object Serialize(object item) + { + throw new NotImplementedException(); + } + + public string SerializeToQueryLanguage(object item) + { + throw new NotImplementedException(); + } + + public bool ValidateObject(object item) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NoParameterelessConstructorProxy.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NoParameterelessConstructorProxy.cs new file mode 100644 index 000000000..410a4e599 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NoParameterelessConstructorProxy.cs @@ -0,0 +1,24 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.GlobalTypesTestData +{ + using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + + public class NoParameterelessConstructorProxy : GraphUnionProxy + { + public NoParameterelessConstructorProxy(string name) + { + this.Name = name; + this.Types.Add(typeof(TwoPropertyObject)); + this.Types.Add(typeof(TwoPropertyObjectV2)); + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NoParameterlessConstructorScalar.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NoParameterlessConstructorScalar.cs new file mode 100644 index 000000000..abd6423b4 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NoParameterlessConstructorScalar.cs @@ -0,0 +1,31 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.GlobalTypesTestData +{ + using System; + using GraphQL.AspNet.Schemas.TypeSystem.Scalars; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + + public class NoParameterlessConstructorScalar : ScalarGraphTypeBase + { + public NoParameterlessConstructorScalar(string name) + : base(name, typeof(TwoPropertyObject)) + { + this.ValueType = ScalarValueType.Boolean; + } + + public override ScalarValueType ValueType { get; } + + public override object Resolve(ReadOnlySpan data) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NoSourceResolverScalar.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NoSourceResolverScalar.cs new file mode 100644 index 000000000..08fc07a0b --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NoSourceResolverScalar.cs @@ -0,0 +1,82 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.GlobalTypesTestData +{ + using System; + using GraphQL.AspNet.Interfaces.Execution; + using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Schemas.Structural; + using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Schemas.TypeSystem.Scalars; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + using Moq; + + public class NoSourceResolverScalar : IScalarGraphType + { + public NoSourceResolverScalar() + { + this.Name = "ValidName"; + this.ValueType = ScalarValueType.String; + this.Kind = TypeKind.SCALAR; + this.SourceResolver = null; + this.ObjectType = typeof(TwoPropertyStruct); + this.AppliedDirectives = new AppliedDirectiveCollection(this); + } + + public ScalarValueType ValueType { get; } + + public ILeafValueResolver SourceResolver { get; set; } + + public string SpecifiedByUrl { get; set; } + + public TypeKind Kind { get; } + + public bool Publish { get; set; } + + public bool IsVirtual { get; } + + public Type ObjectType { get; } + + public string InternalFullName { get; } + + public SchemaItemPath Route { get; } + + public IAppliedDirectiveCollection AppliedDirectives { get; } + + public string Name { get; } + + public string Description { get; set; } + + public IScalarGraphType Clone(string newName) + { + throw new NotImplementedException(); + } + + public object Resolve(ReadOnlySpan data) + { + throw new NotImplementedException(); + } + + public object Serialize(object item) + { + throw new NotImplementedException(); + } + + public string SerializeToQueryLanguage(object item) + { + throw new NotImplementedException(); + } + + public bool ValidateObject(object item) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NoUnionMembersProxy.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NoUnionMembersProxy.cs new file mode 100644 index 000000000..0cae246a4 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NoUnionMembersProxy.cs @@ -0,0 +1,22 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.GlobalTypesTestData +{ + using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + + public class NoUnionMembersProxy : GraphUnionProxy + { + public NoUnionMembersProxy() + { + this.Name = "Name"; + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NoValueTypeScalar.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NoValueTypeScalar.cs new file mode 100644 index 000000000..6cff6e8a7 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NoValueTypeScalar.cs @@ -0,0 +1,81 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.GlobalTypesTestData +{ + using System; + using GraphQL.AspNet.Interfaces.Execution; + using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Schemas.Structural; + using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Schemas.TypeSystem.Scalars; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + using Moq; + + public class NoValueTypeScalar : IScalarGraphType + { + public NoValueTypeScalar() + { + this.Name = "ValidName"; + this.ValueType = ScalarValueType.Unknown; + this.SourceResolver = new Mock().Object; + this.ObjectType = typeof(TwoPropertyStruct); + this.AppliedDirectives = new AppliedDirectiveCollection(this); + } + + public ScalarValueType ValueType { get; } + + public ILeafValueResolver SourceResolver { get; set; } + + public string SpecifiedByUrl { get; set; } + + public TypeKind Kind => TypeKind.SCALAR; + + public bool Publish { get; set; } + + public bool IsVirtual { get; } + + public Type ObjectType { get; } + + public string InternalFullName { get; } + + public SchemaItemPath Route { get; } + + public IAppliedDirectiveCollection AppliedDirectives { get; } + + public string Name { get; } + + public string Description { get; set; } + + public IScalarGraphType Clone(string newName) + { + throw new NotImplementedException(); + } + + public object Resolve(ReadOnlySpan data) + { + throw new NotImplementedException(); + } + + public object Serialize(object item) + { + throw new NotImplementedException(); + } + + public string SerializeToQueryLanguage(object item) + { + throw new NotImplementedException(); + } + + public bool ValidateObject(object item) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NotScalarKindScalar.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NotScalarKindScalar.cs new file mode 100644 index 000000000..25a769b79 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NotScalarKindScalar.cs @@ -0,0 +1,90 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.GlobalTypesTestData +{ + using System; + using GraphQL.AspNet.Interfaces.Execution; + using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Schemas.Structural; + using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Schemas.TypeSystem.Scalars; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + using Moq; + + public class NotScalarKindScalar : IScalarGraphType + { + public NotScalarKindScalar() + { + this.Name = "ValidName"; + this.ValueType = ScalarValueType.String; + this.SourceResolver = new Mock().Object; + this.ObjectType = typeof(TwoPropertyObject); + this.AppliedDirectives = new AppliedDirectiveCollection(this); + } + + public ScalarValueType ValueType { get; } + + public ILeafValueResolver SourceResolver { get; set; } + + public string SpecifiedByUrl { get; set; } + + public TypeKind Kind => TypeKind.OBJECT; + + public bool Publish { get; set; } + + public bool IsVirtual { get; } + + public Type ObjectType { get; } + + public string InternalFullName { get; } + + public SchemaItemPath Route { get; } + + public IAppliedDirectiveCollection AppliedDirectives { get; } + + public string Name { get; } + + public string Description { get; set; } + + public IScalarGraphType Clone(string newName) + { + throw new NotImplementedException(); + } + + public object Resolve(ReadOnlySpan data) + { + throw new NotImplementedException(); + } + + public object Serialize(object item) + { + throw new NotImplementedException(); + } + + public string SerializeToQueryLanguage(object item) + { + throw new NotImplementedException(); + } + + public bool ValidateObject(object item) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NullAppliedDirectivesScalar.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NullAppliedDirectivesScalar.cs new file mode 100644 index 000000000..4bd6b1940 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NullAppliedDirectivesScalar.cs @@ -0,0 +1,81 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.GlobalTypesTestData +{ + using System; + using GraphQL.AspNet.Interfaces.Execution; + using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Schemas.Structural; + using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Schemas.TypeSystem.Scalars; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + using Moq; + + public class NullAppliedDirectivesScalar : IScalarGraphType + { + public NullAppliedDirectivesScalar() + { + this.Name = "ValidName"; + this.ValueType = ScalarValueType.String; + this.SourceResolver = new Mock().Object; + this.ObjectType = typeof(TwoPropertyStruct); + this.AppliedDirectives = null; + } + + public ScalarValueType ValueType { get; } + + public ILeafValueResolver SourceResolver { get; set; } + + public string SpecifiedByUrl { get; set; } + + public TypeKind Kind => TypeKind.SCALAR; + + public bool Publish { get; set; } + + public bool IsVirtual { get; } + + public Type ObjectType { get; } + + public string InternalFullName { get; } + + public SchemaItemPath Route { get; } + + public IAppliedDirectiveCollection AppliedDirectives { get; } + + public string Name { get; } + + public string Description { get; set; } + + public IScalarGraphType Clone(string newName) + { + throw new NotImplementedException(); + } + + public object Resolve(ReadOnlySpan data) + { + throw new NotImplementedException(); + } + + public object Serialize(object item) + { + throw new NotImplementedException(); + } + + public string SerializeToQueryLanguage(object item) + { + throw new NotImplementedException(); + } + + public bool ValidateObject(object item) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NullTypesUnionProxy.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NullTypesUnionProxy.cs new file mode 100644 index 000000000..599c5107d --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NullTypesUnionProxy.cs @@ -0,0 +1,37 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.GlobalTypesTestData +{ + using System; + using System.Collections.Generic; + using GraphQL.AspNet.Interfaces.Schema; + + public class NullTypesUnionProxy : IGraphUnionProxy + { + public NullTypesUnionProxy() + { + this.Name = "Name"; + this.Types = null; + } + + public HashSet Types { get; } + + public bool Publish { get; set; } + + public string Name { get; } + + public string Description { get; set; } + + public Type MapType(Type runtimeObjectType) + { + return null; + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/ObjectTypeIsNullableScalar.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/ObjectTypeIsNullableScalar.cs new file mode 100644 index 000000000..00fce028b --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/ObjectTypeIsNullableScalar.cs @@ -0,0 +1,81 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.GlobalTypesTestData +{ + using System; + using GraphQL.AspNet.Interfaces.Execution; + using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Schemas.Structural; + using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Schemas.TypeSystem.Scalars; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + using Moq; + + public class ObjectTypeIsNullableScalar : IScalarGraphType + { + public ObjectTypeIsNullableScalar() + { + this.Name = "ValidName"; + this.ValueType = ScalarValueType.String; + this.SourceResolver = new Mock().Object; + this.ObjectType = typeof(TwoPropertyStruct?); + this.AppliedDirectives = new AppliedDirectiveCollection(this); + } + + public ScalarValueType ValueType { get; } + + public ILeafValueResolver SourceResolver { get; set; } + + public string SpecifiedByUrl { get; set; } + + public TypeKind Kind => TypeKind.SCALAR; + + public bool Publish { get; set; } + + public bool IsVirtual { get; } + + public Type ObjectType { get; } + + public string InternalFullName { get; } + + public SchemaItemPath Route { get; } + + public IAppliedDirectiveCollection AppliedDirectives { get; } + + public string Name { get; } + + public string Description { get; set; } + + public IScalarGraphType Clone(string newName) + { + throw new NotImplementedException(); + } + + public object Resolve(ReadOnlySpan data) + { + throw new NotImplementedException(); + } + + public object Serialize(object item) + { + throw new NotImplementedException(); + } + + public string SerializeToQueryLanguage(object item) + { + throw new NotImplementedException(); + } + + public bool ValidateObject(object item) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/ValidUnionProxy.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/ValidUnionProxy.cs new file mode 100644 index 000000000..75f702cfb --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/ValidUnionProxy.cs @@ -0,0 +1,24 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.GlobalTypesTestData +{ + using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + + public class ValidUnionProxy : GraphUnionProxy + { + public ValidUnionProxy() + { + this.Name = "name"; + this.Types.Add(typeof(TwoPropertyObject)); + this.Types.Add(typeof(TwoPropertyObjectV2)); + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GraphValidationTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GraphValidationTests.cs index 735c2f398..89c2c2d4b 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/GraphValidationTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GraphValidationTests.cs @@ -149,5 +149,15 @@ public void RetrieveSecurityPolicies_MethodWithSecurityPolicies_ReturnsOneItem() var policies = GraphValidation.RetrieveSecurityPolicies(info); Assert.AreEqual(1, Enumerable.Count(policies)); } + + [TestCase("BobSmith", true)] + [TestCase("Bob##Smith", false)] + [TestCase("", false)] + [TestCase(null, false)] + public void IsValidName(string name, bool isValid) + { + var result = GraphValidation.IsValidGraphName(name); + Assert.AreEqual(isValid, result); + } } } \ No newline at end of file From f295e0d5a0d1d5992b05013ab7655e588b377893 Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Fri, 14 Jul 2023 21:41:36 -0700 Subject: [PATCH 34/63] WIP, ready for injected service tests --- ...tGraphQLSchemaFactory_RuntimeDefinitions.cs | 2 ++ .../TypeTemplates/UnionGraphTypeTemplate.cs | 5 +---- .../GraphFieldValidator.cs | 18 ++++++++++++++++++ .../Schemas/TypeSystem/GlobalTypes_Unions.cs | 9 --------- .../Configuration/ConfigurationSetupTests.cs | 1 - .../Engine/DefaultSchemaFactoryTests.cs | 11 +++++++++-- .../GeneralQueryExecutionRuntimeFieldTests.cs | 6 ------ .../Schemas/EnumValueCollectionTests.cs | 2 +- .../Schemas/GlobalTypeTests.cs | 6 +++--- .../GlobalTypesTestData/NotScalarKindScalar.cs | 9 --------- 10 files changed, 34 insertions(+), 35 deletions(-) diff --git a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_RuntimeDefinitions.cs b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_RuntimeDefinitions.cs index e5a2fb0d1..17ba38463 100644 --- a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_RuntimeDefinitions.cs +++ b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_RuntimeDefinitions.cs @@ -27,6 +27,8 @@ protected virtual void AddRuntimeSchemaItemDefinition(IGraphQLRuntimeSchemaItemD { if (itemDefinition is IGraphQLRuntimeResolvedFieldDefinition fieldDef) this.AddRuntimeFieldDefinition(fieldDef); + + // TODO: Add support for directives } /// diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/UnionGraphTypeTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/UnionGraphTypeTemplate.cs index 6f8d60424..5965281d4 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/UnionGraphTypeTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/UnionGraphTypeTemplate.cs @@ -10,11 +10,9 @@ namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates { using System; - using GraphQL.AspNet.Common; using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Common.Generics; using GraphQL.AspNet.Execution; - using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Schemas.Structural; @@ -49,8 +47,7 @@ protected override void ParseTemplateDefinition() { if (_proxyType != null) { - - _instance = InstanceFactory.CreateInstance(_proxyType) as IGraphUnionProxy; + _instance = GlobalTypes.CreateUnionProxyFromType(_proxyType); if (_instance != null) { this.Route = new SchemaItemPath(SchemaItemPath.Join(SchemaItemCollections.Types, _instance.Name)); diff --git a/src/graphql-aspnet/Schemas/SchemaItemValidators/GraphFieldValidator.cs b/src/graphql-aspnet/Schemas/SchemaItemValidators/GraphFieldValidator.cs index 49a1e5daf..009ec2bbe 100644 --- a/src/graphql-aspnet/Schemas/SchemaItemValidators/GraphFieldValidator.cs +++ b/src/graphql-aspnet/Schemas/SchemaItemValidators/GraphFieldValidator.cs @@ -12,8 +12,26 @@ namespace GraphQL.AspNet.Schemas.SchemaItemValidators using System; using GraphQL.AspNet.Interfaces.Schema; + /// + /// A runtime validator that will inspect and ensure the integrity of a + /// before a schema is placed online. + /// internal class GraphFieldValidator : BaseSchemaItemValidator { + /// + /// Gets the singular instnace of this validator. + /// + /// The instance. + public static ISchemaItemValidator Instance { get; } = new GraphFieldValidator(); + + /// + /// Prevents a default instance of the class from being created. + /// + private GraphFieldValidator() + { + } + + /// public override void ValidateOrThrow(ISchemaItem schemaItem, ISchema schema) { } diff --git a/src/graphql-aspnet/Schemas/TypeSystem/GlobalTypes_Unions.cs b/src/graphql-aspnet/Schemas/TypeSystem/GlobalTypes_Unions.cs index a43a4e77e..c2226e635 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/GlobalTypes_Unions.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/GlobalTypes_Unions.cs @@ -7,15 +7,6 @@ // License: MIT // ************************************************************* -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - namespace GraphQL.AspNet.Schemas.TypeSystem { using System; diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Configuration/ConfigurationSetupTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Configuration/ConfigurationSetupTests.cs index 0fb0419fe..39b35af29 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Configuration/ConfigurationSetupTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Configuration/ConfigurationSetupTests.cs @@ -156,7 +156,6 @@ public void AddSubscriptionPublishing_RegistrationChecks() using var restorePoint = new GraphQLGlobalSubscriptionRestorePoint(); // ensure the runtime is in a default state (just in case the statics got messed up) - var serviceCollection = new ServiceCollection(); // the internal publisher (added by default) diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTests.cs b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTests.cs index 8e92788ef..9da1faa58 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTests.cs @@ -7,6 +7,15 @@ // License: MIT // ************************************************************* +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + namespace GraphQL.AspNet.Tests.Engine { using System; @@ -16,13 +25,11 @@ namespace GraphQL.AspNet.Tests.Engine using GraphQL.AspNet.Interfaces.Engine; using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Schemas; - using GraphQL.AspNet.Schemas.Generation; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Common.Interfaces; using GraphQL.AspNet.Tests.Engine.DefaultSchemaFactoryTestData; - using GraphQL.AspNet.Tests.Framework.Interfaces; using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionRuntimeFieldTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionRuntimeFieldTests.cs index 86aae17a2..f1993a2ec 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionRuntimeFieldTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionRuntimeFieldTests.cs @@ -316,9 +316,6 @@ public async Task BasicMappedQuery_WithExplicitlyDeclaredInjectedService_Returni [Test] public async Task BasicMappedQuery_WithImplicitlyDeclaredInjectedService_ReturningValueResult_ResolvesCorrectly() { - Assert.Inconclusive("Need to finish this test"); - return; - var serverBuilder = new TestServerBuilder(); serverBuilder.AddTransient(); @@ -351,9 +348,6 @@ public async Task BasicMappedQuery_WithImplicitlyDeclaredInjectedService_Returni [Test] public async Task BasicMappedQuery_WithImplicitlyDeclaredInjectedService_ReturningActionResult_ResolvesCorrectly() { - Assert.Inconclusive("Need to finish this test"); - return; - var serverBuilder = new TestServerBuilder(); serverBuilder.AddTransient(); diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/EnumValueCollectionTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/EnumValueCollectionTests.cs index f01cfa636..9226d9a79 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/EnumValueCollectionTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/EnumValueCollectionTests.cs @@ -174,7 +174,7 @@ public void TryGetValue(string name, bool shouldBeFound) collection.Add(enumValue.Object); var result = collection.TryGetValue(name, out var item); - if(shouldBeFound) + if (shouldBeFound) { Assert.IsTrue(result); Assert.IsNotNull(item); diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypeTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypeTests.cs index 3f4d929a8..9d1b600ec 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypeTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypeTests.cs @@ -130,7 +130,7 @@ public static void ValidateScalarorThrow(Type typeToTest, bool shouldThrow) Assert.Fail("Threw when it shouldnt"); } - catch (Exception ex) + catch (Exception) { Assert.Fail("Threw invalid exception type"); } @@ -200,7 +200,7 @@ public void ValidateUnionProxyOrThrow(Type typeToTest, bool shouldThrow) Assert.Fail("Threw when it shouldnt"); } - catch (Exception ex) + catch (Exception) { Assert.Fail("Threw invalid exception type"); } @@ -212,7 +212,7 @@ public void ValidateUnionProxyOrThrow(Type typeToTest, bool shouldThrow) } [TestCase(null, false)] - [TestCase(typeof(TwoPropertyObject), false )] // not a union proxy + [TestCase(typeof(TwoPropertyObject), false)] // not a union proxy [TestCase(typeof(NoParameterelessConstructorProxy), false)] [TestCase(typeof(NoNameUnionProxy), false)] [TestCase(typeof(InvalidNameUnionProxy), false)] diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NotScalarKindScalar.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NotScalarKindScalar.cs index 25a769b79..841ed90bf 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NotScalarKindScalar.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NotScalarKindScalar.cs @@ -7,15 +7,6 @@ // License: MIT // ************************************************************* -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - namespace GraphQL.AspNet.Tests.Schemas.GlobalTypesTestData { using System; From ebada7efd831e403ef2d84c1b6c7809e023fca95 Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Sat, 15 Jul 2023 06:50:21 -0700 Subject: [PATCH 35/63] WIP, unit test org updates --- ...hemaItemDefinitionExtensions_Directives.cs | 24 ++++----- ...chemaItemDefinitionExtensions_Internals.cs | 2 +- .../SchemaArgumentBindingRules.cs | 45 +++++++++++----- .../SchemaDeclarationConfiguration.cs | 17 ++---- ...GraphQLSchemaFactory_RuntimeDefinitions.cs | 29 +++++++++-- .../Rule_5_8_VariableDeclarationChecks.cs | 1 - .../ISchemaDeclarationConfiguration.cs | 8 ++- ... => IGraphQLRuntimeDirectiveDefinition.cs} | 2 +- .../TypeTemplates/GraphArgumentTemplate.cs | 10 ++-- .../RuntimeDirectiveActionDefinition.cs | 4 +- .../Engine/DefaultSchemaFactoryTests.cs | 9 ---- .../Parsing/SourceTextLexerExtensionsTests.cs | 4 +- .../MappedDirectiveTemplateTests.cs | 10 ++-- .../MappedMutationGroupTests.cs | 2 +- .../MappedMutationTemplateTests.cs | 2 +- .../MappedQueryGroupTests.cs | 2 +- .../MappedQueryTemplateTests.cs | 2 +- .../MappedTypeExtensionTemplateTests.cs | 2 +- .../ResolvedFieldTemplateTests.cs | 2 +- .../TypeMakers/DirectiveTypeMakerTests.cs | 19 +++---- .../TypeMakers/EnumGraphTypeMakerTests.cs | 21 ++++---- .../TypeMakers/FieldMaker_InputFieldTests.cs | 22 ++++---- .../FieldMaker_StandardFieldTests.cs | 23 ++++---- .../TypeMakers/GraphTypeMakerTestBase.cs | 12 ++--- .../InputObjectGraphTypeMakerTests.cs | 29 ++++++----- .../TypeMakers/InterfaceTypeMakerTests.cs | 17 +++--- .../TypeMakers/ObjectGraphTypeMakerTests.cs | 39 +++++++------- .../TypeMakers/ScalarGraphTypeMakerTests.cs | 3 +- .../TypeMakers/TestData/ComplexInputObject.cs | 2 +- .../TestData/CustomScalarWithDirectives.cs | 2 +- .../TypeMakers/TestData/DirectiveWithArgs.cs | 3 +- .../TestData/EnumValueWithDirective.cs | 3 +- .../TestData/EnumWithDescriptions.cs | 2 +- .../TypeMakers/TestData/EnumWithDirective.cs | 3 +- .../TypeMakers/TestData/EnumWithGraphName.cs | 2 +- .../TestData/EnumWithUndeclaredValues.cs | 2 +- .../TestData/EnumWithValueOfFalseKeyword.cs | 3 +- .../TestData/EnumWithValueOfNullKeyword.cs | 3 +- .../TestData/EnumWithValueOfTrueKeyword.cs | 3 +- .../TypeMakers/TestData/ISimpleInterface.cs | 2 +- .../TypeMakers/TestData/ITestInterface1.cs | 3 +- .../TypeMakers/TestData/ITestInterface2.cs | 3 +- .../ITestInterfaceForDeclaredInterfaces.cs | 3 +- .../TypeMakers/TestData/IUnionTestDataItem.cs | 2 +- .../TypeMakers/TestData/InputTestObject.cs | 2 +- .../InputTestObjectWithDefaultFieldValues.cs | 2 +- .../TestData/InputTypeWithDirective.cs | 3 +- ...nterfaceThatInheritsDeclaredMethodField.cs | 2 +- ...erfaceThatInheritsUndeclaredMethodField.cs | 2 +- .../InterfaceWithDeclaredInterfaceField.cs | 2 +- .../TestData/InterfaceWithDirective.cs | 3 +- .../InterfaceWithUndeclaredInterfaceField.cs | 2 +- .../TestData/MultiMethodDirective.cs | 3 +- .../TestData/NullableEnumController.cs | 2 +- .../TestData/ObjectDirectiveTestItem.cs | 3 +- .../TestData/ObjectWithDeclaredMethodField.cs | 2 +- .../ObjectWithInheritedDeclaredMethodField.cs | 2 +- ...bjectWithInheritedUndeclaredMethodField.cs | 2 +- .../ObjectWithUndeclaredMethodField.cs | 2 +- .../TypeMakers/TestData/OneMarkedProperty.cs | 2 +- .../TestData/PropAuthorizeAttribute.cs | 2 +- .../TestData/RepeatableDirective.cs | 3 +- .../TypeMakers/TestData/SecuredController.cs | 2 +- .../TestData/SelfReferencingObject.cs | 2 +- .../TestData/SimplePropertyObject.cs | 2 +- .../TypeMakers/TestData/TypeCreationItem.cs | 2 +- .../TestData/TypeWithUndeclaredFields.cs | 2 +- .../TypeWithUndeclaredFieldsWithOverride.cs | 2 +- ...ypeWithUndeclaredFieldsWithOverrideNone.cs | 2 +- .../TypeMakers/TestData/UnionDataA.cs | 2 +- .../TypeMakers/TestData/UnionDataB.cs | 2 +- .../TestData/UnionProxyWithDirective.cs | 3 +- .../UnionProxyWithInvalidDirective.cs | 3 +- .../TestData/UnionTestController.cs | 2 +- .../TypeMakers/TestData/UnionTestProxy.cs | 2 +- .../TypeMakers/UnionTypeMakerTests.cs | 19 +++---- .../ActionMethodTemplateTests.cs | 34 ++++++------ .../AppliedDirectiveTemplateTests.cs | 4 +- .../TypeTemplates/ArgumentTemplateTests.cs | 17 ++++++ .../DirectiveMethodTemplateTests.cs | 6 +-- .../TypeTemplates/DirectiveTemplateTests.cs | 18 +++---- .../EnumGraphTypeTemplateTests.cs | 52 +++++++++---------- .../TypeTemplates/GraphTypeNamesTests.cs | 2 +- .../InputGraphFieldTemplateTests.cs | 12 ++--- .../MethodGraphFieldTemplateTests.cs | 10 ++-- .../ObjectGraphTypeTemplateTests.cs | 2 +- .../ParameterTestData/ParameterTestClass.cs | 2 + 87 files changed, 354 insertions(+), 296 deletions(-) rename src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/{IGraphQLRuntimeDirectiveActionDefinition.cs => IGraphQLRuntimeDirectiveDefinition.cs} (80%) rename src/unit-tests/graphql-aspnet-tests/{Configuration/Templates => Schemas/Generation/RuntimeFieldDeclarations}/MappedDirectiveTemplateTests.cs (93%) rename src/unit-tests/graphql-aspnet-tests/{Configuration/Templates => Schemas/Generation/RuntimeFieldDeclarations}/MappedMutationGroupTests.cs (98%) rename src/unit-tests/graphql-aspnet-tests/{Configuration/Templates => Schemas/Generation/RuntimeFieldDeclarations}/MappedMutationTemplateTests.cs (97%) rename src/unit-tests/graphql-aspnet-tests/{Configuration/Templates => Schemas/Generation/RuntimeFieldDeclarations}/MappedQueryGroupTests.cs (98%) rename src/unit-tests/graphql-aspnet-tests/{Configuration/Templates => Schemas/Generation/RuntimeFieldDeclarations}/MappedQueryTemplateTests.cs (97%) rename src/unit-tests/graphql-aspnet-tests/{Configuration/Templates => Schemas/Generation/RuntimeFieldDeclarations}/MappedTypeExtensionTemplateTests.cs (99%) rename src/unit-tests/graphql-aspnet-tests/{Configuration/Templates => Schemas/Generation/RuntimeFieldDeclarations}/ResolvedFieldTemplateTests.cs (98%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/DirectiveTypeMakerTests.cs (85%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/EnumGraphTypeMakerTests.cs (90%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/FieldMaker_InputFieldTests.cs (94%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/FieldMaker_StandardFieldTests.cs (91%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/GraphTypeMakerTestBase.cs (89%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/InputObjectGraphTypeMakerTests.cs (85%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/InterfaceTypeMakerTests.cs (90%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/ObjectGraphTypeMakerTests.cs (85%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/ScalarGraphTypeMakerTests.cs (98%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/ComplexInputObject.cs (87%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/CustomScalarWithDirectives.cs (94%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/DirectiveWithArgs.cs (90%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/EnumValueWithDirective.cs (86%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/EnumWithDescriptions.cs (88%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/EnumWithDirective.cs (86%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/EnumWithGraphName.cs (85%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/EnumWithUndeclaredValues.cs (87%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/EnumWithValueOfFalseKeyword.cs (85%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/EnumWithValueOfNullKeyword.cs (85%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/EnumWithValueOfTrueKeyword.cs (85%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/ISimpleInterface.cs (87%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/ITestInterface1.cs (83%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/ITestInterface2.cs (83%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/ITestInterfaceForDeclaredInterfaces.cs (85%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/IUnionTestDataItem.cs (85%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/InputTestObject.cs (94%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/InputTestObjectWithDefaultFieldValues.cs (92%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/InputTypeWithDirective.cs (86%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/InterfaceThatInheritsDeclaredMethodField.cs (87%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/InterfaceThatInheritsUndeclaredMethodField.cs (87%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/InterfaceWithDeclaredInterfaceField.cs (88%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/InterfaceWithDirective.cs (87%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/InterfaceWithUndeclaredInterfaceField.cs (86%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/MultiMethodDirective.cs (93%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/NullableEnumController.cs (90%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/ObjectDirectiveTestItem.cs (92%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/ObjectWithDeclaredMethodField.cs (87%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/ObjectWithInheritedDeclaredMethodField.cs (85%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/ObjectWithInheritedUndeclaredMethodField.cs (85%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/ObjectWithUndeclaredMethodField.cs (85%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/OneMarkedProperty.cs (87%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/PropAuthorizeAttribute.cs (86%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/RepeatableDirective.cs (91%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/SecuredController.cs (91%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/SelfReferencingObject.cs (87%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/SimplePropertyObject.cs (93%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/TypeCreationItem.cs (91%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/TypeWithUndeclaredFields.cs (93%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/TypeWithUndeclaredFieldsWithOverride.cs (94%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/TypeWithUndeclaredFieldsWithOverrideNone.cs (94%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/UnionDataA.cs (86%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/UnionDataB.cs (86%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/UnionProxyWithDirective.cs (87%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/UnionProxyWithInvalidDirective.cs (89%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/UnionTestController.cs (96%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/TestData/UnionTestProxy.cs (92%) rename src/unit-tests/graphql-aspnet-tests/{Engine => Schemas/Generation}/TypeMakers/UnionTypeMakerTests.cs (80%) diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Directives.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Directives.cs index 1a0d187fb..faca9cb93 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Directives.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Directives.cs @@ -33,8 +33,8 @@ public static partial class GraphQLRuntimeSchemaItemDefinitionExtensions /// The name of the policy to assign via this requirement. /// A comma-seperated list of roles to assign via this requirement. /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeDirectiveActionDefinition RequireAuthorization( - this IGraphQLRuntimeDirectiveActionDefinition directiveTemplate, + public static IGraphQLRuntimeDirectiveDefinition RequireAuthorization( + this IGraphQLRuntimeDirectiveDefinition directiveTemplate, string policyName = null, string roles = null) { @@ -61,7 +61,7 @@ public static IGraphQLRuntimeDirectiveActionDefinition RequireAuthorization( /// /// The directive being built. /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeDirectiveActionDefinition AllowAnonymous(this IGraphQLRuntimeDirectiveActionDefinition directiveTemplate) + public static IGraphQLRuntimeDirectiveDefinition AllowAnonymous(this IGraphQLRuntimeDirectiveDefinition directiveTemplate) { Validation.ThrowIfNull(directiveTemplate, nameof(directiveTemplate)); directiveTemplate.AddAttribute(new AllowAnonymousAttribute()); @@ -74,7 +74,7 @@ public static IGraphQLRuntimeDirectiveActionDefinition AllowAnonymous(this IGrap /// /// The directive template. /// IGraphQLDirectiveTemplate. - public static IGraphQLRuntimeDirectiveActionDefinition IsRepeatable(this IGraphQLRuntimeDirectiveActionDefinition directiveTemplate) + public static IGraphQLRuntimeDirectiveDefinition IsRepeatable(this IGraphQLRuntimeDirectiveDefinition directiveTemplate) { var repeatable = new RepeatableAttribute(); directiveTemplate.AddAttribute(repeatable); @@ -92,8 +92,8 @@ public static IGraphQLRuntimeDirectiveActionDefinition IsRepeatable(this IGraphQ /// The bitwise set of locations where this /// directive can be applied. /// IGraphQLDirectiveTemplate. - public static IGraphQLRuntimeDirectiveActionDefinition RestrictLocations( - this IGraphQLRuntimeDirectiveActionDefinition directiveTemplate, + public static IGraphQLRuntimeDirectiveDefinition RestrictLocations( + this IGraphQLRuntimeDirectiveDefinition directiveTemplate, DirectiveLocation locations) { var restrictions = new DirectiveLocationsAttribute(locations); @@ -117,7 +117,7 @@ public static IGraphQLRuntimeDirectiveActionDefinition RestrictLocations( /// The delegate to assign as the resolver. This method will be /// parsed to determine input arguments for the field on the target schema. /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeDirectiveActionDefinition AddResolver(this IGraphQLRuntimeDirectiveActionDefinition directiveTemplate, Delegate resolverMethod) + public static IGraphQLRuntimeDirectiveDefinition AddResolver(this IGraphQLRuntimeDirectiveDefinition directiveTemplate, Delegate resolverMethod) { directiveTemplate.Resolver = resolverMethod; directiveTemplate.ReturnType = null; @@ -137,7 +137,7 @@ public static IGraphQLRuntimeDirectiveActionDefinition AddResolver(this IGraphQL /// The delegate to assign as the resolver. This method will be /// parsed to determine input arguments for the directive on the target schema. /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeDirectiveActionDefinition AddResolver(this IGraphQLRuntimeDirectiveActionDefinition directiveTemplate, Delegate resolverMethod) + public static IGraphQLRuntimeDirectiveDefinition AddResolver(this IGraphQLRuntimeDirectiveDefinition directiveTemplate, Delegate resolverMethod) { directiveTemplate.Resolver = resolverMethod; directiveTemplate.ReturnType = typeof(TReturnType); @@ -150,7 +150,7 @@ public static IGraphQLRuntimeDirectiveActionDefinition AddResolver( /// The schema options where the directive will be created. /// Name of the directive (e.g. '@myDirective'). /// IGraphQLDirectiveTemplate. - public static IGraphQLRuntimeDirectiveActionDefinition MapDirective(this SchemaOptions schemaOptions, string directiveName) + public static IGraphQLRuntimeDirectiveDefinition MapDirective(this SchemaOptions schemaOptions, string directiveName) { return MapDirectiveInternal(schemaOptions, directiveName); } @@ -162,7 +162,7 @@ public static IGraphQLRuntimeDirectiveActionDefinition MapDirective(this SchemaO /// Name of the directive (e.g. '@myDirective'). /// The resolver that will be executed when the directive is invoked. /// IGraphQLDirectiveTemplate. - public static IGraphQLRuntimeDirectiveActionDefinition MapDirective(this SchemaOptions schemaOptions, string directiveName, Delegate resolverMethod) + public static IGraphQLRuntimeDirectiveDefinition MapDirective(this SchemaOptions schemaOptions, string directiveName, Delegate resolverMethod) { Validation.ThrowIfNull(resolverMethod, nameof(resolverMethod)); @@ -176,7 +176,7 @@ public static IGraphQLRuntimeDirectiveActionDefinition MapDirective(this SchemaO /// The builder representing the schema being constructed. /// Name of the directive (e.g. '@myDirective'). /// IGraphQLDirectiveTemplate. - public static IGraphQLRuntimeDirectiveActionDefinition MapDirective(this ISchemaBuilder schemaBuilder, string directiveName) + public static IGraphQLRuntimeDirectiveDefinition MapDirective(this ISchemaBuilder schemaBuilder, string directiveName) { Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); @@ -194,7 +194,7 @@ public static IGraphQLRuntimeDirectiveActionDefinition MapDirective(this ISchema /// Name of the directive (e.g. '@myDirective'). /// The resolver that will be executed when the directive is invoked. /// IGraphQLDirectiveTemplate. - public static IGraphQLRuntimeDirectiveActionDefinition MapDirective(this ISchemaBuilder schemaBuilder, string directiveName, Delegate resolverMethod) + public static IGraphQLRuntimeDirectiveDefinition MapDirective(this ISchemaBuilder schemaBuilder, string directiveName, Delegate resolverMethod) { Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); Validation.ThrowIfNull(resolverMethod, nameof(resolverMethod)); diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Internals.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Internals.cs index b436cf44a..9e8687999 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Internals.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Internals.cs @@ -59,7 +59,7 @@ private static IGraphQLRuntimeTypeExtensionDefinition MapTypeExtensionInternal( return field; } - private static IGraphQLRuntimeDirectiveActionDefinition MapDirectiveInternal(this SchemaOptions schemaOptions, string directiveName) + private static IGraphQLRuntimeDirectiveDefinition MapDirectiveInternal(this SchemaOptions schemaOptions, string directiveName) { while (directiveName != null && directiveName.StartsWith(TokenTypeNames.STRING_AT_SYMBOL)) directiveName = directiveName.Substring(1); diff --git a/src/graphql-aspnet/Configuration/SchemaArgumentBindingRules.cs b/src/graphql-aspnet/Configuration/SchemaArgumentBindingRules.cs index 71d39dc5c..3d470a2df 100644 --- a/src/graphql-aspnet/Configuration/SchemaArgumentBindingRules.cs +++ b/src/graphql-aspnet/Configuration/SchemaArgumentBindingRules.cs @@ -9,6 +9,8 @@ namespace GraphQL.AspNet.Configuration { + using System; + /// /// A declaration of the possible rules used by a schema to determine which /// arguments should be injected by a DI container and which should be part of the @@ -17,25 +19,42 @@ namespace GraphQL.AspNet.Configuration public enum SchemaArgumentBindingRules { /// - /// Undecorated arguments will be treated as being part of the schema if the declared .NET type of the - /// argument is part of the schema. If the argument type is not part of the schema, - /// the runtime will attempt to be resolved from the DI container when a query executes. + /// + /// Undecorated parameters will be treated as being part of the schema if the declared .NET type of the + /// argument is part of the schema as an appropriate graph type (e.g. SCALAR, ENUM, INPUT_OBJECT). + /// + /// Method parameters not included in the schema will attempt to be resolved from a scoped + /// when a field or directive resolver is invoked. + /// /// - ArgumentsPreferQueryResolution = 0, + /// + /// This is the default option for all schemas unless changed by the developer. + /// + ParametersPreferQueryResolution = 0, /// - /// All arguments intended to be part of the schema must be explicitly decorated using - /// [FromGraphQL]. Undecorated arguments will be treated as needing to be resolved - /// from a DI container when a query execute. Undecorated arguments WILL NOT be included as part of the schema. + /// + /// All method parameters intending to be included as arguments on the schema must be explicitly decorated using + /// [FromGraphQL]. Undecorated parameters will be treated as needing to be resolved + /// from a scoped when a field or directive resolver is invoked. + /// + /// + /// Undecorated parameters WILL NOT be included as part of the schema. + /// /// - ArgumentsRequireGraphQlDeclaration = 1, + ParametersRequireGraphQlDeclaration = 1, /// - /// All arguments intended to be resolved from the DI container during query execution must be explicitly - /// declared using [FromServices]. - /// Undecorated arguments will be treated as being resolved from a query and WILL be included - /// as part of the schema. + /// + /// All method parameters intending to be resolved from a scoped + /// must be explicitly declared using [FromServices]. Undecorated arguments will be treated as + /// being part of the schema. + /// + /// + /// Undecorated parameters WILL be included as part of the schema. This may lead to the schema being unable to be + /// generated and the server failing to start. + /// /// - ArgumentsRequireDiDeclaration = 2, + ParametersRequireDiDeclaration = 2, } } \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/SchemaDeclarationConfiguration.cs b/src/graphql-aspnet/Configuration/SchemaDeclarationConfiguration.cs index 2ef2a8225..73dd760e1 100644 --- a/src/graphql-aspnet/Configuration/SchemaDeclarationConfiguration.cs +++ b/src/graphql-aspnet/Configuration/SchemaDeclarationConfiguration.cs @@ -29,19 +29,15 @@ public class SchemaDeclarationConfiguration : ISchemaDeclarationConfiguration public SchemaDeclarationConfiguration() { this.AllowedOperations = new HashSet(); - this.ArgumentBindingRules = new HashSet(); - this.AllowedOperations.Add(GraphOperationType.Query); this.AllowedOperations.Add(GraphOperationType.Mutation); - - this.ArgumentBindingRules - .Add(Configuration.SchemaArgumentBindingRules.ArgumentsPreferQueryResolution); + this.ArgumentBindingRule = SchemaArgumentBindingRules.ParametersPreferQueryResolution; } /// /// Merges the specified configuration setttings into this instance. /// - /// The configuration. + /// The configuration values to merge into this instance. public void Merge(ISchemaDeclarationConfiguration config) { if (config == null) @@ -50,25 +46,20 @@ public void Merge(ISchemaDeclarationConfiguration config) this.DisableIntrospection = config.DisableIntrospection; this.FieldDeclarationRequirements = config.FieldDeclarationRequirements; this.GraphNamingFormatter = config.GraphNamingFormatter; + this.ArgumentBindingRule = config.ArgumentBindingRule; if (config.AllowedOperations != null) { foreach (var op in config.AllowedOperations) this.AllowedOperations.Add(op); } - - if (config.ArgumentBindingRules != null) - { - foreach (var rule in config.ArgumentBindingRules) - this.ArgumentBindingRules.Add(rule); - } } /// public bool DisableIntrospection { get; set; } /// - public HashSet ArgumentBindingRules { get; } + public SchemaArgumentBindingRules ArgumentBindingRule { get; set; } /// public TemplateDeclarationRequirements FieldDeclarationRequirements { get; set; } = TemplateDeclarationRequirements.Default; diff --git a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_RuntimeDefinitions.cs b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_RuntimeDefinitions.cs index 17ba38463..c240ba265 100644 --- a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_RuntimeDefinitions.cs +++ b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_RuntimeDefinitions.cs @@ -9,12 +9,13 @@ namespace GraphQL.AspNet.Engine { + using System; using GraphQL.AspNet.Common; using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; using GraphQL.AspNet.Schemas.Generation.TypeTemplates; /// - /// The default schema factory, capable of creating singleton instances of + /// The default schema factory, capable of creating instances of /// schemas, fully populated and ready to serve requests. /// public partial class DefaultGraphQLSchemaFactory @@ -25,14 +26,32 @@ public partial class DefaultGraphQLSchemaFactory /// The runtime defined item to add to the schema. protected virtual void AddRuntimeSchemaItemDefinition(IGraphQLRuntimeSchemaItemDefinition itemDefinition) { - if (itemDefinition is IGraphQLRuntimeResolvedFieldDefinition fieldDef) - this.AddRuntimeFieldDefinition(fieldDef); + switch (itemDefinition) + { + case IGraphQLRuntimeResolvedFieldDefinition fieldDef: + this.AddRuntimeFieldDefinition(fieldDef); + break; - // TODO: Add support for directives + case IGraphQLRuntimeDirectiveDefinition directiveDef: + this.AddRuntimeDirectiveDefinition(directiveDef); + break; + + // TODO: Add support for directives + // TODO: Add warning log entries for unsupported item defs. + } + } + + /// + /// Adds a new directive to the schema based on the runtime definition created during program startup. + /// + /// The directive definition to add. + protected virtual void AddRuntimeDirectiveDefinition(IGraphQLRuntimeDirectiveDefinition directiveDef) + { + throw new NotImplementedException(); } /// - /// Adds the runtime defined field into the schema. + /// Adds a new field to the schema based on the runtime definition created during program startup. /// /// The field definition to add. protected virtual void AddRuntimeFieldDefinition(IGraphQLRuntimeResolvedFieldDefinition fieldDefinition) diff --git a/src/graphql-aspnet/Execution/RulesEngine/RuleSets/DocumentValidation/QueryOperationSteps/Rule_5_8_VariableDeclarationChecks.cs b/src/graphql-aspnet/Execution/RulesEngine/RuleSets/DocumentValidation/QueryOperationSteps/Rule_5_8_VariableDeclarationChecks.cs index 919e54591..4a378523c 100644 --- a/src/graphql-aspnet/Execution/RulesEngine/RuleSets/DocumentValidation/QueryOperationSteps/Rule_5_8_VariableDeclarationChecks.cs +++ b/src/graphql-aspnet/Execution/RulesEngine/RuleSets/DocumentValidation/QueryOperationSteps/Rule_5_8_VariableDeclarationChecks.cs @@ -317,7 +317,6 @@ private bool Check585_IsVariableUsageAllowed( if (iof.Field == null) return true; - // TODO: Add support for default input values on fields (github issue #70) hasLocationDefaultValue = !iof.Field.IsRequired; originalLocationType = iof.Field.TypeExpression; argName = iof.Name; diff --git a/src/graphql-aspnet/Interfaces/Configuration/ISchemaDeclarationConfiguration.cs b/src/graphql-aspnet/Interfaces/Configuration/ISchemaDeclarationConfiguration.cs index f3db6a802..44919d849 100644 --- a/src/graphql-aspnet/Interfaces/Configuration/ISchemaDeclarationConfiguration.cs +++ b/src/graphql-aspnet/Interfaces/Configuration/ISchemaDeclarationConfiguration.cs @@ -42,12 +42,10 @@ public interface ISchemaDeclarationConfiguration TemplateDeclarationRequirements FieldDeclarationRequirements { get; } /// - /// Gets the defined rules this schema should use when inspecting implicit or late bound - /// field arguments before the schema is placed online. These rules do not effect explicitly - /// declared arguments that use [FromGraphQL] or [FromServices]. + /// Gets the tie-breaker selection rule this schema should use when determining how to handle unattributed method parameters. /// - /// The schema item binding rules to obey. - HashSet ArgumentBindingRules { get; } + /// The tie breaker rule to use when evaluating method parameters as potential field arguments. + SchemaArgumentBindingRules ArgumentBindingRule { get; } /// /// Gets an object used to format the declared names in your C# code as various items in the type system diff --git a/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeDirectiveActionDefinition.cs b/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeDirectiveDefinition.cs similarity index 80% rename from src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeDirectiveActionDefinition.cs rename to src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeDirectiveDefinition.cs index 0308327f0..5b6439e87 100644 --- a/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeDirectiveActionDefinition.cs +++ b/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeDirectiveDefinition.cs @@ -13,7 +13,7 @@ namespace GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions /// An intermediate template that utilizies a key/value pair system to build up a set of component parts /// that the templating engine will use to generate a full fledged field in a schema. /// - public interface IGraphQLRuntimeDirectiveActionDefinition : IGraphQLRuntimeSchemaItemDefinition, IGraphQLResolvableSchemaItemDefinition + public interface IGraphQLRuntimeDirectiveDefinition : IGraphQLRuntimeSchemaItemDefinition, IGraphQLResolvableSchemaItemDefinition { } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphArgumentTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphArgumentTemplate.cs index 7ab533e55..22e4c53f7 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphArgumentTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphArgumentTemplate.cs @@ -65,7 +65,7 @@ public virtual void Parse() if (_argDeclaration != null) { name = _argDeclaration?.ArgumentName?.Trim(); - this.ArgumentModifiers = this.ArgumentModifiers | GraphArgumentModifiers.ExplicitSchemaItem; + this.ArgumentModifiers = GraphArgumentModifiers.ExplicitSchemaItem; } if (string.IsNullOrWhiteSpace(name)) @@ -75,7 +75,7 @@ public virtual void Parse() // to be consumed from a DI container var fromServicesAttrib = this.Parameter.SingleAttributeOfTypeOrDefault(); if (fromServicesAttrib != null) - this.ArgumentModifiers = this.ArgumentModifiers | GraphArgumentModifiers.ExplicitInjected; + this.ArgumentModifiers = GraphArgumentModifiers.ExplicitInjected; name = name.Replace(Constants.Routing.PARAMETER_META_NAME, this.Parameter.Name); this.Route = new GraphArgumentFieldPath(this.Parent.Route, name); @@ -129,11 +129,11 @@ public virtual void Parse() // since the source data will be an OBJECT type (not INPUT_OBJECT) there is no way the user could have supplied it if (this.IsSourceDataArgument()) { - this.ArgumentModifiers = this.ArgumentModifiers | GraphArgumentModifiers.ParentFieldResult; + this.ArgumentModifiers = GraphArgumentModifiers.ParentFieldResult; } else if (this.IsCancellationTokenArgument()) { - this.ArgumentModifiers = this.ArgumentModifiers | GraphArgumentModifiers.CancellationToken; + this.ArgumentModifiers = GraphArgumentModifiers.CancellationToken; } } @@ -147,7 +147,7 @@ protected virtual bool IsSourceDataArgument() if (this.Parent.Arguments.Any(x => x.ArgumentModifiers.HasFlag(GraphArgumentModifiers.ParentFieldResult))) return false; - if (this.ArgumentModifiers.IsInjected()) + if (this.ArgumentModifiers != GraphArgumentModifiers.None) return false; if (this.ObjectType == this.Parent.SourceObjectType) diff --git a/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeDirectiveActionDefinition.cs b/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeDirectiveActionDefinition.cs index 3729fd0a6..ffee7a743 100644 --- a/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeDirectiveActionDefinition.cs +++ b/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeDirectiveActionDefinition.cs @@ -16,11 +16,11 @@ namespace GraphQL.AspNet.Schemas.RuntimeSchemaItemDefinitions using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; /// - /// An internal implementation of the + /// An internal implementation of the /// used to generate new graphql directives via a minimal api style of coding. /// [DebuggerDisplay("{Template}")] - internal class RuntimeDirectiveActionDefinition : BaseRuntimeControllerActionDefinition, IGraphQLRuntimeDirectiveActionDefinition + internal class RuntimeDirectiveActionDefinition : BaseRuntimeControllerActionDefinition, IGraphQLRuntimeDirectiveDefinition { /// /// Initializes a new instance of the class. diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTests.cs b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTests.cs index 9da1faa58..c1c389b43 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTests.cs @@ -7,15 +7,6 @@ // License: MIT // ************************************************************* -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - namespace GraphQL.AspNet.Tests.Engine { using System; diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/Parsing/SourceTextLexerExtensionsTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/Parsing/SourceTextLexerExtensionsTests.cs index 46f65f07f..b8a9503d7 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/Parsing/SourceTextLexerExtensionsTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/Parsing/SourceTextLexerExtensionsTests.cs @@ -8,7 +8,7 @@ // ************************************************************* // ReSharper disable All -namespace GraphQL.AspNet.Tests.Parsing +namespace GraphQL.AspNet.Tests.Execution.Parsing { using System; using System.Linq; @@ -127,7 +127,7 @@ public void SourceText_NextString_ValidStrings( // Note: expectedResult is ignored if null. if (expectedResult != null) - Assert.AreEqual(expectedResult, source.RetrieveText(result).ToString()); + Assert.AreEqual(expectedResult, source.RetrieveText(result).ToString()); } [TestCase("", 0, -1, -1, -1)] // nothing diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedDirectiveTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedDirectiveTemplateTests.cs similarity index 93% rename from src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedDirectiveTemplateTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedDirectiveTemplateTests.cs index 52d2f41c0..5d22873a4 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedDirectiveTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedDirectiveTemplateTests.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Configuration.Templates +namespace GraphQL.AspNet.Tests.Schemas.Generation.RuntimeFieldDeclarations { using System.Linq; using GraphQL.AspNet.Attributes; @@ -31,7 +31,7 @@ public void MapDirective_ByOptions_AddsDirectiveToOptions() var options = new SchemaOptions(services); var directive = options.MapDirective("@myDirective"); - Assert.IsInstanceOf(typeof(IGraphQLRuntimeDirectiveActionDefinition), directive); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeDirectiveDefinition), directive); Assert.AreEqual(1, options.RuntimeTemplates.Count()); Assert.IsNotNull(options.RuntimeTemplates.FirstOrDefault(x => x == directive)); @@ -50,7 +50,7 @@ public void MapDirective_ByBuilder_AddsDirectiveToOptions() builderMock.Setup(x => x.Options).Returns(options); var directive = builderMock.Object.MapDirective("@myDirective"); - Assert.IsInstanceOf(typeof(IGraphQLRuntimeDirectiveActionDefinition), directive); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeDirectiveDefinition), directive); Assert.AreEqual(1, options.RuntimeTemplates.Count()); Assert.IsNotNull(options.RuntimeTemplates.FirstOrDefault(x => x == directive)); @@ -63,7 +63,7 @@ public void MapDirective_ByOptions_WithResolver_AddsDirectiveToOptions() var options = new SchemaOptions(services); var directive = options.MapDirective("@myDirective", (string a) => 1); - Assert.IsInstanceOf(typeof(IGraphQLRuntimeDirectiveActionDefinition), directive); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeDirectiveDefinition), directive); Assert.AreEqual(1, options.RuntimeTemplates.Count()); Assert.IsNotNull(options.RuntimeTemplates.FirstOrDefault(x => x == directive)); @@ -82,7 +82,7 @@ public void MapDirective_ByBuilder_WithResolver_AddsDirectiveToOptions() builderMock.Setup(x => x.Options).Returns(options); var directive = builderMock.Object.MapDirective("@myDirective", (string a) => 1); - Assert.IsInstanceOf(typeof(IGraphQLRuntimeDirectiveActionDefinition), directive); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeDirectiveDefinition), directive); Assert.AreEqual(1, options.RuntimeTemplates.Count()); Assert.IsNotNull(options.RuntimeTemplates.FirstOrDefault(x => x == directive)); diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedMutationGroupTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedMutationGroupTests.cs similarity index 98% rename from src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedMutationGroupTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedMutationGroupTests.cs index 20f3ac138..4b9e247df 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedMutationGroupTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedMutationGroupTests.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Configuration.Templates +namespace GraphQL.AspNet.Tests.Schemas.Generation.RuntimeFieldDeclarations { using System.Linq; using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedMutationTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedMutationTemplateTests.cs similarity index 97% rename from src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedMutationTemplateTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedMutationTemplateTests.cs index 1557d28fb..ef917d347 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedMutationTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedMutationTemplateTests.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Configuration.Templates +namespace GraphQL.AspNet.Tests.Schemas.Generation.RuntimeFieldDeclarations { using System.Linq; using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedQueryGroupTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedQueryGroupTests.cs similarity index 98% rename from src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedQueryGroupTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedQueryGroupTests.cs index cffa8095f..b4d123c8a 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedQueryGroupTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedQueryGroupTests.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Configuration.Templates +namespace GraphQL.AspNet.Tests.Schemas.Generation.RuntimeFieldDeclarations { using System.Linq; using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedQueryTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedQueryTemplateTests.cs similarity index 97% rename from src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedQueryTemplateTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedQueryTemplateTests.cs index 139afdac0..ad8e4ba6a 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedQueryTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedQueryTemplateTests.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Configuration.Templates +namespace GraphQL.AspNet.Tests.Schemas.Generation.RuntimeFieldDeclarations { using System.Linq; using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedTypeExtensionTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedTypeExtensionTemplateTests.cs similarity index 99% rename from src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedTypeExtensionTemplateTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedTypeExtensionTemplateTests.cs index 826ac49df..3c490ceef 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/MappedTypeExtensionTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedTypeExtensionTemplateTests.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Configuration.Templates +namespace GraphQL.AspNet.Tests.Schemas.Generation.RuntimeFieldDeclarations { using System.Linq; using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/ResolvedFieldTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/ResolvedFieldTemplateTests.cs similarity index 98% rename from src/unit-tests/graphql-aspnet-tests/Configuration/Templates/ResolvedFieldTemplateTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/ResolvedFieldTemplateTests.cs index 1e514e15e..874775a3f 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/Templates/ResolvedFieldTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/ResolvedFieldTemplateTests.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Configuration.Templates +namespace GraphQL.AspNet.Tests.Schemas.Generation.RuntimeFieldDeclarations { using System.Linq; using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/DirectiveTypeMakerTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/DirectiveTypeMakerTests.cs similarity index 85% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/DirectiveTypeMakerTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/DirectiveTypeMakerTests.cs index 5a93802ef..4f5782c52 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/DirectiveTypeMakerTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/DirectiveTypeMakerTests.cs @@ -6,7 +6,8 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers { using System.Linq; using GraphQL.AspNet.Engine; @@ -18,8 +19,8 @@ namespace GraphQL.AspNet.Tests.Engine.TypeMakers using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.CommonHelpers; - using GraphQL.AspNet.Tests.Engine.TypeMakers.TestData; using GraphQL.AspNet.Tests.Framework; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData; using NUnit.Framework; [TestFixture] @@ -41,14 +42,14 @@ public void Directive_BasicPropertyCheck() Assert.AreEqual("multiMethod", directive.Name); Assert.AreEqual("A Multi Method Directive", directive.Description); Assert.AreEqual(TypeKind.DIRECTIVE, directive.Kind); - Assert.IsTrue((bool)directive.Publish); + Assert.IsTrue(directive.Publish); Assert.AreEqual(DirectiveLocation.FIELD | DirectiveLocation.SCALAR, directive.Locations); Assert.AreEqual(typeof(GraphDirectiveActionResolver), directive.Resolver.GetType()); Assert.AreEqual(2, directive.Arguments.Count); - var arg0 = Enumerable.FirstOrDefault(directive.Arguments); - var arg1 = Enumerable.Skip(directive.Arguments, 1).FirstOrDefault(); + var arg0 = directive.Arguments.FirstOrDefault(); + var arg1 = directive.Arguments.Skip(1).FirstOrDefault(); Assert.IsNotNull(arg0); Assert.AreEqual("firstArg", arg0.Name); @@ -72,16 +73,16 @@ public void Directive_RepeatableAttributeIsSetWhenPresent() var directive = typeMaker.CreateGraphType(template).GraphType as IDirective; - Assert.IsTrue((bool)directive.IsRepeatable); + Assert.IsTrue(directive.IsRepeatable); Assert.AreEqual("repeatable", directive.Name); Assert.AreEqual(TypeKind.DIRECTIVE, directive.Kind); - Assert.IsTrue((bool)directive.Publish); + Assert.IsTrue(directive.Publish); Assert.AreEqual(DirectiveLocation.SCALAR, directive.Locations); Assert.AreEqual(2, directive.Arguments.Count); - var arg0 = Enumerable.FirstOrDefault(directive.Arguments); - var arg1 = Enumerable.Skip(directive.Arguments, 1).FirstOrDefault(); + var arg0 = directive.Arguments.FirstOrDefault(); + var arg1 = directive.Arguments.Skip(1).FirstOrDefault(); Assert.IsNotNull(arg0); Assert.AreEqual("firstArg", arg0.Name); diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/EnumGraphTypeMakerTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/EnumGraphTypeMakerTests.cs similarity index 90% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/EnumGraphTypeMakerTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/EnumGraphTypeMakerTests.cs index 0cabe13cb..83027e83e 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/EnumGraphTypeMakerTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/EnumGraphTypeMakerTests.cs @@ -6,7 +6,8 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers { using System; using System.Linq; @@ -18,8 +19,8 @@ namespace GraphQL.AspNet.Tests.Engine.TypeMakers using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Schemas.Generation.TypeMakers; using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Tests.Engine.TypeMakers.TestData; using GraphQL.AspNet.Tests.Framework; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData; using NUnit.Framework; [TestFixture] @@ -40,8 +41,8 @@ public void Parse_EnumWithUndeclaredValues_WhenConfigRequiresDeclaration_DoesntI var graphType = maker.CreateGraphType(template).GraphType as IEnumGraphType; Assert.AreEqual(2, graphType.Values.Count); - Assert.IsTrue((bool)graphType.Values.ContainsKey("DECLAREDVALUE1")); - Assert.IsTrue((bool)graphType.Values.ContainsKey("VALUE_AWESOME")); + Assert.IsTrue(graphType.Values.ContainsKey("DECLAREDVALUE1")); + Assert.IsTrue(graphType.Values.ContainsKey("VALUE_AWESOME")); } [Test] @@ -59,12 +60,12 @@ public void Parse_EnumWithUndeclaredValues_WhenConfigDoesNotRequireDeclaration_D var graphType = maker.CreateGraphType(template).GraphType as IEnumGraphType; Assert.AreEqual(3, graphType.Values.Count); - Assert.IsTrue((bool)graphType.Values.ContainsKey("DECLAREDVALUE1")); + Assert.IsTrue(graphType.Values.ContainsKey("DECLAREDVALUE1")); - Assert.IsTrue((bool)graphType.Values.ContainsKey("VALUE_AWESOME")); - Assert.IsFalse((bool)graphType.Values.ContainsKey("DECLAREDVALUE2")); + Assert.IsTrue(graphType.Values.ContainsKey("VALUE_AWESOME")); + Assert.IsFalse(graphType.Values.ContainsKey("DECLAREDVALUE2")); - Assert.IsTrue((bool)graphType.Values.ContainsKey("UNDECLAREDVALUE1")); + Assert.IsTrue(graphType.Values.ContainsKey("UNDECLAREDVALUE1")); } [Test] @@ -115,7 +116,7 @@ public void AppliedDirectives_TransferFromTemplate() Assert.AreEqual(graphType, graphType.AppliedDirectives.Parent); - var appliedDirective = Enumerable.Single(graphType.AppliedDirectives); + var appliedDirective = graphType.AppliedDirectives.Single(); Assert.IsNotNull(appliedDirective); Assert.AreEqual(typeof(DirectiveWithArgs), appliedDirective.DirectiveType); CollectionAssert.AreEqual(new object[] { 23, "enum arg" }, appliedDirective.ArgumentValues); @@ -139,7 +140,7 @@ public void DirectivesAreTransferedToGraphType() Assert.AreEqual(0, value1.AppliedDirectives.Count); Assert.AreEqual(1, value2.AppliedDirectives.Count); - var appliedDirective = Enumerable.FirstOrDefault(value2.AppliedDirectives); + var appliedDirective = value2.AppliedDirectives.FirstOrDefault(); Assert.IsNotNull(appliedDirective); Assert.AreEqual(value2, value2.AppliedDirectives.Parent); Assert.AreEqual(typeof(DirectiveWithArgs), appliedDirective.DirectiveType); diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/FieldMaker_InputFieldTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/FieldMaker_InputFieldTests.cs similarity index 94% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/FieldMaker_InputFieldTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/FieldMaker_InputFieldTests.cs index f733d8d02..f0e13757a 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/FieldMaker_InputFieldTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/FieldMaker_InputFieldTests.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers { using System.Linq; using GraphQL.AspNet.Schemas; @@ -15,8 +15,8 @@ namespace GraphQL.AspNet.Tests.Engine.TypeMakers using GraphQL.AspNet.Schemas.Generation.TypeMakers; using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.CommonHelpers; - using GraphQL.AspNet.Tests.Engine.TypeMakers.TestData; using GraphQL.AspNet.Tests.Framework; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData; using NUnit.Framework; public class FieldMaker_InputFieldTests : GraphTypeMakerTestBase @@ -37,7 +37,7 @@ public void Parse_NotRequiredValueTypePropertyCheck() var graphField = new GraphFieldMaker(server.Schema, factory).CreateField(fieldTemplate).Field; Assert.AreEqual("notRequiredValueTypeField", graphField.Name); - Assert.IsFalse((bool)graphField.IsRequired); + Assert.IsFalse(graphField.IsRequired); // even though its not required, its still "Int!" because its a // non-nullable value type @@ -47,7 +47,7 @@ public void Parse_NotRequiredValueTypePropertyCheck() Assert.AreEqual(typeof(int), graphField.DeclaredReturnType); Assert.AreEqual(1, graphField.AppliedDirectives.Count); - Assert.AreEqual("DirectiveForNotRequiredValueTypeField", Enumerable.First(graphField.AppliedDirectives).DirectiveName); + Assert.AreEqual("DirectiveForNotRequiredValueTypeField", graphField.AppliedDirectives.First().DirectiveName); } [Test] @@ -66,7 +66,7 @@ public void Parse_RequiredValueTypePropertyCheck() var graphField = new GraphFieldMaker(server.Schema, factory).CreateField(fieldTemplate).Field; Assert.AreEqual("requiredValueTypeField", graphField.Name); - Assert.IsTrue((bool)graphField.IsRequired); + Assert.IsTrue(graphField.IsRequired); Assert.AreEqual("Int!", graphField.TypeExpression.ToString()); Assert.AreEqual("[type]/Input_InputTestObject/RequiredValueTypeField", graphField.Route.ToString()); @@ -92,7 +92,7 @@ public void Parse_NotRequiredReferenceTypePropertyCheck() var graphField = new GraphFieldMaker(server.Schema, factory).CreateField(fieldTemplate).Field; Assert.AreEqual("notRequiredReferenceTypeField", graphField.Name); - Assert.IsFalse((bool)graphField.IsRequired); + Assert.IsFalse(graphField.IsRequired); // teh field is not required and the type is a reference type (which is nullable) // meaning the type expression should also be "nullable" @@ -122,7 +122,7 @@ public void Parse_RequiredReferenceTypePropertyCheck() Assert.AreEqual("requiredReferenceTypeField", graphField.Name); // a nullable type expression can never be "required" - Assert.IsFalse((bool)graphField.IsRequired); + Assert.IsFalse(graphField.IsRequired); // because its marked as required, even though its a reference type (which is nullable) // the type expression is automatically hoisted to be "non-nullable" @@ -149,7 +149,7 @@ public void Parse_RequiredNonNullableReferenceTypePropertyCheck() var graphField = new GraphFieldMaker(server.Schema, factory).CreateField(fieldTemplate).Field; Assert.AreEqual("requiredReferenceExplicitNonNullTypeField", graphField.Name); - Assert.IsTrue((bool)graphField.IsRequired); + Assert.IsTrue(graphField.IsRequired); // because its marked as required, even though its a reference type (which is nullable) // the type expression is automatically hoisted to be "non-nullable" @@ -177,7 +177,7 @@ public void Parse_RequiredGraphIdPropertyCheck() var graphField = new GraphFieldMaker(server.Schema, factory).CreateField(fieldTemplate).Field; Assert.AreEqual("graphIdRequired", graphField.Name); - Assert.IsTrue((bool)graphField.IsRequired); + Assert.IsTrue(graphField.IsRequired); // scalar is required by default Assert.AreEqual("ID!", graphField.TypeExpression.ToString()); @@ -204,7 +204,7 @@ public void Parse_NotRequiredGraphIdPropertyCheck() var graphField = new GraphFieldMaker(server.Schema, factory).CreateField(fieldTemplate).Field; Assert.AreEqual("graphIdNotRequired", graphField.Name); - Assert.IsFalse((bool)graphField.IsRequired); + Assert.IsFalse(graphField.IsRequired); Assert.AreEqual("ID!", graphField.TypeExpression.ToString()); Assert.AreEqual("[type]/Input_InputTestObject/GraphIdNotRequired", graphField.Route.ToString()); @@ -230,7 +230,7 @@ public void Parse_NotRequiredNullableGraphIdPropertyCheck() var graphField = new GraphFieldMaker(server.Schema, factory).CreateField(fieldTemplate).Field; Assert.AreEqual("graphIdNullable", graphField.Name); - Assert.IsFalse((bool)graphField.IsRequired); + Assert.IsFalse(graphField.IsRequired); Assert.AreEqual("ID", graphField.TypeExpression.ToString()); Assert.AreEqual("[type]/Input_InputTestObject/GraphIdNullable", graphField.Route.ToString()); diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/FieldMaker_StandardFieldTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/FieldMaker_StandardFieldTests.cs similarity index 91% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/FieldMaker_StandardFieldTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/FieldMaker_StandardFieldTests.cs index 4740c5528..6fbf46e09 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/FieldMaker_StandardFieldTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/FieldMaker_StandardFieldTests.cs @@ -6,7 +6,8 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers { using System.Linq; using GraphQL.AspNet.Interfaces.Internal; @@ -18,8 +19,8 @@ namespace GraphQL.AspNet.Tests.Engine.TypeMakers using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Security; using GraphQL.AspNet.Tests.CommonHelpers; - using GraphQL.AspNet.Tests.Engine.TypeMakers.TestData; using GraphQL.AspNet.Tests.Framework; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData; using Moq; using NUnit.Framework; @@ -66,9 +67,9 @@ public void Parse_PolicyOnController_IsInheritedByField() var factory = server.CreateMakerFactory(); var graphField = new GraphFieldMaker(server.Schema, factory).CreateField(actionMethod).Field; - Assert.AreEqual(1, Enumerable.Count(graphField.SecurityGroups)); + Assert.AreEqual(1, graphField.SecurityGroups.Count()); - var group = Enumerable.First(graphField.SecurityGroups); + var group = graphField.SecurityGroups.First(); Assert.AreEqual(template.SecurityPolicies.First(), group.First()); } @@ -89,11 +90,11 @@ public void Parse_PolicyOnController_AndOnMethod_IsInheritedByField_InCorrectOrd var graphField = new GraphFieldMaker(server.Schema, factory).CreateField(actionMethod).Field; - Assert.AreEqual(2, Enumerable.Count(graphField.SecurityGroups)); + Assert.AreEqual(2, graphField.SecurityGroups.Count()); // ensure policy order of controller -> method - var controllerTemplateGroup = Enumerable.First(graphField.SecurityGroups); - var fieldTemplateGroup = Enumerable.Skip(graphField.SecurityGroups, 1).First(); + var controllerTemplateGroup = graphField.SecurityGroups.First(); + var fieldTemplateGroup = graphField.SecurityGroups.Skip(1).First(); Assert.AreEqual(template.SecurityPolicies.First(), controllerTemplateGroup.First()); Assert.AreEqual(actionMethod.SecurityPolicies.First(), fieldTemplateGroup.First()); } @@ -119,7 +120,7 @@ public void Parse_MethodWithNullableEnum_ParsesCorrectly() var graphField = new GraphFieldMaker(server.Schema, factory).CreateField(field).Field; Assert.IsNotNull(graphField); - var graphArg = Enumerable.FirstOrDefault(graphField.Arguments); + var graphArg = graphField.Arguments.FirstOrDefault(); Assert.IsNotNull(graphArg); Assert.IsEmpty(graphArg.TypeExpression.Wrappers); } @@ -192,7 +193,7 @@ public void PropertyGraphField_DirectivesAreAppliedToCreatedField() Assert.AreEqual(1, field.AppliedDirectives.Count); Assert.AreEqual(field, field.AppliedDirectives.Parent); - var appliedDirective = Enumerable.FirstOrDefault(field.AppliedDirectives); + var appliedDirective = field.AppliedDirectives.FirstOrDefault(); Assert.AreEqual(typeof(DirectiveWithArgs), appliedDirective.DirectiveType); CollectionAssert.AreEqual(new object[] { 13, "prop field arg" }, appliedDirective.ArgumentValues); } @@ -218,7 +219,7 @@ public void MethodGraphField_DirectivesAreAppliedToCreatedField() Assert.AreEqual(1, field.AppliedDirectives.Count); Assert.AreEqual(field, field.AppliedDirectives.Parent); - var appliedDirective = Enumerable.FirstOrDefault(field.AppliedDirectives); + var appliedDirective = field.AppliedDirectives.FirstOrDefault(); Assert.AreEqual(typeof(DirectiveWithArgs), appliedDirective.DirectiveType); CollectionAssert.AreEqual(new object[] { 14, "method field arg" }, appliedDirective.ArgumentValues); } @@ -248,7 +249,7 @@ public void Arguments_DirectivesAreApplied() Assert.AreEqual(1, arg.AppliedDirectives.Count); Assert.AreEqual(arg, arg.AppliedDirectives.Parent); - var appliedDirective = Enumerable.FirstOrDefault(field.Arguments["arg1"].AppliedDirectives); + var appliedDirective = field.Arguments["arg1"].AppliedDirectives.FirstOrDefault(); Assert.AreEqual(typeof(DirectiveWithArgs), appliedDirective.DirectiveType); CollectionAssert.AreEqual(new object[] { 15, "arg arg" }, appliedDirective.ArgumentValues); diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/GraphTypeMakerTestBase.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/GraphTypeMakerTestBase.cs similarity index 89% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/GraphTypeMakerTestBase.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/GraphTypeMakerTestBase.cs index 3aec6ed20..5dca1481d 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/GraphTypeMakerTestBase.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/GraphTypeMakerTestBase.cs @@ -7,20 +7,16 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers { using System; using GraphQL.AspNet.Configuration; - using GraphQL.AspNet.Engine; - using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Interfaces.Internal; - using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Tests.Framework; - using GraphQL.AspNet.Schemas.Generation; - using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Schemas.Generation.TypeMakers; - using Microsoft.AspNetCore.Hosting.Server; + using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Tests.CommonHelpers; + using GraphQL.AspNet.Tests.Framework; public abstract class GraphTypeMakerTestBase { diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/InputObjectGraphTypeMakerTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/InputObjectGraphTypeMakerTests.cs similarity index 85% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/InputObjectGraphTypeMakerTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/InputObjectGraphTypeMakerTests.cs index f258a5004..1872a2d7c 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/InputObjectGraphTypeMakerTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/InputObjectGraphTypeMakerTests.cs @@ -6,7 +6,8 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers { using System.Linq; using GraphQL.AspNet.Configuration; @@ -15,8 +16,8 @@ namespace GraphQL.AspNet.Tests.Engine.TypeMakers using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Tests.Common.CommonHelpers; - using GraphQL.AspNet.Tests.Engine.TypeMakers.TestData; using GraphQL.AspNet.Tests.Framework; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData; using NUnit.Framework; [TestFixture] @@ -39,9 +40,9 @@ public void Parse_FieldAndDependencies_SetCorrectly() Assert.IsNotNull(field); // string, OneMarkedProperty - Assert.AreEqual(2, Enumerable.Count(typeResult.DependentTypes)); - Assert.IsTrue(Enumerable.Any(typeResult.DependentTypes, x => x.Type == typeof(OneMarkedProperty))); - Assert.IsTrue(Enumerable.Any(typeResult.DependentTypes, x => x.Type == typeof(string))); + Assert.AreEqual(2, typeResult.DependentTypes.Count()); + Assert.IsTrue(typeResult.DependentTypes.Any(x => x.Type == typeof(OneMarkedProperty))); + Assert.IsTrue(typeResult.DependentTypes.Any(x => x.Type == typeof(string))); } [Test] @@ -137,8 +138,8 @@ public void InputObject_CreateGraphType_WhenPropertyDelcarationIsRequired_DoesNo var inputType = result.GraphType as IInputObjectGraphType; Assert.IsNotNull(inputType); - Assert.IsTrue(Enumerable.Any(inputType.Fields, x => x.Name == nameof(TypeWithUndeclaredFields.DeclaredProperty))); - Assert.IsFalse(Enumerable.Any(inputType.Fields, x => x.Name == nameof(TypeWithUndeclaredFields.UndeclaredProperty))); + Assert.IsTrue(inputType.Fields.Any(x => x.Name == nameof(TypeWithUndeclaredFields.DeclaredProperty))); + Assert.IsFalse(inputType.Fields.Any(x => x.Name == nameof(TypeWithUndeclaredFields.UndeclaredProperty))); } [Test] @@ -148,8 +149,8 @@ public void CreateGraphType_WhenPropertyDelcarationIsNotRequired_DoesIncludeUnde var inputType = result.GraphType as IInputObjectGraphType; Assert.IsNotNull(inputType); - Assert.IsTrue(Enumerable.Any(inputType.Fields, x => x.Name == nameof(TypeWithUndeclaredFields.DeclaredProperty))); - Assert.IsTrue(Enumerable.Any(inputType.Fields, x => x.Name == nameof(TypeWithUndeclaredFields.UndeclaredProperty))); + Assert.IsTrue(inputType.Fields.Any(x => x.Name == nameof(TypeWithUndeclaredFields.DeclaredProperty))); + Assert.IsTrue(inputType.Fields.Any(x => x.Name == nameof(TypeWithUndeclaredFields.UndeclaredProperty))); } [Test] @@ -160,8 +161,8 @@ public void CreateGraphType_WhenPropertyDelcarationIsRequired_ButWithGraphTypeOv var objectGraphType = result.GraphType as IInputObjectGraphType; Assert.IsNotNull(objectGraphType); - Assert.IsTrue(Enumerable.Any(objectGraphType.Fields, x => x.Name == nameof(TypeWithUndeclaredFieldsWithOverride.DeclaredProperty))); - Assert.IsFalse(Enumerable.Any(objectGraphType.Fields, x => x.Name == nameof(TypeWithUndeclaredFieldsWithOverride.UndeclaredProperty))); + Assert.IsTrue(objectGraphType.Fields.Any(x => x.Name == nameof(TypeWithUndeclaredFieldsWithOverride.DeclaredProperty))); + Assert.IsFalse(objectGraphType.Fields.Any(x => x.Name == nameof(TypeWithUndeclaredFieldsWithOverride.UndeclaredProperty))); } [Test] @@ -172,8 +173,8 @@ public void InputObject_CreateGraphType_WhenPropertyDelcarationIsNotRequired_But var inputType = result.GraphType as IInputObjectGraphType; Assert.IsNotNull(inputType); - Assert.IsTrue(Enumerable.Any(inputType.Fields, x => x.Name == nameof(TypeWithUndeclaredFieldsWithOverrideNone.DeclaredProperty))); - Assert.IsTrue(Enumerable.Any(inputType.Fields, x => x.Name == nameof(TypeWithUndeclaredFieldsWithOverrideNone.UndeclaredProperty))); + Assert.IsTrue(inputType.Fields.Any(x => x.Name == nameof(TypeWithUndeclaredFieldsWithOverrideNone.DeclaredProperty))); + Assert.IsTrue(inputType.Fields.Any(x => x.Name == nameof(TypeWithUndeclaredFieldsWithOverrideNone.UndeclaredProperty))); } [Test] @@ -203,7 +204,7 @@ public void InputObject_CreateGraphType_DirectivesAreApplied() Assert.AreEqual(1, inputType.AppliedDirectives.Count); Assert.AreEqual(inputType, inputType.AppliedDirectives.Parent); - var appliedDirective = Enumerable.FirstOrDefault(inputType.AppliedDirectives); + var appliedDirective = inputType.AppliedDirectives.FirstOrDefault(); Assert.IsNotNull(appliedDirective); Assert.AreEqual(typeof(DirectiveWithArgs), appliedDirective.DirectiveType); CollectionAssert.AreEqual(new object[] { 44, "input arg" }, appliedDirective.ArgumentValues); diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/InterfaceTypeMakerTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/InterfaceTypeMakerTests.cs similarity index 90% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/InterfaceTypeMakerTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/InterfaceTypeMakerTests.cs index ba85da5ec..1d3b9f528 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/InterfaceTypeMakerTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/InterfaceTypeMakerTests.cs @@ -15,7 +15,8 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers { using System.Linq; using GraphQL.AspNet.Configuration; @@ -23,8 +24,8 @@ namespace GraphQL.AspNet.Tests.Engine.TypeMakers using GraphQL.AspNet.Schemas.Generation.TypeMakers; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Tests.CommonHelpers; - using GraphQL.AspNet.Tests.Engine.TypeMakers.TestData; using GraphQL.AspNet.Tests.Framework; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData; using NUnit.Framework; [TestFixture] @@ -47,7 +48,7 @@ public void CreateGraphType_PropertyCheck() Assert.AreEqual(TypeKind.INTERFACE, graphType.Kind); // Property1, Property2, __typename - Assert.AreEqual(3, Enumerable.Count(graphType.Fields)); + Assert.AreEqual(3, graphType.Fields.Count()); } [Test] @@ -60,7 +61,7 @@ public void CreateGraphType_DirectivesAreApplied() Assert.AreEqual(1, interfaceType.AppliedDirectives.Count); Assert.AreEqual(interfaceType, interfaceType.AppliedDirectives.Parent); - var appliedDirective = Enumerable.FirstOrDefault(interfaceType.AppliedDirectives); + var appliedDirective = interfaceType.AppliedDirectives.FirstOrDefault(); Assert.IsNotNull(appliedDirective); Assert.AreEqual(typeof(DirectiveWithArgs), appliedDirective.DirectiveType); CollectionAssert.AreEqual(new object[] { 58, "interface arg" }, appliedDirective.ArgumentValues); @@ -76,13 +77,13 @@ public void CreateGraphType_DeclaredInterfacesAreCaptured() // __typename and Field3 // only those declared on the interface, not those inherited - Assert.AreEqual(2, Enumerable.Count(interfaceType.Fields)); + Assert.AreEqual(2, interfaceType.Fields.Count()); // should reference the two additional interfaces // ITestInterface1 ITestInterface2 - Assert.AreEqual(2, Enumerable.Count(interfaceType.InterfaceNames)); - Assert.IsTrue(Enumerable.Any(interfaceType.InterfaceNames, x => x == "ITestInterface1")); - Assert.IsTrue(Enumerable.Any(interfaceType.InterfaceNames, x => x == "ITestInterface2")); + Assert.AreEqual(2, interfaceType.InterfaceNames.Count()); + Assert.IsTrue(interfaceType.InterfaceNames.Any(x => x == "ITestInterface1")); + Assert.IsTrue(interfaceType.InterfaceNames.Any(x => x == "ITestInterface2")); } [Test] diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/ObjectGraphTypeMakerTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/ObjectGraphTypeMakerTests.cs similarity index 85% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/ObjectGraphTypeMakerTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/ObjectGraphTypeMakerTests.cs index d65d8175d..2360395fd 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/ObjectGraphTypeMakerTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/ObjectGraphTypeMakerTests.cs @@ -6,7 +6,8 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers { using System.Linq; using GraphQL.AspNet.Configuration; @@ -18,8 +19,8 @@ namespace GraphQL.AspNet.Tests.Engine.TypeMakers using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.CommonHelpers; - using GraphQL.AspNet.Tests.Engine.TypeMakers.TestData; using GraphQL.AspNet.Tests.Framework; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData; using NUnit.Framework; [TestFixture] @@ -122,8 +123,8 @@ public void CreateGraphType_WhenMethodDelcarationIsRequired_DoesNotIncludeUndecl var objectGraphType = this.MakeGraphType(typeof(TypeWithUndeclaredFields), TypeKind.OBJECT, TemplateDeclarationRequirements.Method).GraphType as IObjectGraphType; Assert.IsNotNull(objectGraphType); - Assert.IsTrue(Enumerable.Any(objectGraphType.Fields, x => x.Name == nameof(TypeWithUndeclaredFields.DeclaredMethod))); - Assert.IsFalse(Enumerable.Any(objectGraphType.Fields, x => x.Name == nameof(TypeWithUndeclaredFields.UndeclaredMethod))); + Assert.IsTrue(objectGraphType.Fields.Any(x => x.Name == nameof(TypeWithUndeclaredFields.DeclaredMethod))); + Assert.IsFalse(objectGraphType.Fields.Any(x => x.Name == nameof(TypeWithUndeclaredFields.UndeclaredMethod))); } [Test] @@ -132,8 +133,8 @@ public void CreateGraphType_WhenMethodDelcarationIsNotRequired_DoesIncludeUndecl var objectGraphType = this.MakeGraphType(typeof(TypeWithUndeclaredFields), TypeKind.OBJECT, TemplateDeclarationRequirements.None).GraphType as IObjectGraphType; Assert.IsNotNull(objectGraphType); - Assert.IsTrue(Enumerable.Any(objectGraphType.Fields, x => x.Name == nameof(TypeWithUndeclaredFields.DeclaredMethod))); - Assert.IsTrue(Enumerable.Any(objectGraphType.Fields, x => x.Name == nameof(TypeWithUndeclaredFields.UndeclaredMethod))); + Assert.IsTrue(objectGraphType.Fields.Any(x => x.Name == nameof(TypeWithUndeclaredFields.DeclaredMethod))); + Assert.IsTrue(objectGraphType.Fields.Any(x => x.Name == nameof(TypeWithUndeclaredFields.UndeclaredMethod))); } [Test] @@ -142,8 +143,8 @@ public void CreateGraphType_AsObject_WhenPropertyDelcarationIsRequired_DoesNotIn var objectGraphType = this.MakeGraphType(typeof(TypeWithUndeclaredFields), TypeKind.OBJECT, TemplateDeclarationRequirements.Property).GraphType as IObjectGraphType; Assert.IsNotNull(objectGraphType); - Assert.IsTrue(Enumerable.Any(objectGraphType.Fields, x => x.Name == nameof(TypeWithUndeclaredFields.DeclaredProperty))); - Assert.IsFalse(Enumerable.Any(objectGraphType.Fields, x => x.Name == nameof(TypeWithUndeclaredFields.UndeclaredProperty))); + Assert.IsTrue(objectGraphType.Fields.Any(x => x.Name == nameof(TypeWithUndeclaredFields.DeclaredProperty))); + Assert.IsFalse(objectGraphType.Fields.Any(x => x.Name == nameof(TypeWithUndeclaredFields.UndeclaredProperty))); } [Test] @@ -152,8 +153,8 @@ public void CreateGraphType_AsObject_WhenPropertyDelcarationIsNotRequired_DoesIn var objectGraphType = this.MakeGraphType(typeof(TypeWithUndeclaredFields), TypeKind.OBJECT, TemplateDeclarationRequirements.None).GraphType as IObjectGraphType; Assert.IsNotNull(objectGraphType); - Assert.IsTrue(Enumerable.Any(objectGraphType.Fields, x => x.Name == nameof(TypeWithUndeclaredFields.DeclaredProperty))); - Assert.IsTrue(Enumerable.Any(objectGraphType.Fields, x => x.Name == nameof(TypeWithUndeclaredFields.UndeclaredProperty))); + Assert.IsTrue(objectGraphType.Fields.Any(x => x.Name == nameof(TypeWithUndeclaredFields.DeclaredProperty))); + Assert.IsTrue(objectGraphType.Fields.Any(x => x.Name == nameof(TypeWithUndeclaredFields.UndeclaredProperty))); } [Test] @@ -162,8 +163,8 @@ public void CreateGraphType_AsObject_WhenMethodDelcarationIsRequired_ButWithGrap var objectGraphType = this.MakeGraphType(typeof(TypeWithUndeclaredFieldsWithOverride), TypeKind.OBJECT, TemplateDeclarationRequirements.None).GraphType as IObjectGraphType; Assert.IsNotNull(objectGraphType); - Assert.IsTrue(Enumerable.Any(objectGraphType.Fields, x => x.Name == nameof(TypeWithUndeclaredFieldsWithOverride.DeclaredMethod))); - Assert.IsFalse(Enumerable.Any(objectGraphType.Fields, x => x.Name == nameof(TypeWithUndeclaredFieldsWithOverride.UndeclaredMethod))); + Assert.IsTrue(objectGraphType.Fields.Any(x => x.Name == nameof(TypeWithUndeclaredFieldsWithOverride.DeclaredMethod))); + Assert.IsFalse(objectGraphType.Fields.Any(x => x.Name == nameof(TypeWithUndeclaredFieldsWithOverride.UndeclaredMethod))); } [Test] @@ -172,8 +173,8 @@ public void CreateGraphType_AsObject_WhenMethodDelcarationIsNotRequired_ButWithG var objectGraphType = this.MakeGraphType(typeof(TypeWithUndeclaredFieldsWithOverrideNone), TypeKind.OBJECT, TemplateDeclarationRequirements.Method).GraphType as IObjectGraphType; Assert.IsNotNull(objectGraphType); - Assert.IsTrue(Enumerable.Any(objectGraphType.Fields, x => x.Name == nameof(TypeWithUndeclaredFieldsWithOverrideNone.DeclaredMethod))); - Assert.IsTrue(Enumerable.Any(objectGraphType.Fields, x => x.Name == nameof(TypeWithUndeclaredFieldsWithOverrideNone.UndeclaredMethod))); + Assert.IsTrue(objectGraphType.Fields.Any(x => x.Name == nameof(TypeWithUndeclaredFieldsWithOverrideNone.DeclaredMethod))); + Assert.IsTrue(objectGraphType.Fields.Any(x => x.Name == nameof(TypeWithUndeclaredFieldsWithOverrideNone.UndeclaredMethod))); } [Test] @@ -182,8 +183,8 @@ public void CreateGraphType_AsObject_WhenPropertyDelcarationIsRequired_ButWithGr var objectGraphType = this.MakeGraphType(typeof(TypeWithUndeclaredFieldsWithOverride), TypeKind.OBJECT, TemplateDeclarationRequirements.None).GraphType as IObjectGraphType; Assert.IsNotNull(objectGraphType); - Assert.IsTrue(Enumerable.Any(objectGraphType.Fields, x => x.Name == nameof(TypeWithUndeclaredFields.DeclaredProperty))); - Assert.IsFalse(Enumerable.Any(objectGraphType.Fields, x => x.Name == nameof(TypeWithUndeclaredFields.UndeclaredProperty))); + Assert.IsTrue(objectGraphType.Fields.Any(x => x.Name == nameof(TypeWithUndeclaredFields.DeclaredProperty))); + Assert.IsFalse(objectGraphType.Fields.Any(x => x.Name == nameof(TypeWithUndeclaredFields.UndeclaredProperty))); } [Test] @@ -192,8 +193,8 @@ public void CreateGraphType_AsObject_WhenPropertyDelcarationIsNotRequired_ButWit var objectGraphType = this.MakeGraphType(typeof(TypeWithUndeclaredFieldsWithOverrideNone), TypeKind.OBJECT, TemplateDeclarationRequirements.Property).GraphType as IObjectGraphType; Assert.IsNotNull(objectGraphType); - Assert.IsTrue(Enumerable.Any(objectGraphType.Fields, x => x.Name == nameof(TypeWithUndeclaredFields.DeclaredProperty))); - Assert.IsTrue(Enumerable.Any(objectGraphType.Fields, x => x.Name == nameof(TypeWithUndeclaredFields.UndeclaredProperty))); + Assert.IsTrue(objectGraphType.Fields.Any(x => x.Name == nameof(TypeWithUndeclaredFields.DeclaredProperty))); + Assert.IsTrue(objectGraphType.Fields.Any(x => x.Name == nameof(TypeWithUndeclaredFields.UndeclaredProperty))); } [Test] @@ -220,7 +221,7 @@ public void CreateGraphType_DirectivesAreApplied() Assert.AreEqual(1, objectType.AppliedDirectives.Count); Assert.AreEqual(objectType, objectType.AppliedDirectives.Parent); - var appliedDirective = Enumerable.FirstOrDefault(objectType.AppliedDirectives); + var appliedDirective = objectType.AppliedDirectives.FirstOrDefault(); Assert.IsNotNull(appliedDirective); Assert.AreEqual(typeof(DirectiveWithArgs), appliedDirective.DirectiveType); CollectionAssert.AreEqual(new object[] { 12, "object directive" }, appliedDirective.ArgumentValues); diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/ScalarGraphTypeMakerTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/ScalarGraphTypeMakerTests.cs similarity index 98% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/ScalarGraphTypeMakerTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/ScalarGraphTypeMakerTests.cs index 8c0842808..fc7e4881f 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/ScalarGraphTypeMakerTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/ScalarGraphTypeMakerTests.cs @@ -6,7 +6,8 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers { using System; using GraphQL.AspNet.Configuration.Formatting; diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/ComplexInputObject.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ComplexInputObject.cs similarity index 87% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/ComplexInputObject.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ComplexInputObject.cs index a31e8eb39..220ec23ef 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/ComplexInputObject.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ComplexInputObject.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/CustomScalarWithDirectives.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/CustomScalarWithDirectives.cs similarity index 94% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/CustomScalarWithDirectives.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/CustomScalarWithDirectives.cs index 18106e813..ec5cc1862 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/CustomScalarWithDirectives.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/CustomScalarWithDirectives.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { using System; using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/DirectiveWithArgs.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/DirectiveWithArgs.cs similarity index 90% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/DirectiveWithArgs.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/DirectiveWithArgs.cs index 8d8d7ab4e..6a1b022e0 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/DirectiveWithArgs.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/DirectiveWithArgs.cs @@ -6,7 +6,8 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Directives; diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/EnumValueWithDirective.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/EnumValueWithDirective.cs similarity index 86% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/EnumValueWithDirective.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/EnumValueWithDirective.cs index bff6bc0a6..873b0eeed 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/EnumValueWithDirective.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/EnumValueWithDirective.cs @@ -6,7 +6,8 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/EnumWithDescriptions.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/EnumWithDescriptions.cs similarity index 88% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/EnumWithDescriptions.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/EnumWithDescriptions.cs index 08b50e74c..4de779d8d 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/EnumWithDescriptions.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/EnumWithDescriptions.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { using System.ComponentModel; diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/EnumWithDirective.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/EnumWithDirective.cs similarity index 86% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/EnumWithDirective.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/EnumWithDirective.cs index ede4913c9..24d7511df 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/EnumWithDirective.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/EnumWithDirective.cs @@ -6,7 +6,8 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/EnumWithGraphName.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/EnumWithGraphName.cs similarity index 85% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/EnumWithGraphName.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/EnumWithGraphName.cs index 96b1eaf7f..c8d9ed395 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/EnumWithGraphName.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/EnumWithGraphName.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/EnumWithUndeclaredValues.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/EnumWithUndeclaredValues.cs similarity index 87% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/EnumWithUndeclaredValues.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/EnumWithUndeclaredValues.cs index d57c25ff0..e23e298bf 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/EnumWithUndeclaredValues.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/EnumWithUndeclaredValues.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/EnumWithValueOfFalseKeyword.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/EnumWithValueOfFalseKeyword.cs similarity index 85% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/EnumWithValueOfFalseKeyword.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/EnumWithValueOfFalseKeyword.cs index 6be5452e4..c0b12e3cf 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/EnumWithValueOfFalseKeyword.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/EnumWithValueOfFalseKeyword.cs @@ -6,7 +6,8 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/EnumWithValueOfNullKeyword.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/EnumWithValueOfNullKeyword.cs similarity index 85% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/EnumWithValueOfNullKeyword.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/EnumWithValueOfNullKeyword.cs index 78d0bb56c..a317fd1dd 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/EnumWithValueOfNullKeyword.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/EnumWithValueOfNullKeyword.cs @@ -6,7 +6,8 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/EnumWithValueOfTrueKeyword.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/EnumWithValueOfTrueKeyword.cs similarity index 85% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/EnumWithValueOfTrueKeyword.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/EnumWithValueOfTrueKeyword.cs index 4bd4af325..48eb95310 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/EnumWithValueOfTrueKeyword.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/EnumWithValueOfTrueKeyword.cs @@ -6,7 +6,8 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/ISimpleInterface.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ISimpleInterface.cs similarity index 87% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/ISimpleInterface.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ISimpleInterface.cs index c3edf5b92..0a39ea48e 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/ISimpleInterface.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ISimpleInterface.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/ITestInterface1.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ITestInterface1.cs similarity index 83% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/ITestInterface1.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ITestInterface1.cs index d86a8785b..40f862a74 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/ITestInterface1.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ITestInterface1.cs @@ -6,7 +6,8 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { public interface ITestInterface1 { diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/ITestInterface2.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ITestInterface2.cs similarity index 83% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/ITestInterface2.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ITestInterface2.cs index 756061274..299cc7659 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/ITestInterface2.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ITestInterface2.cs @@ -6,7 +6,8 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { public interface ITestInterface2 { diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/ITestInterfaceForDeclaredInterfaces.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ITestInterfaceForDeclaredInterfaces.cs similarity index 85% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/ITestInterfaceForDeclaredInterfaces.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ITestInterfaceForDeclaredInterfaces.cs index 2f31db3c3..3368591b2 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/ITestInterfaceForDeclaredInterfaces.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ITestInterfaceForDeclaredInterfaces.cs @@ -6,7 +6,8 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { public interface ITestInterfaceForDeclaredInterfaces : ITestInterface1, ITestInterface2 { diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/IUnionTestDataItem.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/IUnionTestDataItem.cs similarity index 85% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/IUnionTestDataItem.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/IUnionTestDataItem.cs index d12e499a7..6ac7fdaaa 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/IUnionTestDataItem.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/IUnionTestDataItem.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { public interface IUnionTestDataItem { diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/InputTestObject.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/InputTestObject.cs similarity index 94% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/InputTestObject.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/InputTestObject.cs index a38dad10a..f992800a8 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/InputTestObject.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/InputTestObject.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { using System.ComponentModel.DataAnnotations; using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/InputTestObjectWithDefaultFieldValues.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/InputTestObjectWithDefaultFieldValues.cs similarity index 92% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/InputTestObjectWithDefaultFieldValues.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/InputTestObjectWithDefaultFieldValues.cs index 3fe095029..ee7bc5cfe 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/InputTestObjectWithDefaultFieldValues.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/InputTestObjectWithDefaultFieldValues.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { using System.ComponentModel.DataAnnotations; using GraphQL.AspNet.Tests.Common.CommonHelpers; diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/InputTypeWithDirective.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/InputTypeWithDirective.cs similarity index 86% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/InputTypeWithDirective.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/InputTypeWithDirective.cs index ff5a9cfe6..44289e234 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/InputTypeWithDirective.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/InputTypeWithDirective.cs @@ -6,7 +6,8 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/InterfaceThatInheritsDeclaredMethodField.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/InterfaceThatInheritsDeclaredMethodField.cs similarity index 87% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/InterfaceThatInheritsDeclaredMethodField.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/InterfaceThatInheritsDeclaredMethodField.cs index 68f237751..048fbeae7 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/InterfaceThatInheritsDeclaredMethodField.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/InterfaceThatInheritsDeclaredMethodField.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { public interface InterfaceThatInheritsDeclaredMethodField : InterfaceWithDeclaredInterfaceField { diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/InterfaceThatInheritsUndeclaredMethodField.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/InterfaceThatInheritsUndeclaredMethodField.cs similarity index 87% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/InterfaceThatInheritsUndeclaredMethodField.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/InterfaceThatInheritsUndeclaredMethodField.cs index db4791e7f..167417811 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/InterfaceThatInheritsUndeclaredMethodField.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/InterfaceThatInheritsUndeclaredMethodField.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { public interface InterfaceThatInheritsUndeclaredMethodField : InterfaceWithUndeclaredInterfaceField { diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/InterfaceWithDeclaredInterfaceField.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/InterfaceWithDeclaredInterfaceField.cs similarity index 88% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/InterfaceWithDeclaredInterfaceField.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/InterfaceWithDeclaredInterfaceField.cs index 5119d69a1..3c47c9c2d 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/InterfaceWithDeclaredInterfaceField.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/InterfaceWithDeclaredInterfaceField.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/InterfaceWithDirective.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/InterfaceWithDirective.cs similarity index 87% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/InterfaceWithDirective.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/InterfaceWithDirective.cs index b9e57b696..aaddd1011 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/InterfaceWithDirective.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/InterfaceWithDirective.cs @@ -6,7 +6,8 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/InterfaceWithUndeclaredInterfaceField.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/InterfaceWithUndeclaredInterfaceField.cs similarity index 86% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/InterfaceWithUndeclaredInterfaceField.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/InterfaceWithUndeclaredInterfaceField.cs index 9a044f78d..a9425b8fa 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/InterfaceWithUndeclaredInterfaceField.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/InterfaceWithUndeclaredInterfaceField.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { public interface InterfaceWithUndeclaredInterfaceField { diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/MultiMethodDirective.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/MultiMethodDirective.cs similarity index 93% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/MultiMethodDirective.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/MultiMethodDirective.cs index 25136a25e..74224ea21 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/MultiMethodDirective.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/MultiMethodDirective.cs @@ -6,7 +6,8 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { using System.ComponentModel; using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/NullableEnumController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/NullableEnumController.cs similarity index 90% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/NullableEnumController.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/NullableEnumController.cs index 43cbfec2d..1df09798a 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/NullableEnumController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/NullableEnumController.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/ObjectDirectiveTestItem.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ObjectDirectiveTestItem.cs similarity index 92% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/ObjectDirectiveTestItem.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ObjectDirectiveTestItem.cs index 6d251d183..f00833fc2 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/ObjectDirectiveTestItem.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ObjectDirectiveTestItem.cs @@ -6,7 +6,8 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/ObjectWithDeclaredMethodField.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ObjectWithDeclaredMethodField.cs similarity index 87% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/ObjectWithDeclaredMethodField.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ObjectWithDeclaredMethodField.cs index 74be406cd..bf477954b 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/ObjectWithDeclaredMethodField.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ObjectWithDeclaredMethodField.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/ObjectWithInheritedDeclaredMethodField.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ObjectWithInheritedDeclaredMethodField.cs similarity index 85% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/ObjectWithInheritedDeclaredMethodField.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ObjectWithInheritedDeclaredMethodField.cs index 6fa45f95e..52b19222d 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/ObjectWithInheritedDeclaredMethodField.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ObjectWithInheritedDeclaredMethodField.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { public class ObjectWithInheritedDeclaredMethodField : ObjectWithDeclaredMethodField { diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/ObjectWithInheritedUndeclaredMethodField.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ObjectWithInheritedUndeclaredMethodField.cs similarity index 85% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/ObjectWithInheritedUndeclaredMethodField.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ObjectWithInheritedUndeclaredMethodField.cs index df004d7d2..6eb8b51dc 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/ObjectWithInheritedUndeclaredMethodField.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ObjectWithInheritedUndeclaredMethodField.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { public class ObjectWithInheritedUndeclaredMethodField : ObjectWithUndeclaredMethodField { diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/ObjectWithUndeclaredMethodField.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ObjectWithUndeclaredMethodField.cs similarity index 85% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/ObjectWithUndeclaredMethodField.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ObjectWithUndeclaredMethodField.cs index 1bd934e10..b082f9c30 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/ObjectWithUndeclaredMethodField.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ObjectWithUndeclaredMethodField.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { public class ObjectWithUndeclaredMethodField { diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/OneMarkedProperty.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/OneMarkedProperty.cs similarity index 87% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/OneMarkedProperty.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/OneMarkedProperty.cs index f0f52b796..d9834f680 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/OneMarkedProperty.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/OneMarkedProperty.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/PropAuthorizeAttribute.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/PropAuthorizeAttribute.cs similarity index 86% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/PropAuthorizeAttribute.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/PropAuthorizeAttribute.cs index 5ae51dc05..c403f6893 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/PropAuthorizeAttribute.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/PropAuthorizeAttribute.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { using System; using Microsoft.AspNetCore.Authorization; diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/RepeatableDirective.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/RepeatableDirective.cs similarity index 91% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/RepeatableDirective.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/RepeatableDirective.cs index 294b24a5f..51a768753 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/RepeatableDirective.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/RepeatableDirective.cs @@ -6,7 +6,8 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Directives; diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/SecuredController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/SecuredController.cs similarity index 91% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/SecuredController.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/SecuredController.cs index bf8d6b103..d472ce2da 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/SecuredController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/SecuredController.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Controllers; diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/SelfReferencingObject.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/SelfReferencingObject.cs similarity index 87% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/SelfReferencingObject.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/SelfReferencingObject.cs index f65318b8d..84e80058e 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/SelfReferencingObject.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/SelfReferencingObject.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/SimplePropertyObject.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/SimplePropertyObject.cs similarity index 93% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/SimplePropertyObject.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/SimplePropertyObject.cs index ec6523f95..e6b1e5bbc 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/SimplePropertyObject.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/SimplePropertyObject.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { using System.Collections.Generic; using System.ComponentModel; diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/TypeCreationItem.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/TypeCreationItem.cs similarity index 91% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/TypeCreationItem.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/TypeCreationItem.cs index 0710b4c81..be12a0286 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/TypeCreationItem.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/TypeCreationItem.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Tests.Common.CommonHelpers; diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/TypeWithUndeclaredFields.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/TypeWithUndeclaredFields.cs similarity index 93% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/TypeWithUndeclaredFields.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/TypeWithUndeclaredFields.cs index 39dd6f2cf..6c728f9cf 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/TypeWithUndeclaredFields.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/TypeWithUndeclaredFields.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/TypeWithUndeclaredFieldsWithOverride.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/TypeWithUndeclaredFieldsWithOverride.cs similarity index 94% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/TypeWithUndeclaredFieldsWithOverride.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/TypeWithUndeclaredFieldsWithOverride.cs index 717f8c7fb..ebc897397 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/TypeWithUndeclaredFieldsWithOverride.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/TypeWithUndeclaredFieldsWithOverride.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Configuration; diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/TypeWithUndeclaredFieldsWithOverrideNone.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/TypeWithUndeclaredFieldsWithOverrideNone.cs similarity index 94% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/TypeWithUndeclaredFieldsWithOverrideNone.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/TypeWithUndeclaredFieldsWithOverrideNone.cs index 4e1d7fc73..b37f0b90c 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/TypeWithUndeclaredFieldsWithOverrideNone.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/TypeWithUndeclaredFieldsWithOverrideNone.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Configuration; diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/UnionDataA.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/UnionDataA.cs similarity index 86% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/UnionDataA.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/UnionDataA.cs index 08c52abc8..027a25f05 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/UnionDataA.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/UnionDataA.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { public class UnionDataA : IUnionTestDataItem { diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/UnionDataB.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/UnionDataB.cs similarity index 86% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/UnionDataB.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/UnionDataB.cs index 5fb9bc69d..2861a7a82 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/UnionDataB.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/UnionDataB.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { public class UnionDataB : IUnionTestDataItem { diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/UnionProxyWithDirective.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/UnionProxyWithDirective.cs similarity index 87% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/UnionProxyWithDirective.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/UnionProxyWithDirective.cs index 5b537beaa..65e88d031 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/UnionProxyWithDirective.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/UnionProxyWithDirective.cs @@ -6,7 +6,8 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Schemas.TypeSystem; diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/UnionProxyWithInvalidDirective.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/UnionProxyWithInvalidDirective.cs similarity index 89% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/UnionProxyWithInvalidDirective.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/UnionProxyWithInvalidDirective.cs index 94b721492..c4bfa0200 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/UnionProxyWithInvalidDirective.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/UnionProxyWithInvalidDirective.cs @@ -6,7 +6,8 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Schemas.TypeSystem; diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/UnionTestController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/UnionTestController.cs similarity index 96% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/UnionTestController.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/UnionTestController.cs index fcb25b622..08c97963d 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/UnionTestController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/UnionTestController.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { using System; using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/UnionTestProxy.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/UnionTestProxy.cs similarity index 92% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/UnionTestProxy.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/UnionTestProxy.cs index 221e09654..a7129705e 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/TestData/UnionTestProxy.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/UnionTestProxy.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers.TestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { using System; using System.Collections.Generic; diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/UnionTypeMakerTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/UnionTypeMakerTests.cs similarity index 80% rename from src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/UnionTypeMakerTests.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/UnionTypeMakerTests.cs index e55a7f19b..de9e9cf6a 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/TypeMakers/UnionTypeMakerTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/UnionTypeMakerTests.cs @@ -6,7 +6,8 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Engine.TypeMakers + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers { using System; using System.Linq; @@ -15,8 +16,8 @@ namespace GraphQL.AspNet.Tests.Engine.TypeMakers using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Schemas.Generation.TypeMakers; using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Tests.Engine.TypeMakers.TestData; using GraphQL.AspNet.Tests.Framework; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData; using NUnit.Framework; [TestFixture] @@ -37,13 +38,13 @@ public void ActionTemplate_CreateUnionType_PropertyCheck() Assert.AreEqual("FragmentData", union.Name); Assert.IsNull(union.Description); - Assert.AreEqual(2, Enumerable.Count(union.PossibleGraphTypeNames)); - Assert.AreEqual(2, Enumerable.Count(union.PossibleConcreteTypes)); + Assert.AreEqual(2, union.PossibleGraphTypeNames.Count()); + Assert.AreEqual(2, union.PossibleConcreteTypes.Count()); - Assert.IsTrue((bool)union.PossibleGraphTypeNames.Contains(nameof(UnionDataA))); - Assert.IsTrue((bool)union.PossibleGraphTypeNames.Contains(nameof(UnionDataB))); - Assert.IsTrue((bool)union.PossibleConcreteTypes.Contains(typeof(UnionDataA))); - Assert.IsTrue((bool)union.PossibleConcreteTypes.Contains(typeof(UnionDataB))); + Assert.IsTrue(union.PossibleGraphTypeNames.Contains(nameof(UnionDataA))); + Assert.IsTrue(union.PossibleGraphTypeNames.Contains(nameof(UnionDataB))); + Assert.IsTrue(union.PossibleConcreteTypes.Contains(typeof(UnionDataA))); + Assert.IsTrue(union.PossibleConcreteTypes.Contains(typeof(UnionDataB))); } [Test] @@ -60,7 +61,7 @@ public void UnionProxyWithDirectives_DirectivesAreApplied() Assert.AreEqual(1, unionType.AppliedDirectives.Count); Assert.AreEqual(unionType, unionType.AppliedDirectives.Parent); - var appliedDirective = Enumerable.FirstOrDefault(unionType.AppliedDirectives); + var appliedDirective = unionType.AppliedDirectives.FirstOrDefault(); Assert.IsNotNull(appliedDirective); Assert.AreEqual(typeof(DirectiveWithArgs), appliedDirective.DirectiveType); CollectionAssert.AreEqual(new object[] { 121, "union directive" }, appliedDirective.ArgumentValues); diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionMethodTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionMethodTemplateTests.cs index f4c3594a8..6d13e11c8 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionMethodTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionMethodTemplateTests.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.Templating +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates { using System.Linq; using GraphQL.AspNet.Controllers; @@ -60,8 +60,8 @@ public void ActionTemplate_Parse_BasicPropertySets() Assert.AreEqual("path0", action.Parent.Name); Assert.AreEqual(methodInfo, action.Method); Assert.AreEqual(0, action.Arguments.Count); - Assert.IsFalse((bool)action.Route.IsTopLevelField); - Assert.IsFalse((bool)action.IsAsyncField); + Assert.IsFalse(action.Route.IsTopLevelField); + Assert.IsFalse(action.IsAsyncField); } [Test] @@ -71,7 +71,7 @@ public void ActionTemplate_Parse_MethodMarkedAsOperationIsAssignedARootPath() Assert.AreEqual(SchemaItemCollections.Query, action.Route.RootCollection); Assert.AreEqual(0, action.Arguments.Count); - Assert.IsFalse((bool)action.IsAsyncField); + Assert.IsFalse(action.IsAsyncField); Assert.AreEqual("[query]/path22", action.Route.Path); } @@ -84,9 +84,9 @@ public void ActionTemplate_Parse_WithValidDeclaredUnion_ParsesCorrectly() Assert.IsNotNull(action.UnionProxy); Assert.AreEqual(2, action.UnionProxy.Types.Count); Assert.AreEqual(action.ObjectType, typeof(object)); - Assert.IsTrue((bool)action.TypeExpression.IsListOfItems); - Assert.IsTrue((bool)action.UnionProxy.Types.Contains(typeof(UnionDataA))); - Assert.IsTrue((bool)action.UnionProxy.Types.Contains(typeof(UnionDataB))); + Assert.IsTrue(action.TypeExpression.IsListOfItems); + Assert.IsTrue(action.UnionProxy.Types.Contains(typeof(UnionDataA))); + Assert.IsTrue(action.UnionProxy.Types.Contains(typeof(UnionDataB))); Assert.IsNull(action.UnionProxy.Description); Assert.AreEqual("FragmentData", action.UnionProxy.Name); } @@ -145,7 +145,7 @@ public void ActionTemplate_ReturnTypeOfActionResult_WithDeclaredListDataType_Ren var action = this.CreateActionTemplate(nameof(ActionResultReturnTypeController.ActionResultMethodWithListReturnType)); Assert.AreEqual(typeof(TwoPropertyObject), action.ObjectType); - Assert.IsTrue((bool)action.TypeExpression.IsListOfItems); + Assert.IsTrue(action.TypeExpression.IsListOfItems); } [Test] @@ -189,11 +189,11 @@ public void ActionTemplate_ReturnTypeOfInterface_WithPossibleTypesAttribute_Retr var types = action.RetrieveRequiredTypes(); Assert.IsNotNull(types); - Assert.AreEqual(3, Enumerable.Count(types)); + Assert.AreEqual(3, types.Count()); - Assert.IsTrue(Enumerable.Any(types, x => x.Type == typeof(TestItemA))); - Assert.IsTrue(Enumerable.Any(types, x => x.Type == typeof(TestItemB))); - Assert.IsTrue(Enumerable.Any(types, x => x.Type == typeof(ITestItem))); + Assert.IsTrue(types.Any(x => x.Type == typeof(TestItemA))); + Assert.IsTrue(types.Any(x => x.Type == typeof(TestItemB))); + Assert.IsTrue(types.Any(x => x.Type == typeof(ITestItem))); } [Test] @@ -203,9 +203,9 @@ public void ActionTemplate_ReturnTypeOfInterface_WithoutPossibleTypesAttribute_D var types = action.RetrieveRequiredTypes(); Assert.IsNotNull(types); - Assert.AreEqual(1, Enumerable.Count(types)); + Assert.AreEqual(1, types.Count()); - Assert.IsTrue(Enumerable.Any(types, x => x.Type == typeof(ITestItem))); + Assert.IsTrue(types.Any(x => x.Type == typeof(ITestItem))); } [Test] @@ -252,7 +252,7 @@ public void ActionTemplate_ArrayOnInputParameter_RendersFine() var types = action.RetrieveRequiredTypes(); Assert.IsNotNull(types); - Assert.IsTrue(Enumerable.Any(types, x => x.Type == typeof(string))); + Assert.IsTrue(types.Any(x => x.Type == typeof(string))); Assert.AreEqual(1, action.Arguments.Count); Assert.AreEqual(typeof(TwoPropertyObject[]), action.Arguments[0].DeclaredArgumentType); @@ -264,9 +264,9 @@ public void Parse_AssignedDirective_IsTemplatized() { var action = this.CreateActionTemplate(nameof(ActionMethodWithDirectiveController.Execute)); - Assert.AreEqual(1, Enumerable.Count(action.AppliedDirectives)); + Assert.AreEqual(1, action.AppliedDirectives.Count()); - var appliedDirective = Enumerable.First(action.AppliedDirectives); + var appliedDirective = action.AppliedDirectives.First(); Assert.AreEqual(typeof(DirectiveWithArgs), appliedDirective.DirectiveType); Assert.AreEqual(new object[] { 202, "controller action arg" }, appliedDirective.Arguments); } diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/AppliedDirectiveTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/AppliedDirectiveTemplateTests.cs index 152cfef88..0ad14fc04 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/AppliedDirectiveTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/AppliedDirectiveTemplateTests.cs @@ -6,11 +6,13 @@ // -- // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.Templating + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates { using System; using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Interfaces.Internal; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.DirectiveTestData; using Moq; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ArgumentTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ArgumentTemplateTests.cs index cd17b4328..f5acce68f 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ArgumentTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ArgumentTemplateTests.cs @@ -19,6 +19,7 @@ namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.Structural; + using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Tests.CommonHelpers; using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.DirectiveTestData; using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ParameterTestData; @@ -293,6 +294,22 @@ public void IncompatiableTypeExpressionNullToNotNull_ThrowsException() }); } + [Test] + public void FromGraphQLDeclaration_SetsParamModifierAppropriately() + { + var template = this.ExtractParameterTemplate("justFromGraphQLDeclaration", out var paramInfo); + Assert.AreEqual(GraphArgumentModifiers.ExplicitSchemaItem, template.ArgumentModifiers); + } + + [Test] + public void FromServiceDeclaration_SetsParamModifierAppropriately() + { + // actual type expression [Int] + // declared as [Int!]! + var template = this.ExtractParameterTemplate("compatiableTypeExpressionList", out var paramInfo); + Assert.AreEqual(GraphArgumentModifiers.ExplicitInjected, template.ArgumentModifiers); + } + [Test] public void ArgumentAttributedasFromGraphQLAndFromServices_ThrowsException() { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveMethodTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveMethodTemplateTests.cs index 838f798f2..05e7aeccf 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveMethodTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveMethodTemplateTests.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.Templating +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates { using GraphQL.AspNet.Execution; using GraphQL.AspNet.Execution.Exceptions; @@ -43,7 +43,7 @@ public void SimpleDescriptor_AllDefaults_GeneralPropertyCheck() Assert.AreEqual("IGraphActionResult (object source, int arg1, string arg2)", template.MethodSignature); Assert.AreEqual(nameof(SimpleExecutableDirective.Execute), template.Name); Assert.AreEqual($"Simple.{nameof(SimpleExecutableDirective.Execute)}", template.InternalFullName); - Assert.IsTrue((bool)template.IsAsyncField); + Assert.IsTrue(template.IsAsyncField); Assert.AreEqual(typeof(IGraphActionResult), template.ObjectType); Assert.AreEqual(DirectiveLocation.FIELD, template.Locations); Assert.AreEqual(3, template.Arguments.Count); @@ -53,7 +53,7 @@ public void SimpleDescriptor_AllDefaults_GeneralPropertyCheck() Assert.AreEqual(typeof(int), template.Arguments[1].ObjectType); Assert.AreEqual("arg2", template.Arguments[2].Name); Assert.AreEqual(typeof(string), template.Arguments[2].ObjectType); - Assert.IsTrue((bool)template.IsExplicitDeclaration); + Assert.IsTrue(template.IsExplicitDeclaration); Assert.AreEqual(GraphFieldSource.Method, template.FieldSource); Assert.AreEqual(null, template.DeclaredTypeWrappers); diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTemplateTests.cs index bc56b1c5a..d87c4216c 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTemplateTests.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.Templating +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates { using System.Linq; using GraphQL.AspNet.Common.Extensions; @@ -33,12 +33,12 @@ public void Simpletemplate_AllDefaults_GeneralPropertyCheck() Assert.AreEqual(typeof(SimpleExecutableDirective).FriendlyName(true), template.InternalFullName); Assert.AreEqual("Simple Description", template.Description); Assert.AreEqual(1, template.Methods.Count); - Assert.IsTrue((bool)template.Locations.HasFlag(DirectiveLocation.FIELD)); + Assert.IsTrue(template.Locations.HasFlag(DirectiveLocation.FIELD)); Assert.AreEqual(typeof(SimpleExecutableDirective), template.ObjectType); Assert.AreEqual("[directive]/SimpleExecutable", template.Route.Path); Assert.AreEqual(DirectiveLocation.FIELD, template.Locations); Assert.IsNotNull(template.Methods.FindMetaData(DirectiveLocation.FIELD)); - Assert.IsFalse((bool)template.IsRepeatable); + Assert.IsFalse(template.IsRepeatable); } [Test] @@ -106,7 +106,7 @@ public void RepeatableAttribute_SetsRepeatableProperty() template.Parse(); template.ValidateOrThrow(); - Assert.IsTrue((bool)template.IsRepeatable); + Assert.IsTrue(template.IsRepeatable); } [Test] @@ -118,13 +118,13 @@ public void SecurityPolicices_AreParsedCorrectly() Assert.AreEqual(2, template.SecurityPolicies.Count); - Assert.IsFalse((bool)template.SecurityPolicies.AllowAnonymous); + Assert.IsFalse(template.SecurityPolicies.AllowAnonymous); - Assert.IsTrue(Enumerable.ElementAt(template.SecurityPolicies, 0).IsNamedPolicy); - Assert.AreEqual("CustomPolicy", Enumerable.ElementAt(template.SecurityPolicies, 0).PolicyName); + Assert.IsTrue(template.SecurityPolicies.ElementAt(0).IsNamedPolicy); + Assert.AreEqual("CustomPolicy", template.SecurityPolicies.ElementAt(0).PolicyName); - Assert.IsFalse(Enumerable.ElementAt(template.SecurityPolicies, 1).IsNamedPolicy); - CollectionAssert.AreEquivalent(new string[] { "CustomRole1", "CustomRole2" }, Enumerable.ElementAt(template.SecurityPolicies, 1).AllowedRoles); + Assert.IsFalse(template.SecurityPolicies.ElementAt(1).IsNamedPolicy); + CollectionAssert.AreEquivalent(new string[] { "CustomRole1", "CustomRole2" }, template.SecurityPolicies.ElementAt(1).AllowedRoles); } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumGraphTypeTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumGraphTypeTemplateTests.cs index 01c4a6a09..42ad517c5 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumGraphTypeTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumGraphTypeTemplateTests.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.Templating +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates { using System; using System.Linq; @@ -31,7 +31,7 @@ public void Parse_SimpleEnum_AllDefault_ParsesCorrectly() Assert.AreEqual($"{Constants.Routing.ENUM_ROOT}/{nameof(SimpleEnum)}", template.Route.Path); Assert.AreEqual(nameof(SimpleEnum), template.Name); Assert.AreEqual(null, template.Description); - Assert.AreEqual(1, Enumerable.Count(template.Values)); + Assert.AreEqual(1, template.Values.Count()); Assert.AreEqual("Value1", template.Values[0].Name); Assert.AreEqual(null, template.Values[0].Description); } @@ -63,10 +63,10 @@ public void Parse_EnumWithDescriptionOnValues_ParsesCorrectly() template.Parse(); template.ValidateOrThrow(); - Assert.IsTrue(Enumerable.Any(template.Values, x => x.Name == "Value1" && x.Description == null)); - Assert.IsTrue(Enumerable.Any(template.Values, x => x.Name == "Value2" && x.Description == "Value2 Description")); - Assert.IsTrue(Enumerable.Any(template.Values, x => x.Name == "Value3" && x.Description == null)); - Assert.IsTrue(Enumerable.Any(template.Values, x => x.Name == "Value4" && x.Description == "Value4 Description")); + Assert.IsTrue(template.Values.Any(x => x.Name == "Value1" && x.Description == null)); + Assert.IsTrue(template.Values.Any(x => x.Name == "Value2" && x.Description == "Value2 Description")); + Assert.IsTrue(template.Values.Any(x => x.Name == "Value3" && x.Description == null)); + Assert.IsTrue(template.Values.Any(x => x.Name == "Value4" && x.Description == "Value4 Description")); } [Test] @@ -88,9 +88,9 @@ public void Parse_EnumWithValueWithGraphName_ParsesCorrectly() template.Parse(); template.ValidateOrThrow(); - Assert.IsTrue(Enumerable.Any(template.Values, x => x.Name == "Value1")); - Assert.IsTrue(Enumerable.Any(template.Values, x => x.Name == "AnotherName")); - Assert.IsTrue(Enumerable.All(template.Values, x => x.Name != "Value2")); + Assert.IsTrue(template.Values.Any(x => x.Name == "Value1")); + Assert.IsTrue(template.Values.Any(x => x.Name == "AnotherName")); + Assert.IsTrue(template.Values.All(x => x.Name != "Value2")); } [Test] @@ -112,9 +112,9 @@ public void Parse_EnumWithNonIntBase_ParsesCorrectly() template.ValidateOrThrow(); Assert.AreEqual(3, template.Values.Count); - Assert.IsTrue(Enumerable.Any(template.Values, x => x.Name == "Value1")); - Assert.IsTrue(Enumerable.Any(template.Values, x => x.Name == "Value2")); - Assert.IsTrue(Enumerable.Any(template.Values, x => x.Name != "Value3")); + Assert.IsTrue(template.Values.Any(x => x.Name == "Value1")); + Assert.IsTrue(template.Values.Any(x => x.Name == "Value2")); + Assert.IsTrue(template.Values.Any(x => x.Name != "Value3")); } [Test] @@ -152,12 +152,12 @@ public void Parse_EnsureEnumsOfSignedValues(Type type) template.ValidateOrThrow(); Assert.AreEqual(6, template.Values.Count); - Assert.IsTrue(Enumerable.Any(template.Values, x => x.Name == "Value1")); - Assert.IsTrue(Enumerable.Any(template.Values, x => x.Name == "Value2")); - Assert.IsTrue(Enumerable.Any(template.Values, x => x.Name != "Value3")); - Assert.IsTrue(Enumerable.Any(template.Values, x => x.Name == "Value4")); - Assert.IsTrue(Enumerable.Any(template.Values, x => x.Name == "Value5")); - Assert.IsTrue(Enumerable.Any(template.Values, x => x.Name != "Value6")); + Assert.IsTrue(template.Values.Any(x => x.Name == "Value1")); + Assert.IsTrue(template.Values.Any(x => x.Name == "Value2")); + Assert.IsTrue(template.Values.Any(x => x.Name != "Value3")); + Assert.IsTrue(template.Values.Any(x => x.Name == "Value4")); + Assert.IsTrue(template.Values.Any(x => x.Name == "Value5")); + Assert.IsTrue(template.Values.Any(x => x.Name != "Value6")); } [TestCase(typeof(EnumFromByte))] @@ -171,9 +171,9 @@ public void Parse_EnsureEnumsOfUnSignedValues(Type type) template.ValidateOrThrow(); Assert.AreEqual(3, template.Values.Count); - Assert.IsTrue(Enumerable.Any(template.Values, x => x.Name == "Value1")); - Assert.IsTrue(Enumerable.Any(template.Values, x => x.Name == "Value2")); - Assert.IsTrue(Enumerable.Any(template.Values, x => x.Name != "Value3")); + Assert.IsTrue(template.Values.Any(x => x.Name == "Value1")); + Assert.IsTrue(template.Values.Any(x => x.Name == "Value2")); + Assert.IsTrue(template.Values.Any(x => x.Name != "Value3")); } [Test] @@ -209,9 +209,9 @@ public void Parse_AssignedDirective_IsTemplatized() template.Parse(); template.ValidateOrThrow(); - Assert.AreEqual(1, Enumerable.Count(template.AppliedDirectives)); + Assert.AreEqual(1, template.AppliedDirectives.Count()); - var appliedDirective = Enumerable.First(template.AppliedDirectives); + var appliedDirective = template.AppliedDirectives.First(); Assert.AreEqual(typeof(DirectiveWithArgs), appliedDirective.DirectiveType); Assert.AreEqual(new object[] { 5, "bob" }, appliedDirective.Arguments); } @@ -223,12 +223,12 @@ public void Parse_EnumOption_AssignedDirective_IsTemplatized() template.Parse(); template.ValidateOrThrow(); - Assert.AreEqual(0, Enumerable.Count(template.AppliedDirectives)); + Assert.AreEqual(0, template.AppliedDirectives.Count()); - var optionTemplate = Enumerable.FirstOrDefault(template.Values, x => x.Name == "Value1"); + var optionTemplate = template.Values.FirstOrDefault(x => x.Name == "Value1"); Assert.AreEqual(0, optionTemplate.AppliedDirectives.Count()); - optionTemplate = Enumerable.FirstOrDefault(template.Values, x => x.Name == "Value2"); + optionTemplate = template.Values.FirstOrDefault(x => x.Name == "Value2"); Assert.AreEqual(1, optionTemplate.AppliedDirectives.Count()); var appliedDirective = optionTemplate.AppliedDirectives.First(); diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/GraphTypeNamesTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/GraphTypeNamesTests.cs index b561c1e18..2e89697fd 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/GraphTypeNamesTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/GraphTypeNamesTests.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.Templating +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates { using System; using System.Collections.Generic; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InputGraphFieldTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InputGraphFieldTemplateTests.cs index c41ac0296..c657d5ab6 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InputGraphFieldTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InputGraphFieldTemplateTests.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.Templating +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates { using System.Linq; using GraphQL.AspNet.Execution.Exceptions; @@ -39,10 +39,10 @@ public void Parse_GeneralPropertyCheck() Assert.AreEqual("[type]/Item0/Name", template.Route.ToString()); Assert.AreEqual("name desc", template.Description); Assert.AreEqual(typeof(string), template.ObjectType); - Assert.IsFalse((bool)template.IsRequired); + Assert.IsFalse(template.IsRequired); Assert.AreEqual("String", template.TypeExpression.ToString()); - Assert.AreEqual(1, Enumerable.Count(template.AppliedDirectives)); - Assert.AreEqual("nameDirective", Enumerable.Single(template.AppliedDirectives).DirectiveName); + Assert.AreEqual(1, template.AppliedDirectives.Count()); + Assert.AreEqual("nameDirective", template.AppliedDirectives.Single().DirectiveName); Assert.AreEqual("Name", template.InternalName); } @@ -62,7 +62,7 @@ public void Parse_IsRequired_IsNotSet() // field does not declare [Required] therefore must // have a default value - Assert.IsFalse((bool)template.IsRequired); + Assert.IsFalse(template.IsRequired); } [Test] @@ -80,7 +80,7 @@ public void Parse_IsRequired_IsSet() template.ValidateOrThrow(); // field does declare [Required] there for cannot have a default value - Assert.IsTrue((bool)template.IsRequired); + Assert.IsTrue(template.IsRequired); } [Test] diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplateTests.cs index bafa99156..4652e6128 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplateTests.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Schemas.Generation +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates { using System.Linq; using GraphQL.AspNet.Common.Extensions; @@ -184,9 +184,9 @@ public void Parse_AssignedDirective_IsTemplatized() var parent = obj.Object; var template = this.CreateMethodTemplate(nameof(MethodClassWithDirective.Counter)); - Assert.AreEqual(1, Enumerable.Count(template.AppliedDirectives)); + Assert.AreEqual(1, template.AppliedDirectives.Count()); - var appliedDirective = Enumerable.First(template.AppliedDirectives); + var appliedDirective = template.AppliedDirectives.First(); Assert.AreEqual(typeof(DirectiveWithArgs), appliedDirective.DirectiveType); Assert.AreEqual(new object[] { 44, "method arg" }, appliedDirective.Arguments); } @@ -201,12 +201,12 @@ public void DefaultNonNullableParameter_NotMarkedRequired() var parent = obj.Object; var template = this.CreateMethodTemplate(nameof(MethodClass.DefaultNonNullableParameter)); - Assert.AreEqual(0, Enumerable.Count(template.AppliedDirectives)); + Assert.AreEqual(0, template.AppliedDirectives.Count()); Assert.AreEqual(1, template.Arguments.Count); var arg = template.Arguments[0]; - Assert.IsTrue((bool)arg.HasDefaultValue); + Assert.IsTrue(arg.HasDefaultValue); Assert.AreEqual(5, arg.DefaultValue); } diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectGraphTypeTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectGraphTypeTemplateTests.cs index 5f03281be..ca615ce3f 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectGraphTypeTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectGraphTypeTemplateTests.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Schemas.Generation +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates { using System; using System.Collections.Generic; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ParameterTestData/ParameterTestClass.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ParameterTestData/ParameterTestClass.cs index 5b77ab3d3..8cb2b362e 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ParameterTestData/ParameterTestClass.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ParameterTestData/ParameterTestClass.cs @@ -48,6 +48,8 @@ public int TestMethod( [FromGraphQL(TypeExpression = "[Type]")] int incompatiableTypeExpressionListToSingle, [FromGraphQL(TypeExpression = "Type!")] int[] incompatiableTypeExpressionSingleToList, [FromGraphQL(TypeExpression = "Type")] int incompatiableTypeExpressionNullToNotNull, // nullable expression, actual type is not nullable + [FromGraphQL] TwoPropertyObject justFromGraphQLDeclaration, + [FromServices] TwoPropertyObject justFromServicesDeclaration, [FromGraphQL] [FromServices] TwoPropertyObject doubleDeclaredObject, Person defaultValueObjectArg = null, string defaultValueStringArg = null, From 9397db77cc72680adad4f4912cd7c15195b1d848 Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Sat, 15 Jul 2023 12:04:49 -0700 Subject: [PATCH 36/63] WIP, basics of injected services are working --- ...EnabledGraphQLTypeMakerFactory{TSchema}.cs | 2 +- .../SubscriptionEnabledGraphFieldMaker.cs | 11 +- ...ptionControllerActionGraphFieldTemplate.cs | 2 +- ...chemaItemDefinitionExtensions_Internals.cs | 4 +- ...aItemDefinitionExtensions_VirtualFields.cs | 4 +- .../SchemaArgumentBindingRules.cs | 4 +- .../DefaultGraphQLSchemaFactory_GraphTypes.cs | 19 +- .../DefaultGraphQLSchemaFactory_Validation.cs | 2 +- .../Engine/DefaultGraphQLTypeMakerFactory.cs | 2 +- .../Execution/ExecutionArgumentCollection.cs | 122 +++++---- .../FieldResolverParameterMetaData.cs | 6 + .../IGraphFieldResolverParameterMetaData.cs | 6 + .../Internal/IGraphArgumentTemplate.cs | 9 +- .../BaseRuntimeControllerActionDefinition.cs | 2 +- .../RuntimeDirectiveActionDefinition.cs | 2 +- .../RuntimeResolvedFieldDefinition.cs | 4 +- .../RuntimeTypeExtensionDefinition.cs | 3 +- .../RuntimeVirtualFieldTemplate.cs | 2 +- .../BaseSchemaItemValidator.cs | 2 +- .../GraphArgumentValidator.cs | 19 +- .../GraphFieldValidator.cs | 2 +- .../NoValidationSchemaItemValidator.cs | 2 +- .../SchemaItemValidationFactory.cs | 2 +- .../Generation/TypeMakers/DirectiveMaker.cs | 2 +- .../TypeMakers/GraphArgumentMaker.cs | 3 +- .../Generation/TypeMakers/GraphFieldMaker.cs | 124 +++++---- .../Generation/TypeTemplates/DependentType.cs | 18 ++ .../TypeTemplates/GraphArgumentTemplate.cs | 65 +++-- .../TypeTemplates/ScalarGraphTypeTemplate.cs | 1 - .../TypeSystem/GraphArgumentModifiers.cs | 17 +- .../GraphArgumentModifiersExtensions.cs | 56 ++-- .../Schemas/TypeSystem/SchemaExtensions.cs | 60 ++--- ...SubscriptionEnabledFieldFieldMakerTests.cs | 6 +- .../Templating/GraphActionTemplateTests.cs | 8 +- .../TestServer.cs | 5 +- .../IInjectedService.cs | 15 ++ .../SkippedType.cs | 20 ++ .../Engine/DefaultSchemaFactoryTests.cs | 128 +++++++++ .../IServiceForExecutionArgumentTest.cs | 16 ++ .../ObjectWithFields.cs | 47 ++++ .../ServiceForExecutionArgumentTest.cs | 21 ++ .../Execution/ExecutionArgumentTests.cs | 247 ++++++++++++++++++ .../GeneralQueryExecutionRuntimeFieldTests.cs | 2 + .../GraphArgumentValidatorTests.cs | 86 ++++++ .../TypeMakers/FieldMaker_InputFieldTests.cs | 34 +-- .../FieldMaker_StandardFieldTests.cs | 94 ++++++- .../TypeMakers/GraphTypeMakerTestBase.cs | 5 +- .../ObjectWithAttributedFieldArguments.cs | 43 +++ .../TypeTemplates/ArgumentTemplateTests.cs | 8 +- .../TypeExtensionFieldTemplateTests.cs | 12 +- .../Schemas/SchemaTypeCollectionTests.cs | 4 +- 51 files changed, 1075 insertions(+), 305 deletions(-) rename src/graphql-aspnet/Schemas/{ => Generation}/RuntimeSchemaItemDefinitions/BaseRuntimeControllerActionDefinition.cs (98%) rename src/graphql-aspnet/Schemas/{ => Generation}/RuntimeSchemaItemDefinitions/RuntimeDirectiveActionDefinition.cs (95%) rename src/graphql-aspnet/Schemas/{ => Generation}/RuntimeSchemaItemDefinitions/RuntimeResolvedFieldDefinition.cs (96%) rename src/graphql-aspnet/Schemas/{ => Generation}/RuntimeSchemaItemDefinitions/RuntimeTypeExtensionDefinition.cs (96%) rename src/graphql-aspnet/Schemas/{ => Generation}/RuntimeSchemaItemDefinitions/RuntimeVirtualFieldTemplate.cs (96%) rename src/graphql-aspnet/Schemas/{ => Generation}/SchemaItemValidators/BaseSchemaItemValidator.cs (90%) rename src/graphql-aspnet/Schemas/{ => Generation}/SchemaItemValidators/GraphArgumentValidator.cs (64%) rename src/graphql-aspnet/Schemas/{ => Generation}/SchemaItemValidators/GraphFieldValidator.cs (94%) rename src/graphql-aspnet/Schemas/{ => Generation}/SchemaItemValidators/NoValidationSchemaItemValidator.cs (94%) rename src/graphql-aspnet/Schemas/{ => Generation}/SchemaItemValidators/SchemaItemValidationFactory.cs (94%) create mode 100644 src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/IInjectedService.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/SkippedType.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Execution/ExecutionArgumentTestData/IServiceForExecutionArgumentTest.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Execution/ExecutionArgumentTestData/ObjectWithFields.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Execution/ExecutionArgumentTestData/ServiceForExecutionArgumentTest.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/Generation/SchemaItemValidators/GraphArgumentValidatorTests.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ObjectWithAttributedFieldArguments.cs diff --git a/src/graphql-aspnet-subscriptions/Engine/SubscriptionEnabledGraphQLTypeMakerFactory{TSchema}.cs b/src/graphql-aspnet-subscriptions/Engine/SubscriptionEnabledGraphQLTypeMakerFactory{TSchema}.cs index f5154b6fe..2f9e8b23c 100644 --- a/src/graphql-aspnet-subscriptions/Engine/SubscriptionEnabledGraphQLTypeMakerFactory{TSchema}.cs +++ b/src/graphql-aspnet-subscriptions/Engine/SubscriptionEnabledGraphQLTypeMakerFactory{TSchema}.cs @@ -52,7 +52,7 @@ public override IGraphTypeTemplate MakeTemplate(Type objectType, TypeKind? kind /// public override IGraphFieldMaker CreateFieldMaker() { - return new SubscriptionEnabledGraphFieldMaker(this.Schema, this); + return new SubscriptionEnabledGraphFieldMaker(this.Schema, this.CreateArgumentMaker()); } } } \ No newline at end of file diff --git a/src/graphql-aspnet-subscriptions/Engine/TypeMakers/SubscriptionEnabledGraphFieldMaker.cs b/src/graphql-aspnet-subscriptions/Engine/TypeMakers/SubscriptionEnabledGraphFieldMaker.cs index 6f8fd48c7..3bf6b5009 100644 --- a/src/graphql-aspnet-subscriptions/Engine/TypeMakers/SubscriptionEnabledGraphFieldMaker.cs +++ b/src/graphql-aspnet-subscriptions/Engine/TypeMakers/SubscriptionEnabledGraphFieldMaker.cs @@ -39,15 +39,14 @@ public class SubscriptionEnabledGraphFieldMaker : GraphFieldMaker /// Initializes a new instance of the class. /// /// The schema instance to reference when creating fields. - /// The maker factory to create dependnet makers - /// if and when necessary. - public SubscriptionEnabledGraphFieldMaker(ISchema schema, IGraphQLTypeMakerFactory makerFactory) - : base(schema, makerFactory) + /// A maker that can make arguments declared on this field. + public SubscriptionEnabledGraphFieldMaker(ISchema schema, IGraphArgumentMaker argMaker) + : base(schema, argMaker) { } /// - protected override MethodGraphField InstantiateField( + protected override MethodGraphField CreateFieldInstance( GraphNameFormatter formatter, IGraphFieldTemplate template, List securityGroups) @@ -76,7 +75,7 @@ protected override MethodGraphField InstantiateField( directives); } - return base.InstantiateField(formatter, template, securityGroups); + return base.CreateFieldInstance(formatter, template, securityGroups); } } } \ No newline at end of file diff --git a/src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionControllerActionGraphFieldTemplate.cs b/src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionControllerActionGraphFieldTemplate.cs index 6f0917402..3d6efab44 100644 --- a/src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionControllerActionGraphFieldTemplate.cs +++ b/src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionControllerActionGraphFieldTemplate.cs @@ -121,7 +121,7 @@ public override void ValidateOrThrow() } // ensure there is only one param marked as the source object - var sourceArgument = this.Arguments.SingleOrDefault(x => x.ArgumentModifiers.HasFlag(GraphArgumentModifiers.ParentFieldResult)); + var sourceArgument = this.Arguments.SingleOrDefault(x => x.ArgumentModifier.HasFlag(GraphArgumentModifiers.ParentFieldResult)); if (sourceArgument == null) { throw new GraphTypeDeclarationException( diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Internals.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Internals.cs index 9e8687999..ca62af9a2 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Internals.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Internals.cs @@ -12,11 +12,9 @@ namespace GraphQL.AspNet.Configuration using System; using GraphQL.AspNet.Common; using GraphQL.AspNet.Execution; - using GraphQL.AspNet.Execution.Parsing; using GraphQL.AspNet.Execution.Parsing.Lexing.Tokens; using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; - using GraphQL.AspNet.Schemas.RuntimeSchemaItemDefinitions; - using GraphQL.AspNet.Schemas.Structural; + using GraphQL.AspNet.Schemas.Generation.RuntimeSchemaItemDefinitions; using GraphQL.AspNet.Schemas.TypeSystem; /// diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_VirtualFields.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_VirtualFields.cs index 3ad888a7a..19d1f4a19 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_VirtualFields.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_VirtualFields.cs @@ -10,13 +10,11 @@ namespace GraphQL.AspNet.Configuration { using System; - using System.Runtime.CompilerServices; using GraphQL.AspNet.Common; using GraphQL.AspNet.Execution; using GraphQL.AspNet.Interfaces.Configuration; - using GraphQL.AspNet.Interfaces.Controllers; using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; - using GraphQL.AspNet.Schemas.RuntimeSchemaItemDefinitions; + using GraphQL.AspNet.Schemas.Generation.RuntimeSchemaItemDefinitions; using Microsoft.AspNetCore.Authorization; /// diff --git a/src/graphql-aspnet/Configuration/SchemaArgumentBindingRules.cs b/src/graphql-aspnet/Configuration/SchemaArgumentBindingRules.cs index 3d470a2df..fe8e09ce9 100644 --- a/src/graphql-aspnet/Configuration/SchemaArgumentBindingRules.cs +++ b/src/graphql-aspnet/Configuration/SchemaArgumentBindingRules.cs @@ -42,7 +42,7 @@ public enum SchemaArgumentBindingRules /// Undecorated parameters WILL NOT be included as part of the schema. /// /// - ParametersRequireGraphQlDeclaration = 1, + ParametersRequireFromGraphQLDeclaration = 1, /// /// @@ -55,6 +55,6 @@ public enum SchemaArgumentBindingRules /// generated and the server failing to start. /// /// - ParametersRequireDiDeclaration = 2, + ParametersRequireFromServicesDeclaration = 2, } } \ No newline at end of file diff --git a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_GraphTypes.cs b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_GraphTypes.cs index 54dda36db..9585de7fc 100644 --- a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_GraphTypes.cs +++ b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_GraphTypes.cs @@ -103,6 +103,20 @@ protected virtual void EnsureGraphType(Type type, TypeKind? typeKind = null) } } + /// + /// Ensures the union proxy is incorporated into the schema appropriately. This method is used + /// when a union is discovered when parsing various field declarations. + /// + /// The union to include. + protected virtual void EnsureUnion(IGraphUnionProxy union) + { + Validation.ThrowIfNull(union, nameof(union)); + var maker = this.MakerFactory.CreateUnionMaker(); + var result = maker.CreateUnionFromProxy(union); + + this.Schema.KnownTypes.EnsureGraphType(result.GraphType, result.ConcreteType); + } + /// /// Ensures the dependents in the provided collection are part of the target . /// @@ -116,7 +130,10 @@ protected virtual void EnsureDependents(IGraphItemDependencies dependencySet) foreach (var dependent in dependencySet.DependentTypes) { - this.EnsureGraphType(dependent.Type, dependent.ExpectedKind); + if (dependent.Type != null) + this.EnsureGraphType(dependent.Type, dependent.ExpectedKind); + else if (dependent.UnionDeclaration != null) + this.EnsureUnion(dependent.UnionDeclaration); } } } diff --git a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Validation.cs b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Validation.cs index 4ef73245b..de6aff7ca 100644 --- a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Validation.cs +++ b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Validation.cs @@ -12,7 +12,7 @@ namespace GraphQL.AspNet.Engine using System; using System.Collections.Generic; using GraphQL.AspNet.Configuration; - using GraphQL.AspNet.Schemas.SchemaItemValidators; + using GraphQL.AspNet.Schemas.Generation.SchemaItemValidators; using GraphQL.AspNet.Schemas.TypeSystem; /// diff --git a/src/graphql-aspnet/Engine/DefaultGraphQLTypeMakerFactory.cs b/src/graphql-aspnet/Engine/DefaultGraphQLTypeMakerFactory.cs index d0f03f95b..780d528a8 100644 --- a/src/graphql-aspnet/Engine/DefaultGraphQLTypeMakerFactory.cs +++ b/src/graphql-aspnet/Engine/DefaultGraphQLTypeMakerFactory.cs @@ -76,7 +76,7 @@ public virtual IGraphTypeMaker CreateTypeMaker(Type objectType, TypeKind? kind = /// public virtual IGraphFieldMaker CreateFieldMaker() { - return new GraphFieldMaker(this.Schema, this); + return new GraphFieldMaker(this.Schema, this.CreateArgumentMaker()); } /// diff --git a/src/graphql-aspnet/Execution/ExecutionArgumentCollection.cs b/src/graphql-aspnet/Execution/ExecutionArgumentCollection.cs index e4a1a4725..6162d83f0 100644 --- a/src/graphql-aspnet/Execution/ExecutionArgumentCollection.cs +++ b/src/graphql-aspnet/Execution/ExecutionArgumentCollection.cs @@ -116,39 +116,6 @@ public object[] PrepareArguments(IGraphFieldResolverMetaData resolverMetadata) object passedValue = this.ResolveParameterValue(parameter); - bool schemaListItem; - if (parameter.ArgumentModifiers.IsPartOfTheSchema()) - { - // additional checks and coersion if this the value is - // being supplied from a query - var graphArgument = _fieldContext? - .Request - .Field - .Arguments - .FindArgumentByParameterName(parameter.InternalName); - - graphArgument = graphArgument ?? - _directiveContext? - .Request - .Directive - .Arguments - .FindArgumentByParameterName(parameter.InternalName); - - if (graphArgument == null) - throw new GraphExecutionException($"Argument '{parameter.InternalName}' was not found on its expected parent."); - - schemaListItem = graphArgument.TypeExpression.IsListOfItems; - if (passedValue == null && !graphArgument.TypeExpression.IsNullable) - { - // technically shouldn't be possible given the validation routines - // but captured here as a saftey net for users - // doing custom extensions or implementations - throw new GraphExecutionException( - $"The parameter '{parameter.InternalName}' for field '{_fieldContext?.Request?.Field?.Route.Path}' could not be resolved from the query document " + - "or variable collection and no default value was found."); - } - } - // ensure compatible list types between the internally // tracked data and the target type of the method being invoked // e.g. convert List => T[] when needed @@ -165,32 +132,87 @@ public object[] PrepareArguments(IGraphFieldResolverMetaData resolverMetadata) return preparedParams; } - private object ResolveParameterValue(IGraphFieldResolverParameterMetaData parameterDefinition) + private object ResolveParameterValue(IGraphFieldResolverParameterMetaData paramDef) { - if (parameterDefinition == null) - return null; + Validation.ThrowIfNull(paramDef, nameof(paramDef)); - if (parameterDefinition.ArgumentModifiers.IsSourceParameter()) + if (paramDef.ArgumentModifiers.IsSourceParameter()) return this.SourceData; - if (parameterDefinition.ArgumentModifiers.IsCancellationToken()) + if (paramDef.ArgumentModifiers.IsCancellationToken()) return _fieldContext?.CancellationToken ?? default; - if (parameterDefinition.ArgumentModifiers.IsInjected()) - { - if (_fieldContext != null) - return _fieldContext.ServiceProvider.GetService(parameterDefinition.ExpectedType); - - if (_directiveContext != null) - return _directiveContext.ServiceProvider.GetService(parameterDefinition.ExpectedType); + // if there an argument supplied on the query for this parameter, use that + if (this.TryGetValue(paramDef.InternalName, out var arg)) + return arg.Value; - return null; + // if the parameter is part of the graph, use the related argument's default value + if (paramDef.ArgumentModifiers.CouldBePartOfTheSchema()) + { + // additional checks and coersion if this the value is + // being supplied from a query + var graphArgument = _fieldContext? + .Request + .Field + .Arguments + .FindArgumentByParameterName(paramDef.InternalName); + + graphArgument = graphArgument ?? + _directiveContext? + .Request + .Directive + .Arguments + .FindArgumentByParameterName(paramDef.InternalName); + + if (graphArgument != null) + { + if (graphArgument.HasDefaultValue) + return graphArgument.DefaultValue; + + if (graphArgument.TypeExpression.IsNullable) + return null; + + // When an argument is found on the schema + // and no value was supplied on the query + // and that argument has no default value defined + // and that argument is not allowed to be null + // then error out + // + // This situation is technically not possible given the validation routines in place at runtime + // but captured here as a saftey net for users + // doing custom extensions or implementations + // this prevents resolver execution with indeterminate or unexpected data + var path = _fieldContext?.Request?.Field?.Route.Path ?? _directiveContext?.Request?.Directive?.Route.Path ?? "~unknown~"; + throw new GraphExecutionException( + $"The parameter '{paramDef.InternalName}' for schema item '{path}' could not be resolved from the query document " + + "or variable collection and no default value was found."); + } } - if (this.ContainsKey(parameterDefinition.InternalName)) - return this[parameterDefinition.InternalName].Value; - - return parameterDefinition.DefaultValue; + // its not a formal argument in the schema, try and resolve from DI container + object serviceResolvedValue = null; + if (_fieldContext != null) + serviceResolvedValue = _fieldContext.ServiceProvider?.GetService(paramDef.ExpectedType); + else if (_directiveContext != null) + serviceResolvedValue = _directiveContext.ServiceProvider?.GetService(paramDef.ExpectedType); + + // the service was found in the DI container!! *happy* + if (serviceResolvedValue != null) + return serviceResolvedValue; + + // it wasn't found but the developer declared a fall back. *thankful* + if (paramDef.HasDefaultValue) + return paramDef.DefaultValue; + + var schemaItem = _fieldContext?.Request.Field.Route.Path + ?? _directiveContext?.Request.Directive.Route.Path + ?? paramDef.InternalFullName; + + // error unable to resolve correctly. *womp womp* + throw new GraphExecutionException( + $"The parameter '{paramDef.InternalName}' targeting '{schemaItem}' was expected to be resolved from a " + + $"service provider but a suitable instance could not be obtained from the current invocation context " + + $"and no default value was declared."); } /// diff --git a/src/graphql-aspnet/Execution/Resolvers/FieldResolverParameterMetaData.cs b/src/graphql-aspnet/Execution/Resolvers/FieldResolverParameterMetaData.cs index 537817371..4e10ab26c 100644 --- a/src/graphql-aspnet/Execution/Resolvers/FieldResolverParameterMetaData.cs +++ b/src/graphql-aspnet/Execution/Resolvers/FieldResolverParameterMetaData.cs @@ -34,6 +34,7 @@ internal class FieldResolverParameterMetaData : IGraphFieldResolverParameterMeta /// at runtime by the target schema. /// if set to true this parameter is expecting a list /// of items to be passed to it at runtime. + /// if set to true this parameter was declared with an explicitly set default value. /// The default value assigned to this parameter in source code when the parameter /// was declared. public FieldResolverParameterMetaData( @@ -42,6 +43,7 @@ public FieldResolverParameterMetaData( string internalFullName, GraphArgumentModifiers modifiers, bool isListBasedParameter, + bool hasDefaultValue, object defaultValue = null) { this.ParameterInfo = Validation.ThrowIfNullOrReturn(paramInfo, nameof(paramInfo)); @@ -56,6 +58,7 @@ public FieldResolverParameterMetaData( this.InternalFullName = Validation.ThrowIfNullWhiteSpaceOrReturn(internalFullName, nameof(internalFullName)); this.DefaultValue = defaultValue; this.ArgumentModifiers = modifiers; + this.HasDefaultValue = hasDefaultValue; this.IsList = isListBasedParameter; } @@ -82,5 +85,8 @@ public FieldResolverParameterMetaData( /// public bool IsList { get; } + + /// + public bool HasDefaultValue { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverParameterMetaData.cs b/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverParameterMetaData.cs index 366f24f21..fc1aeaa88 100644 --- a/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverParameterMetaData.cs +++ b/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverParameterMetaData.cs @@ -75,6 +75,12 @@ public interface IGraphFieldResolverParameterMetaData /// The default value. object DefaultValue { get; } + /// + /// Gets a value indicating whether this instance has an explicitly declared default value + /// + /// true if this instance has an explicitly declared default value; otherwise, false. + bool HasDefaultValue { get; } + /// /// Gets a value indicating whether this parameter is expecting a list or collection of items. /// diff --git a/src/graphql-aspnet/Interfaces/Internal/IGraphArgumentTemplate.cs b/src/graphql-aspnet/Interfaces/Internal/IGraphArgumentTemplate.cs index 661b87197..804fd25b1 100644 --- a/src/graphql-aspnet/Interfaces/Internal/IGraphArgumentTemplate.cs +++ b/src/graphql-aspnet/Interfaces/Internal/IGraphArgumentTemplate.cs @@ -44,12 +44,11 @@ public interface IGraphArgumentTemplate : ISchemaItemTemplate GraphTypeExpression TypeExpression { get; } /// - /// Gets a value indicating that this argument represents the resolved data item created - /// by the resolution of the parent field to this field. If true, this argument will not be available - /// on the object graph. + /// Gets a value indicating what role this argument plays in a resolver, whether it be part of the schema, + /// a parent resolved data value, an injected value from a service provider etc. /// - /// true if this instance is source data field; otherwise, false. - GraphArgumentModifiers ArgumentModifiers { get; } + /// The argument modifier value applied to this parameter. + GraphArgumentModifiers ArgumentModifier { get; } /// /// Gets the name of the argument as its declared in the server side code. diff --git a/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/BaseRuntimeControllerActionDefinition.cs b/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/BaseRuntimeControllerActionDefinition.cs similarity index 98% rename from src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/BaseRuntimeControllerActionDefinition.cs rename to src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/BaseRuntimeControllerActionDefinition.cs index de5774975..2fb421f94 100644 --- a/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/BaseRuntimeControllerActionDefinition.cs +++ b/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/BaseRuntimeControllerActionDefinition.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Schemas.RuntimeSchemaItemDefinitions +namespace GraphQL.AspNet.Schemas.Generation.RuntimeSchemaItemDefinitions { using System; using System.Collections.Generic; diff --git a/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeDirectiveActionDefinition.cs b/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeDirectiveActionDefinition.cs similarity index 95% rename from src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeDirectiveActionDefinition.cs rename to src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeDirectiveActionDefinition.cs index ffee7a743..0c43b2e36 100644 --- a/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeDirectiveActionDefinition.cs +++ b/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeDirectiveActionDefinition.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Schemas.RuntimeSchemaItemDefinitions +namespace GraphQL.AspNet.Schemas.Generation.RuntimeSchemaItemDefinitions { using System; using System.Diagnostics; diff --git a/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeResolvedFieldDefinition.cs b/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeResolvedFieldDefinition.cs similarity index 96% rename from src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeResolvedFieldDefinition.cs rename to src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeResolvedFieldDefinition.cs index 18eeafdab..c97aa4bfd 100644 --- a/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeResolvedFieldDefinition.cs +++ b/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeResolvedFieldDefinition.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Schemas.RuntimeSchemaItemDefinitions +namespace GraphQL.AspNet.Schemas.Generation.RuntimeSchemaItemDefinitions { using System; using System.Diagnostics; @@ -66,7 +66,7 @@ public RuntimeResolvedFieldDefinition( SchemaOptions schemaOptions, SchemaItemCollections collection, string pathTemplate) - : base(schemaOptions, collection, pathTemplate) + : base(schemaOptions, collection, pathTemplate) { } diff --git a/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeTypeExtensionDefinition.cs b/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeTypeExtensionDefinition.cs similarity index 96% rename from src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeTypeExtensionDefinition.cs rename to src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeTypeExtensionDefinition.cs index 2e0cacd76..129613d0d 100644 --- a/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeTypeExtensionDefinition.cs +++ b/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeTypeExtensionDefinition.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Schemas.RuntimeSchemaItemDefinitions +namespace GraphQL.AspNet.Schemas.Generation.RuntimeSchemaItemDefinitions { using System; using System.Diagnostics; @@ -15,6 +15,7 @@ namespace GraphQL.AspNet.Schemas.RuntimeSchemaItemDefinitions using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Execution; using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; + using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; diff --git a/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeVirtualFieldTemplate.cs b/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeVirtualFieldTemplate.cs similarity index 96% rename from src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeVirtualFieldTemplate.cs rename to src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeVirtualFieldTemplate.cs index a9a2df9e7..24913b4e1 100644 --- a/src/graphql-aspnet/Schemas/RuntimeSchemaItemDefinitions/RuntimeVirtualFieldTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeVirtualFieldTemplate.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Schemas.RuntimeSchemaItemDefinitions +namespace GraphQL.AspNet.Schemas.Generation.RuntimeSchemaItemDefinitions { using System; using System.Diagnostics; diff --git a/src/graphql-aspnet/Schemas/SchemaItemValidators/BaseSchemaItemValidator.cs b/src/graphql-aspnet/Schemas/Generation/SchemaItemValidators/BaseSchemaItemValidator.cs similarity index 90% rename from src/graphql-aspnet/Schemas/SchemaItemValidators/BaseSchemaItemValidator.cs rename to src/graphql-aspnet/Schemas/Generation/SchemaItemValidators/BaseSchemaItemValidator.cs index f6d642b7f..8f4877656 100644 --- a/src/graphql-aspnet/Schemas/SchemaItemValidators/BaseSchemaItemValidator.cs +++ b/src/graphql-aspnet/Schemas/Generation/SchemaItemValidators/BaseSchemaItemValidator.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Schemas.SchemaItemValidators +namespace GraphQL.AspNet.Schemas.Generation.SchemaItemValidators { using GraphQL.AspNet.Interfaces.Schema; diff --git a/src/graphql-aspnet/Schemas/SchemaItemValidators/GraphArgumentValidator.cs b/src/graphql-aspnet/Schemas/Generation/SchemaItemValidators/GraphArgumentValidator.cs similarity index 64% rename from src/graphql-aspnet/Schemas/SchemaItemValidators/GraphArgumentValidator.cs rename to src/graphql-aspnet/Schemas/Generation/SchemaItemValidators/GraphArgumentValidator.cs index af9ed1dd3..0ab19bd29 100644 --- a/src/graphql-aspnet/Schemas/SchemaItemValidators/GraphArgumentValidator.cs +++ b/src/graphql-aspnet/Schemas/Generation/SchemaItemValidators/GraphArgumentValidator.cs @@ -7,9 +7,10 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Schemas.SchemaItemValidators +namespace GraphQL.AspNet.Schemas.Generation.SchemaItemValidators { using System; + using GraphQL.AspNet.Common; using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Interfaces.Schema; @@ -36,6 +37,9 @@ private GraphArgumentValidator() /// public override void ValidateOrThrow(ISchemaItem schemaItem, ISchema schema) { + Validation.ThrowIfNull(schemaItem, nameof(schemaItem)); + Validation.ThrowIfNull(schema, nameof(schema)); + var argument = schemaItem as IGraphArgument; if (argument == null) { @@ -44,12 +48,21 @@ public override void ValidateOrThrow(ISchemaItem schemaItem, ISchema schema) $"'{typeof(IGraphArgument).FriendlyName()}' but got '{schema?.GetType().FriendlyName() ?? "-none-"}'"); } - if (argument.ObjectType.IsInterface) + if (argument.ObjectType == null || argument.ObjectType.IsInterface) { throw new GraphTypeDeclarationException( - $"The argument '{argument.Name}' on '{argument.Parent.Route.Path}' is of type '{argument.ObjectType.FriendlyName()}', " + + $"The argument '{argument.Name}' on '{argument.Parent?.Route.Path ?? "~unknown~"}' is of type '{argument.ObjectType?.FriendlyName() ?? "~null~"}', " + $"which is an interface. Interfaces cannot be used as input arguments to any graph type."); } + + // the type MUST be in the schema + var foundItem = schema.KnownTypes.FindGraphType(argument.ObjectType, TypeSystem.TypeKind.INPUT_OBJECT); + if (foundItem == null) + { + throw new GraphTypeDeclarationException( + $"The argument '{argument.Name}' on '{argument.Parent?.Route.Path ?? "~unknown~"}' is declared as a {argument.ObjectType.FriendlyName()}, " + + $"which is not included in the schema as an acceptable input type (e.g. Scalar, Enum or Input Object). Ensure your type is included in the schema."); + } } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/SchemaItemValidators/GraphFieldValidator.cs b/src/graphql-aspnet/Schemas/Generation/SchemaItemValidators/GraphFieldValidator.cs similarity index 94% rename from src/graphql-aspnet/Schemas/SchemaItemValidators/GraphFieldValidator.cs rename to src/graphql-aspnet/Schemas/Generation/SchemaItemValidators/GraphFieldValidator.cs index 009ec2bbe..290f0029b 100644 --- a/src/graphql-aspnet/Schemas/SchemaItemValidators/GraphFieldValidator.cs +++ b/src/graphql-aspnet/Schemas/Generation/SchemaItemValidators/GraphFieldValidator.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Schemas.SchemaItemValidators +namespace GraphQL.AspNet.Schemas.Generation.SchemaItemValidators { using System; using GraphQL.AspNet.Interfaces.Schema; diff --git a/src/graphql-aspnet/Schemas/SchemaItemValidators/NoValidationSchemaItemValidator.cs b/src/graphql-aspnet/Schemas/Generation/SchemaItemValidators/NoValidationSchemaItemValidator.cs similarity index 94% rename from src/graphql-aspnet/Schemas/SchemaItemValidators/NoValidationSchemaItemValidator.cs rename to src/graphql-aspnet/Schemas/Generation/SchemaItemValidators/NoValidationSchemaItemValidator.cs index ac49b52ea..28371e1ca 100644 --- a/src/graphql-aspnet/Schemas/SchemaItemValidators/NoValidationSchemaItemValidator.cs +++ b/src/graphql-aspnet/Schemas/Generation/SchemaItemValidators/NoValidationSchemaItemValidator.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Schemas.SchemaItemValidators +namespace GraphQL.AspNet.Schemas.Generation.SchemaItemValidators { using GraphQL.AspNet.Interfaces.Schema; diff --git a/src/graphql-aspnet/Schemas/SchemaItemValidators/SchemaItemValidationFactory.cs b/src/graphql-aspnet/Schemas/Generation/SchemaItemValidators/SchemaItemValidationFactory.cs similarity index 94% rename from src/graphql-aspnet/Schemas/SchemaItemValidators/SchemaItemValidationFactory.cs rename to src/graphql-aspnet/Schemas/Generation/SchemaItemValidators/SchemaItemValidationFactory.cs index 5ef924f0a..22673a134 100644 --- a/src/graphql-aspnet/Schemas/SchemaItemValidators/SchemaItemValidationFactory.cs +++ b/src/graphql-aspnet/Schemas/Generation/SchemaItemValidators/SchemaItemValidationFactory.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Schemas.SchemaItemValidators; +namespace GraphQL.AspNet.Schemas.Generation.SchemaItemValidators; using GraphQL.AspNet.Interfaces.Schema; diff --git a/src/graphql-aspnet/Schemas/Generation/TypeMakers/DirectiveMaker.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/DirectiveMaker.cs index 8b9011f31..a0d218e4e 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeMakers/DirectiveMaker.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/DirectiveMaker.cs @@ -70,7 +70,7 @@ public virtual GraphTypeCreationResult CreateGraphType(IGraphTypeTemplate typeTe // can use any method to fill the arg field list foreach (var argTemplate in template.Arguments) { - if (argTemplate.ArgumentModifiers.IsPartOfTheSchema()) + if (argTemplate.ArgumentModifier.CouldBePartOfTheSchema()) { var argumentResult = _argMaker.CreateArgument(directive, argTemplate); directive.Arguments.AddArgument(argumentResult.Argument); diff --git a/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphArgumentMaker.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphArgumentMaker.cs index a3202bc53..7fabbf828 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphArgumentMaker.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphArgumentMaker.cs @@ -57,7 +57,8 @@ public GraphArgumentCreationResult CreateArgument(ISchemaItem owner, IGraphArgum else { // guess on what the name of the schema item will be - // this is guaranteed correct for all but scalars + // this is guaranteed correct for all but scalars and scalars should be + // added first schemaTypeName = GraphTypeNames.ParseName(template.ObjectType, TypeKind.INPUT_OBJECT); } diff --git a/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphFieldMaker.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphFieldMaker.cs index 1f652b683..092378338 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphFieldMaker.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphFieldMaker.cs @@ -11,20 +11,16 @@ namespace GraphQL.AspNet.Schemas.Generation.TypeMakers { using System; using System.Collections.Generic; - using System.Runtime.CompilerServices; - using System.Runtime.Serialization; using GraphQL.AspNet.Common; using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Common.Generics; using GraphQL.AspNet.Configuration.Formatting; - using GraphQL.AspNet.Execution.RulesEngine.RuleSets.DocumentValidation.FieldSelectionSteps; using GraphQL.AspNet.Interfaces.Configuration; using GraphQL.AspNet.Interfaces.Engine; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Schemas.TypeSystem.Scalars; using GraphQL.AspNet.Security; /// @@ -34,19 +30,18 @@ public class GraphFieldMaker : IGraphFieldMaker { private readonly ISchema _schema; private readonly ISchemaConfiguration _config; - private readonly IGraphQLTypeMakerFactory _makerFactory; + private readonly IGraphArgumentMaker _argMaker; /// /// Initializes a new instance of the class. /// /// The schema instance to reference when creating fields. - /// The maker factory to create dependnet makers - /// if and when necessary. - public GraphFieldMaker(ISchema schema, IGraphQLTypeMakerFactory makerFactory) + /// A maker that can make arguments declared on this field. + public GraphFieldMaker(ISchema schema, IGraphArgumentMaker argMaker) { _schema = Validation.ThrowIfNullOrReturn(schema, nameof(schema)); + _argMaker = Validation.ThrowIfNullOrReturn(argMaker, nameof(argMaker)); _config = _schema.Configuration; - _makerFactory = Validation.ThrowIfNullOrReturn(makerFactory, nameof(makerFactory)); } /// @@ -65,7 +60,7 @@ public virtual GraphFieldCreationResult CreateField(IGraphFieldTemp if (template.SecurityPolicies?.Count > 0) securityGroups.Add(template.SecurityPolicies); - MethodGraphField field = this.InstantiateField(formatter, template, securityGroups); + MethodGraphField field = this.CreateFieldInstance(formatter, template, securityGroups); field.Description = template.Description; field.Complexity = template.Complexity; @@ -73,12 +68,11 @@ public virtual GraphFieldCreationResult CreateField(IGraphFieldTemp if (template.Arguments != null && template.Arguments.Count > 0) { - var argMaker = _makerFactory.CreateArgumentMaker(); foreach (var argTemplate in template.Arguments) { - if (argTemplate.ArgumentModifiers.IsPartOfTheSchema()) + if (this.IsArgumentPartOfSchema(argTemplate)) { - var argumentResult = argMaker.CreateArgument(field, argTemplate); + var argumentResult = _argMaker.CreateArgument(field, argTemplate); field.Arguments.AddArgument(argumentResult.Argument); result.MergeDependents(argumentResult); @@ -87,22 +81,54 @@ public virtual GraphFieldCreationResult CreateField(IGraphFieldTemp } result.AddDependentRange(template.RetrieveRequiredTypes()); - if (template.UnionProxy != null) { - var unionMaker = _makerFactory.CreateUnionMaker(); - var unionResult = unionMaker.CreateUnionFromProxy(template.UnionProxy); - if (unionResult != null) - { - result.AddAbstractDependent(unionResult.GraphType); - result.MergeDependents(unionResult); - } + var dependentUnion = new DependentType(template.UnionProxy, TypeKind.UNION); + result.AddDependent(dependentUnion); } result.Field = field; return result; } + /// + public GraphFieldCreationResult CreateField(IInputGraphFieldTemplate template) + { + var formatter = _config.DeclarationOptions.GraphNamingFormatter; + + var defaultInputObject = InstanceFactory.CreateInstance(template.Parent.ObjectType); + var propGetters = InstanceFactory.CreatePropertyGetterInvokerCollection(template.Parent.ObjectType); + + object defaultValue = null; + + if (!template.IsRequired && propGetters.ContainsKey(template.InternalName)) + { + defaultValue = propGetters[template.InternalName](ref defaultInputObject); + } + + var result = new GraphFieldCreationResult(); + + var directives = template.CreateAppliedDirectives(); + + var field = new InputGraphField( + formatter.FormatFieldName(template.Name), + template.TypeExpression.CloneTo(formatter.FormatGraphTypeName(template.TypeExpression.TypeName)), + template.Route, + template.DeclaredName, + template.ObjectType, + template.DeclaredReturnType, + template.IsRequired, + defaultValue, + directives); + + field.Description = template.Description; + + result.AddDependentRange(template.RetrieveRequiredTypes()); + + result.Field = field; + return result; + } + /// /// Finds and applies proper casing to the graph type name returned by this field. /// @@ -158,7 +184,7 @@ protected virtual string PrepareTypeName(IGraphFieldTemplate template) /// The template. /// The security groups. /// MethodGraphField. - protected virtual MethodGraphField InstantiateField( + protected virtual MethodGraphField CreateFieldInstance( GraphNameFormatter formatter, IGraphFieldTemplate template, List securityGroups) @@ -202,42 +228,44 @@ protected virtual MethodGraphField InstantiateField( } } - /// - public GraphFieldCreationResult CreateField(IInputGraphFieldTemplate template) + /// + /// Determines whether the provided argument template should be included as part of the schema. + /// + /// The argument template to evaluate. + /// true if the template should be rendered into the schema; otherwise, false. + protected virtual bool IsArgumentPartOfSchema(IGraphArgumentTemplate argTemplate) { - var formatter = _config.DeclarationOptions.GraphNamingFormatter; + if (argTemplate.ArgumentModifier.IsExplicitlyPartOfTheSchema()) + return true; - var defaultInputObject = InstanceFactory.CreateInstance(template.Parent.ObjectType); - var propGetters = InstanceFactory.CreatePropertyGetterInvokerCollection(template.Parent.ObjectType); - - object defaultValue = null; + if (!argTemplate.ArgumentModifier.CouldBePartOfTheSchema()) + return false; - if (!template.IsRequired && propGetters.ContainsKey(template.InternalName)) + // teh argument contains no explicit inclusion or exclusion modifiers + // what do we do with it? + switch (_schema.Configuration.DeclarationOptions.ArgumentBindingRule) { - defaultValue = propGetters[template.InternalName](ref defaultInputObject); - } + case Configuration.SchemaArgumentBindingRules.ParametersRequireFromGraphQLDeclaration: - var result = new GraphFieldCreationResult(); + // arg didn't explicitly have [FromGraphQL] so it should NOT be part of the schema + return false; - var directives = template.CreateAppliedDirectives(); + case Configuration.SchemaArgumentBindingRules.ParametersRequireFromServicesDeclaration: - var field = new InputGraphField( - formatter.FormatFieldName(template.Name), - template.TypeExpression.CloneTo(formatter.FormatGraphTypeName(template.TypeExpression.TypeName)), - template.Route, - template.DeclaredName, - template.ObjectType, - template.DeclaredReturnType, - template.IsRequired, - defaultValue, - directives); + // arg didn't explicitly have [FromServices] so it should be part of the schema + return true; - field.Description = template.Description; + case Configuration.SchemaArgumentBindingRules.ParametersPreferQueryResolution: + default: - result.AddDependentRange(template.RetrieveRequiredTypes()); + // only exclude types that could never be correct as an input argument + // --- + // interfaces can never be valid input object types + if (argTemplate.ObjectType.IsInterface) + return false; - result.Field = field; - return result; + return true; + } } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/DependentType.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/DependentType.cs index a75242340..b50e9867d 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/DependentType.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/DependentType.cs @@ -13,6 +13,7 @@ namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates using System.Diagnostics; using GraphQL.AspNet.Common; using GraphQL.AspNet.Common.Extensions; + using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Schemas.TypeSystem; /// @@ -39,12 +40,29 @@ public DependentType(Type type, TypeKind expectedKind) this.ExpectedKind = expectedKind; } + /// + /// Initializes a new instance of the class. + /// + /// The union instance that needs to be turned into a graph type. + /// The expected kind. + public DependentType(IGraphUnionProxy union, TypeKind expectedKind) + { + this.UnionDeclaration = Validation.ThrowIfNullOrReturn(union, nameof(union)); + this.ExpectedKind = expectedKind; + } + /// /// Gets the dependent type this instance points to. /// /// The type. public Type Type { get; } + /// + /// Gets a union proxy that must be added to the schema. + /// + /// The union declaration. + public IGraphUnionProxy UnionDeclaration { get; } + /// /// Gets the expected type kind that the target should be /// instantiated as. diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphArgumentTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphArgumentTemplate.cs index 22e4c53f7..05d22b085 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphArgumentTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphArgumentTemplate.cs @@ -36,6 +36,7 @@ public class GraphArgumentTemplate : IGraphArgumentTemplate { private FromGraphQLAttribute _argDeclaration; private bool _invalidTypeExpression; + private HashSet _foundModifiers; /// /// Initializes a new instance of the class. @@ -48,6 +49,8 @@ public GraphArgumentTemplate(IGraphFieldTemplateBase parent, ParameterInfo param Validation.ThrowIfNull(parent, nameof(parent)); Validation.ThrowIfNull(parameter, nameof(parameter)); + _foundModifiers = new HashSet(); + this.Parent = parent; this.Parameter = parameter; } @@ -65,7 +68,7 @@ public virtual void Parse() if (_argDeclaration != null) { name = _argDeclaration?.ArgumentName?.Trim(); - this.ArgumentModifiers = GraphArgumentModifiers.ExplicitSchemaItem; + _foundModifiers.Add(GraphArgumentModifiers.ExplicitSchemaItem); } if (string.IsNullOrWhiteSpace(name)) @@ -75,7 +78,7 @@ public virtual void Parse() // to be consumed from a DI container var fromServicesAttrib = this.Parameter.SingleAttributeOfTypeOrDefault(); if (fromServicesAttrib != null) - this.ArgumentModifiers = GraphArgumentModifiers.ExplicitInjected; + _foundModifiers.Add(GraphArgumentModifiers.ExplicitInjected); name = name.Replace(Constants.Routing.PARAMETER_META_NAME, this.Parameter.Name); this.Route = new GraphArgumentFieldPath(this.Parent.Route, name); @@ -123,18 +126,14 @@ public virtual void Parse() this.TypeExpression = GraphTypeExpression.FromType(this.DeclaredArgumentType, this.DeclaredTypeWrappers); this.TypeExpression = this.TypeExpression.CloneTo(Constants.Other.DEFAULT_TYPE_EXPRESSION_TYPE_NAME); - // when this argument accepts the same data type as the data returned by its owners target source type - // i.e. if the source data supplied to the field for resolution is the same as this argument - // then assume this argument is to contain the source data - // since the source data will be an OBJECT type (not INPUT_OBJECT) there is no way the user could have supplied it if (this.IsSourceDataArgument()) - { - this.ArgumentModifiers = GraphArgumentModifiers.ParentFieldResult; - } - else if (this.IsCancellationTokenArgument()) - { - this.ArgumentModifiers = GraphArgumentModifiers.CancellationToken; - } + _foundModifiers.Add(GraphArgumentModifiers.ParentFieldResult); + + if (this.IsCancellationTokenArgument()) + _foundModifiers.Add(GraphArgumentModifiers.CancellationToken); + + if (_foundModifiers.Count == 1) + this.ArgumentModifier = _foundModifiers.First(); } /// @@ -144,12 +143,17 @@ public virtual void Parse() /// System.Boolean. protected virtual bool IsSourceDataArgument() { - if (this.Parent.Arguments.Any(x => x.ArgumentModifiers.HasFlag(GraphArgumentModifiers.ParentFieldResult))) + if (this.Parent.Arguments.Any(x => x.ArgumentModifier.HasFlag(GraphArgumentModifiers.ParentFieldResult))) return false; - if (this.ArgumentModifiers != GraphArgumentModifiers.None) + if (_foundModifiers.Count > 0) return false; + // when this argument accepts the same data type as the data returned by its owner's resolver + // i.e. if the source data supplied to the field for resolution is the same as this parameter + // then assume this argument is to contain the source data + // since the source data will be an OBJECT type (not INPUT_OBJECT) + // there is no way the user could have supplied it if (this.ObjectType == this.Parent.SourceObjectType) { var sourceType = this.ObjectType; @@ -173,7 +177,7 @@ protected virtual bool IsCancellationTokenArgument() { if (this.ObjectType == typeof(CancellationToken)) { - if (this.Parent.Arguments.All(x => !x.ArgumentModifiers.IsCancellationToken())) + if (this.Parent.Arguments.All(x => !x.ArgumentModifier.IsCancellationToken())) return true; } @@ -186,7 +190,7 @@ protected virtual bool IsCancellationTokenArgument() /// IEnumerable<Type>. public IEnumerable RetrieveRequiredTypes() { - if (this.ArgumentModifiers.IsNotPartOfTheSchema()) + if (!this.ArgumentModifier.CouldBePartOfTheSchema()) { // internal parameters should not be injected into the object graph // so they have no dependents @@ -217,7 +221,7 @@ public void ValidateOrThrow() if (_invalidTypeExpression) { throw new GraphTypeDeclarationException( - $"The item '{this.Parent.InternalFullName}' declares an argument '{this.Name}' that " + + $"The item '{this.Parent.InternalFullName}' declares a parameter '{this.Name}' that " + $"defines an invalid {nameof(FromGraphQLAttribute.TypeExpression)} (Value = '{_argDeclaration.TypeExpression}'). " + $"The provided type expression must be a valid query language type expression or null."); } @@ -231,20 +235,32 @@ public void ValidateOrThrow() if (!GraphTypeExpression.AreTypesCompatiable(actualTypeExpression, this.TypeExpression, false)) { throw new GraphTypeDeclarationException( - $"The item '{this.Parent.InternalFullName}' declares an argument '{this.Name}' that " + + $"The item '{this.Parent.InternalFullName}' declares a parameter '{this.Name}' that " + $"defines a {nameof(FromGraphQLAttribute.TypeExpression)} that is incompatiable with the " + $".NET parameter. (Declared '{this.TypeExpression}' is incompatiable with '{actualTypeExpression}') "); } - if (this.ArgumentModifiers.IsPartOfTheSchema() && this.ArgumentModifiers.IsInjected()) + // the most common scenario, throw an exception with explicit text + // on how to fix it + if (_foundModifiers.Contains(GraphArgumentModifiers.ExplicitInjected) + && _foundModifiers.Contains(GraphArgumentModifiers.ExplicitSchemaItem)) { throw new GraphTypeDeclarationException( - $"The item '{this.Parent.InternalFullName}' declares an argument '{this.Name}' that " + + $"The item '{this.Parent.InternalFullName}' declares a parameter '{this.Name}' that " + $"is defined to be supplied from a graphql query AND from a DI services container. " + $"An argument can not be supplied from a graphql query and from a DI container. If declaring argument attributes, supply " + $"{nameof(FromGraphQLAttribute)} or {nameof(FromServicesAttribute)}, but not both."); } + if (_foundModifiers.Count > 1) + { + var flags = string.Join(", ", _foundModifiers); + throw new GraphTypeDeclarationException( + $"The item '{this.Parent.InternalFullName}' declares a parameter '{this.Name}' that " + + $"is declares more than one behavior modification flag. Each parameter must declare only one" + + $"behavioral role within a given resolver method. Flags Declared: {flags}"); + } + foreach (var directive in this.AppliedDirectives) directive.ValidateOrThrow(); } @@ -253,7 +269,7 @@ public void ValidateOrThrow() public IGraphFieldResolverParameterMetaData CreateResolverMetaData() { var isValidList = this.TypeExpression.IsListOfItems; - if (!isValidList && this.ArgumentModifiers.IsSourceParameter()) + if (!isValidList && this.ArgumentModifier.IsSourceParameter()) { if (this.Parent is IGraphFieldTemplate gft) isValidList = gft.Mode == FieldResolutionMode.Batch; @@ -263,8 +279,9 @@ public IGraphFieldResolverParameterMetaData CreateResolverMetaData() this.Parameter, this.InternalName, this.InternalFullName, - this.ArgumentModifiers, + this.ArgumentModifier, isValidList, + this.HasDefaultValue, this.DefaultValue); } @@ -308,7 +325,7 @@ public IGraphFieldResolverParameterMetaData CreateResolverMetaData() public Type ObjectType { get; private set; } /// - public GraphArgumentModifiers ArgumentModifiers { get; protected set; } + public GraphArgumentModifiers ArgumentModifier { get; protected set; } /// public string ParameterName => this.Parameter.Name; diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/ScalarGraphTypeTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/ScalarGraphTypeTemplate.cs index 643d11531..5ef35648f 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/ScalarGraphTypeTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/ScalarGraphTypeTemplate.cs @@ -13,7 +13,6 @@ namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates using System.Collections.Generic; using System.Linq; using GraphQL.AspNet.Common; - using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Execution; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; diff --git a/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiers.cs b/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiers.cs index e879c3876..e71bb8003 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiers.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiers.cs @@ -12,13 +12,9 @@ namespace GraphQL.AspNet.Schemas.TypeSystem using System; /// - /// A set of modifiers and flags that can be assigned to individual arguments on graph fields to modify their behavior + /// A set of modifiers that can be assigned to individual arguments on graph fields to modify their behavior /// during execution. /// - /// - /// This enumeration was originally intended to be a bitwise flag but was changed with v2.0 was changed to be - /// a set of distinct values. The power of 2 increments was preserved for backwards compatiability. - /// public enum GraphArgumentModifiers { // implementation note, this used to be a [Flags] enum @@ -29,27 +25,24 @@ public enum GraphArgumentModifiers /// None = 0, - // The Value '1' was deprecated and removed. Its value will not be re-used - // to ensure no cross contamination of old code in referencing libraries. - /// /// This parameter is declared to contain the result of the value returned from the parent field's resolver. Applicable to /// type extension and batch extension action methods. /// - ParentFieldResult = 2, + ParentFieldResult, /// /// This parameter is declared to be a cancellation token /// governing the request or the default token if none was supplied on said request. /// - CancellationToken = 4, + CancellationToken, /// /// This parameter is declared to be resolved via dependency injection. It will NEVER be exposed /// on the object graph. If the type represented by this parameter is not servable via a scoped /// instance, an exception will occur and the target query will not be resolved. /// - ExplicitInjected = 8, + ExplicitInjected, /// /// This parameter is declared to be resolved as an argument to a graph field. It will ALWAYS be @@ -57,6 +50,6 @@ public enum GraphArgumentModifiers /// an exception will occur and the schema will fail to generate. This can occur, for instance, if it is an interface, /// or if the type was explicitly excluded from the graph via attributions. /// - ExplicitSchemaItem = 16, + ExplicitSchemaItem, } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiersExtensions.cs b/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiersExtensions.cs index f9b58d485..a98fa6fe6 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiersExtensions.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiersExtensions.cs @@ -18,68 +18,56 @@ public static class GraphArgumentModifiersExtensions /// /// Determines whether the modifers indicate the argument is to contain the source data value supplied to the resolver for the field. /// - /// The modifiers set to check. + /// The modifier set to check. /// true if the modifers set declares the parent field reslt modifer. - public static bool IsSourceParameter(this GraphArgumentModifiers modifiers) + public static bool IsSourceParameter(this GraphArgumentModifiers modifier) { - return modifiers.HasFlag(GraphArgumentModifiers.ParentFieldResult); + return modifier == GraphArgumentModifiers.ParentFieldResult; } /// /// Determines whether the modifers indicate the argument is a reference /// to the cancellation token governing the overall request. /// - /// The modifiers set to check. + /// The modifier set to check. /// true if the modifers set declares the internal modifer. - public static bool IsCancellationToken(this GraphArgumentModifiers modifiers) + public static bool IsCancellationToken(this GraphArgumentModifiers modifier) { - return modifiers.HasFlag(GraphArgumentModifiers.CancellationToken); + return modifier == GraphArgumentModifiers.CancellationToken; } /// - /// Determines whether the modifiers indicate that the argument is, for one reason or another, - /// not part of the externally exposed schema. This method cannot determine - /// what special type of argument is represented, only that it is special. - /// - /// The modifiers to check. - /// true if the modifiers indicate the argument is not part of the schema; otherwise, false. - public static bool IsNotPartOfTheSchema(this GraphArgumentModifiers modifiers) - { - return !modifiers.IsPartOfTheSchema(); - } - - /// - /// Determines whether the modifiers indicate that the argument is included in a + /// Determines whether the modifier indicate that the argument is included in a /// an externally exposed schema. /// - /// The modifiers to check. - /// true if the modifiers indicate the argument is part of the schema; otherwise, false. - public static bool IsPartOfTheSchema(this GraphArgumentModifiers modifiers) + /// The modifier to check. + /// true if the modifier indicate the argument is part of the schema; otherwise, false. + public static bool CouldBePartOfTheSchema(this GraphArgumentModifiers modifier) { - return modifiers == GraphArgumentModifiers.None - || modifiers.IsExplicitlyPartOfTheSchema(); + return modifier == GraphArgumentModifiers.None || + modifier.IsExplicitlyPartOfTheSchema(); } /// - /// Determines whether the modifiers indicate that the argument is explicitly declared that it MUST be included in a + /// Determines whether the modifier indicate that the argument is explicitly declared that it MUST be included in a /// an externally exposed schema. /// - /// The modifiers to check. - /// true if the modifiers indicate the argument is explicitly declared to be a part of the schema; otherwise, false. - public static bool IsExplicitlyPartOfTheSchema(this GraphArgumentModifiers modifiers) + /// The modifier to check. + /// true if the modifier indicate the argument is explicitly declared to be a part of the schema; otherwise, false. + public static bool IsExplicitlyPartOfTheSchema(this GraphArgumentModifiers modifier) { - return modifiers.HasFlag(GraphArgumentModifiers.ExplicitSchemaItem); + return modifier == GraphArgumentModifiers.ExplicitSchemaItem; } /// - /// Determines whether the modifiers indicate that the argument is to be resolved from a DI + /// Determines whether the modifier indicate that the argument is to be resolved from a DI /// container as opposed to being passed ona query /// - /// The modifiers to check. - /// true if the modifiers indicate the argument is to be resolved from a DI continer; otherwise, false. - public static bool IsInjected(this GraphArgumentModifiers modifiers) + /// The modifier to check. + /// true if the modifier indicate the argument is to be resolved from a DI continer; otherwise, false. + public static bool IsInjected(this GraphArgumentModifiers modifier) { - return modifiers.HasFlag(GraphArgumentModifiers.ExplicitInjected); + return modifier == GraphArgumentModifiers.ExplicitInjected; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/TypeSystem/SchemaExtensions.cs b/src/graphql-aspnet/Schemas/TypeSystem/SchemaExtensions.cs index c24886770..b3a1bf4d4 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/SchemaExtensions.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/SchemaExtensions.cs @@ -32,48 +32,44 @@ public static IEnumerable AllSchemaItems(this ISchema schema, bool // schema first yield return schema; - // all declared operations - foreach (var operationEntry in schema.Operations) - yield return operationEntry.Value; - // process each graph item except directives unless allowed var graphTypesToProcess = schema.KnownTypes.Where(x => - (includeDirectives || x.Kind != TypeKind.DIRECTIVE) - && !(x is IGraphOperation)); // dont let operations get included twice + (includeDirectives || x.Kind != TypeKind.DIRECTIVE)); foreach (var graphType in graphTypesToProcess) { yield return graphType; - if (graphType is IEnumGraphType enumType) - { - // each option on each enum - foreach (var option in enumType.Values) - yield return option.Value; - } - else if (graphType is IInputObjectGraphType inputObject) + switch (graphType) { - // each input field - foreach (var inputField in inputObject.Fields) - yield return inputField; - } - else if (graphType is IGraphFieldContainer fieldContainer) - { - // each field on OBJECT and INTERFACE graph type - foreach (var field in fieldContainer.Fields) - { - yield return field; + case IEnumGraphType enumType: + // each option on each enum + foreach (var option in enumType.Values) + yield return option.Value; + break; + + case IInputObjectGraphType inputObject: + foreach (var inputField in inputObject.Fields) + yield return inputField; + break; - // each argument on each field - foreach (var argument in field.Arguments) + // object graph types and interface graph types + case IGraphFieldContainer fieldContainer: + foreach (var field in fieldContainer.Fields) + { + yield return field; + + // each argument on each field + foreach (var argument in field.Arguments) + yield return argument; + } + + break; + + case IDirective directive: + foreach (var argument in directive.Arguments) yield return argument; - } - } - else if (graphType is IDirective directive) - { - // directive arguments - foreach (var argument in directive.Arguments) - yield return argument; + break; } } } diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/SubscriptionEnabledFieldFieldMakerTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/SubscriptionEnabledFieldFieldMakerTests.cs index 5e62a5ab5..677c2eecd 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/SubscriptionEnabledFieldFieldMakerTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/SubscriptionEnabledFieldFieldMakerTests.cs @@ -21,6 +21,7 @@ namespace GraphQL.AspNet.Tests.Engine using GraphQL.AspNet.Schemas.Generation; using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Engine; + using GraphQL.AspNet.Schemas.Generation.TypeMakers; [TestFixture] public class SubscriptionEnabledFieldFieldMakerTests @@ -42,10 +43,7 @@ public void SubscriptionActionField_TransfersDirectives() var schema = new TestServerBuilder().Build().Schema; - var factory = new SubscriptionEnabledGraphQLTypeMakerFactory(); - factory.Initialize(schema); - - var maker = new SubscriptionEnabledGraphFieldMaker(schema, factory); + var maker = new SubscriptionEnabledGraphFieldMaker(schema, new GraphArgumentMaker(schema)); var field = maker.CreateField(actionTemplate).Field; diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/GraphActionTemplateTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/GraphActionTemplateTests.cs index 68565ac88..41afa1372 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/GraphActionTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/GraphActionTemplateTests.cs @@ -80,7 +80,7 @@ public void ActionTemplate_Parse_ParameterSameAsReturnTypeIsMarkedSource() var action = this.CreateActionTemplate(nameof(SubscriptionMethodController.SingleMethod)); Assert.AreEqual(1, action.Arguments.Count); - Assert.IsTrue(action.Arguments[0].ArgumentModifiers.HasFlag(GraphArgumentModifiers.ParentFieldResult)); + Assert.IsTrue(action.Arguments[0].ArgumentModifier.HasFlag(GraphArgumentModifiers.ParentFieldResult)); } [Test] @@ -89,7 +89,7 @@ public void ActionTemplate_Parse_ExplicitlyDeclaredSourceIsAttributedCorrectly() var action = this.CreateActionTemplate(nameof(SubscriptionMethodController.ExplicitSourceReference)); Assert.AreEqual(1, action.Arguments.Count); - Assert.IsTrue(action.Arguments[0].ArgumentModifiers.HasFlag(GraphArgumentModifiers.ParentFieldResult)); + Assert.IsTrue(action.Arguments[0].ArgumentModifier.HasFlag(GraphArgumentModifiers.ParentFieldResult)); } [Test] @@ -99,7 +99,7 @@ public void ActionTemplate_Parse_ExplicitlyDeclaredSourceIsAttributedCorrectly_W Assert.AreEqual(2, action.Arguments.Count); - var sourceDataParam = action.Arguments.SingleOrDefault(x => x.ArgumentModifiers.HasFlag(GraphArgumentModifiers.ParentFieldResult)); + var sourceDataParam = action.Arguments.SingleOrDefault(x => x.ArgumentModifier.HasFlag(GraphArgumentModifiers.ParentFieldResult)); Assert.IsNotNull(sourceDataParam); Assert.AreEqual(typeof(TwoPropertyObjectV2), sourceDataParam.DeclaredArgumentType); } @@ -111,7 +111,7 @@ public void ActionTemplate_Parse_ExplicitlyDeclaredSourceIsAttributedCorrectly_W Assert.AreEqual(2, action.Arguments.Count); - var sourceDataParam = action.Arguments.SingleOrDefault(x => x.ArgumentModifiers.HasFlag(GraphArgumentModifiers.ParentFieldResult)); + var sourceDataParam = action.Arguments.SingleOrDefault(x => x.ArgumentModifier.HasFlag(GraphArgumentModifiers.ParentFieldResult)); Assert.IsNotNull(sourceDataParam); Assert.AreEqual(typeof(TwoPropertyObjectV2), sourceDataParam.DeclaredArgumentType); } diff --git a/src/unit-tests/graphql-aspnet-testframework/TestServer.cs b/src/unit-tests/graphql-aspnet-testframework/TestServer.cs index 931ee0707..f67cd0d23 100644 --- a/src/unit-tests/graphql-aspnet-testframework/TestServer.cs +++ b/src/unit-tests/graphql-aspnet-testframework/TestServer.cs @@ -200,10 +200,7 @@ public virtual FieldContextBuilder CreateGraphTypeFieldContextBuilder(actionName); - var factory = new DefaultGraphQLTypeMakerFactory(); - factory.Initialize(this.Schema); - - var fieldMaker = new GraphFieldMaker(this.Schema, factory); + var fieldMaker = new GraphFieldMaker(this.Schema, new GraphArgumentMaker(this.Schema)); var fieldResult = fieldMaker.CreateField(template); var builder = new FieldContextBuilder( diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/IInjectedService.cs b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/IInjectedService.cs new file mode 100644 index 000000000..a81acf224 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/IInjectedService.cs @@ -0,0 +1,15 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Engine.DefaultSchemaFactoryTestData +{ + public interface IInjectedService + { + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/SkippedType.cs b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/SkippedType.cs new file mode 100644 index 000000000..457826a82 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTestData/SkippedType.cs @@ -0,0 +1,20 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Engine.DefaultSchemaFactoryTestData +{ + using GraphQL.AspNet.Attributes; + + [GraphSkip] + [GraphType(PreventAutoInclusion = true)] + public class SkippedType + { + public int Prop1 { get; set; } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTests.cs b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTests.cs index c1c389b43..829404bef 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTests.cs @@ -11,8 +11,10 @@ namespace GraphQL.AspNet.Tests.Engine { using System; using System.Linq; + using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Engine; + using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Interfaces.Engine; using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Schemas; @@ -21,6 +23,7 @@ namespace GraphQL.AspNet.Tests.Engine using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Common.Interfaces; using GraphQL.AspNet.Tests.Engine.DefaultSchemaFactoryTestData; + using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; @@ -445,5 +448,130 @@ public void ReturnValueOfAField_ThatIsRegisteredAsAScalar_IsNamedProperly() // not the name as if it was an input object Assert.AreEqual(nameof(TwoPropertyObjectAsScalar), field.TypeExpression.TypeName); } + + [Test] + public void SimpleRuntimeField_NoArguments_IsMappedCorrectly() + { + var collection = this.SetupCollection(); + + var factory = new DefaultGraphQLSchemaFactory(includeBuiltInDirectives: false); + var options = new SchemaOptions(collection); + options.DeclarationOptions.DisableIntrospection = true; + + options.MapQuery("field1", () => 0); + + var provider = collection.BuildServiceProvider(); + var scope = provider.CreateScope(); + var config = options.CreateConfiguration(); + + var instance = factory.CreateInstance( + scope, + config, + runtimeItemDefinitions: options.RuntimeTemplates); + + Assert.IsNotNull(instance); + + // the root query object should contain the field + var query = instance.Operations[GraphOperationType.Query]; + + // field1 & __typename + Assert.AreEqual(2, query.Fields.Count); + Assert.IsNotNull(query.Fields["field1"]); + } + + [Test] + public void SimpleRuntimeField_OneExplicitSchemaArgument_IsMappedCorrectly() + { + var collection = this.SetupCollection(); + + var factory = new DefaultGraphQLSchemaFactory(includeBuiltInDirectives: false); + var options = new SchemaOptions(collection); + options.DeclarationOptions.DisableIntrospection = true; + + options.MapQuery("field1", (string arg1) => 0); + + var provider = collection.BuildServiceProvider(); + var scope = provider.CreateScope(); + var config = options.CreateConfiguration(); + + var instance = factory.CreateInstance( + scope, + config, + runtimeItemDefinitions: options.RuntimeTemplates); + + Assert.IsNotNull(instance); + + // the root query object should contain the field + var query = instance.Operations[GraphOperationType.Query]; + + // field1 & __typename + Assert.AreEqual(2, query.Fields.Count); + + var field = query.Fields["field1"]; + Assert.IsNotNull(field); + Assert.AreEqual(1, field.Arguments.Count); + Assert.IsNotNull(field.Arguments["arg1"]); + Assert.AreEqual(typeof(string), field.Arguments["arg1"].ObjectType); + } + + [Test] + public void SimpleRuntimeField_OneExplicitServiceArgument_IsMappedCorrectly() + { + var collection = this.SetupCollection(); + + var factory = new DefaultGraphQLSchemaFactory(includeBuiltInDirectives: false); + var options = new SchemaOptions(collection); + options.DeclarationOptions.DisableIntrospection = true; + + options.MapQuery("field1", ([FromServices] IInjectedService service) => 0); + + var provider = collection.BuildServiceProvider(); + var scope = provider.CreateScope(); + var config = options.CreateConfiguration(); + + var instance = factory.CreateInstance( + scope, + config, + runtimeItemDefinitions: options.RuntimeTemplates); + + Assert.IsNotNull(instance); + + // the root query object should contain the field + var query = instance.Operations[GraphOperationType.Query]; + + // field1 & __typename + Assert.AreEqual(2, query.Fields.Count); + + var field = query.Fields["field1"]; + Assert.IsNotNull(field); + + // no argument should be registered to the schema + Assert.AreEqual(0, field.Arguments.Count); + } + + [Test] + public void SchemaItemValidators_AreInvoked() + { + var collection = this.SetupCollection(); + + var factory = new DefaultGraphQLSchemaFactory(includeBuiltInDirectives: false); + var options = new SchemaOptions(collection); + options.DeclarationOptions.DisableIntrospection = true; + + // incorrect explicit schema item, enforced by runtime argument validator + options.MapQuery("field1", ([FromGraphQL] IInjectedService service) => 0); + + var provider = collection.BuildServiceProvider(); + var scope = provider.CreateScope(); + var config = options.CreateConfiguration(); + + Assert.Throws(() => + { + var instance = factory.CreateInstance( + scope, + config, + runtimeItemDefinitions: options.RuntimeTemplates); + }); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/ExecutionArgumentTestData/IServiceForExecutionArgumentTest.cs b/src/unit-tests/graphql-aspnet-tests/Execution/ExecutionArgumentTestData/IServiceForExecutionArgumentTest.cs new file mode 100644 index 000000000..ed3bbb6a9 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Execution/ExecutionArgumentTestData/IServiceForExecutionArgumentTest.cs @@ -0,0 +1,16 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Execution.ExecutionArgumentTestData +{ + public interface IServiceForExecutionArgumentTest + { + int ServiceValue { get; } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/ExecutionArgumentTestData/ObjectWithFields.cs b/src/unit-tests/graphql-aspnet-tests/Execution/ExecutionArgumentTestData/ObjectWithFields.cs new file mode 100644 index 000000000..3453d04ed --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Execution/ExecutionArgumentTestData/ObjectWithFields.cs @@ -0,0 +1,47 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Execution.ExecutionArgumentTestData +{ + using GraphQL.AspNet.Attributes; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + + public class ObjectWithFields + { + [GraphField] + public int FieldWithInjectedArgument(IServiceForExecutionArgumentTest arg1) + { + return arg1.ServiceValue; + } + + [GraphField] + public int FieldWithInjectedArgumentWithDefaultValue(IServiceForExecutionArgumentTest arg1 = null) + { + return 33; + } + + [GraphField] + public int FieldWithNullableSchemaArgument(TwoPropertyObject obj) + { + return 33; + } + + [GraphField] + public int FieldWithNonNullableSchemaArgumentThatHasDefaultValue(int arg1 = 3) + { + return 33; + } + + [GraphField] + public int FieldWithNotNullableQueryArgument(int arg1) + { + return 33; + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/ExecutionArgumentTestData/ServiceForExecutionArgumentTest.cs b/src/unit-tests/graphql-aspnet-tests/Execution/ExecutionArgumentTestData/ServiceForExecutionArgumentTest.cs new file mode 100644 index 000000000..bc5092361 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Execution/ExecutionArgumentTestData/ServiceForExecutionArgumentTest.cs @@ -0,0 +1,21 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Execution.ExecutionArgumentTestData +{ + public class ServiceForExecutionArgumentTest : IServiceForExecutionArgumentTest + { + public ServiceForExecutionArgumentTest() + { + this.ServiceValue = 99; + } + + public int ServiceValue { get; } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/ExecutionArgumentTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/ExecutionArgumentTests.cs index 2441d6529..5be15eed7 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/ExecutionArgumentTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/ExecutionArgumentTests.cs @@ -9,8 +9,17 @@ namespace GraphQL.AspNet.Tests.Execution { + using System.Linq; + using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Execution; + using GraphQL.AspNet.Execution.Exceptions; + using GraphQL.AspNet.Execution.RulesEngine.RuleSets.DocumentValidation.QueryFragmentSteps; + using GraphQL.AspNet.Interfaces.Execution; using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; + using GraphQL.AspNet.Tests.Execution.ExecutionArgumentTestData; + using GraphQL.AspNet.Tests.Framework; + using Microsoft.Extensions.DependencyInjection; using Moq; using NUnit.Framework; @@ -57,5 +66,243 @@ public void TryGetArgument_WhenArgDoesntCast_FailsWithResponse() Assert.IsFalse(success); Assert.AreEqual(0, value); // default of int } + + [Test] + public void PrepareArguments_WhenArgumentShouldComeFromDI_AndExistsInDI_IsPreparedCorrectly() + { + var serviceInstance = new ServiceForExecutionArgumentTest(); + + var builder = new TestServerBuilder(TestOptions.UseCodeDeclaredNames); + builder.AddGraphQL(o => + { + o.AddType(); + o.DeclarationOptions.ArgumentBindingRule = SchemaArgumentBindingRules.ParametersPreferQueryResolution; + }); + builder.AddSingleton(serviceInstance); + + var testServer = builder.Build(); + + var template = new ObjectGraphTypeTemplate(typeof(ObjectWithFields)); + template.Parse(); + template.ValidateOrThrow(); + + var fieldMetadata = template + .FieldTemplates + .Values + .FirstOrDefault(x => x.InternalName == nameof(ObjectWithFields.FieldWithInjectedArgument)) + .CreateResolverMetaData(); + + var context = testServer.CreateFieldExecutionContext( + nameof(ObjectWithFields.FieldWithInjectedArgument), + new ObjectWithFields()); + + // mimic a situation where no values are parsed from a query (no execution args) + var argSet = new ExecutionArgumentCollection() as IExecutionArgumentCollection; + argSet = argSet.ForContext(context); + + var resolvedArgs = argSet.PrepareArguments(fieldMetadata); + + Assert.IsNotNull(resolvedArgs); + Assert.AreEqual(1, resolvedArgs.Length); + Assert.AreEqual(resolvedArgs[0], serviceInstance); + } + + [Test] + public void PrepareArguments_WhenArgumentShouldComeFromDI_AndDoesNotExistInDI_AndHasNoDefaultValue_ExecutionExceptionIsThrown() + { + var serviceInstance = new ServiceForExecutionArgumentTest(); + + var builder = new TestServerBuilder(TestOptions.UseCodeDeclaredNames); + builder.AddGraphQL(o => + { + o.AddType(); + o.DeclarationOptions.ArgumentBindingRule = SchemaArgumentBindingRules.ParametersPreferQueryResolution; + }); + + var testServer = builder.Build(); + + var template = new ObjectGraphTypeTemplate(typeof(ObjectWithFields)); + template.Parse(); + template.ValidateOrThrow(); + + var fieldMetadata = template + .FieldTemplates + .Values + .FirstOrDefault(x => x.InternalName == nameof(ObjectWithFields.FieldWithInjectedArgument)) + .CreateResolverMetaData(); + + var context = testServer.CreateFieldExecutionContext( + nameof(ObjectWithFields.FieldWithInjectedArgument), + new ObjectWithFields()); + + // mimic a situation where no values are parsed from a query (no execution args) + // and no default value is present + var argSet = new ExecutionArgumentCollection() as IExecutionArgumentCollection; + argSet = argSet.ForContext(context); + + Assert.Throws(() => + { + var resolvedArgs = argSet.PrepareArguments(fieldMetadata); + }); + } + + [Test] + public void PrepareArguments_WhenArgumentShouldComeFromDI_AndDoesNotExistInDI_AndHasADefaultValue_ValueIsResolved() + { + var serviceInstance = new ServiceForExecutionArgumentTest(); + + var builder = new TestServerBuilder(TestOptions.UseCodeDeclaredNames); + builder.AddGraphQL(o => + { + o.AddType(); + o.DeclarationOptions.ArgumentBindingRule = SchemaArgumentBindingRules.ParametersPreferQueryResolution; + }); + + var testServer = builder.Build(); + + var template = new ObjectGraphTypeTemplate(typeof(ObjectWithFields)); + template.Parse(); + template.ValidateOrThrow(); + + var fieldMetadata = template + .FieldTemplates + .Values + .FirstOrDefault(x => x.InternalName == nameof(ObjectWithFields.FieldWithInjectedArgumentWithDefaultValue)) + .CreateResolverMetaData(); + + var context = testServer.CreateFieldExecutionContext( + nameof(ObjectWithFields.FieldWithInjectedArgumentWithDefaultValue), + new ObjectWithFields()); + + // mimic a situation where no values are parsed from a query (no execution args) + // and nothing is available from DI + // but the parameter declares a default value + var argSet = new ExecutionArgumentCollection() as IExecutionArgumentCollection; + argSet = argSet.ForContext(context); + + var resolvedArgs = argSet.PrepareArguments(fieldMetadata); + Assert.IsNotNull(resolvedArgs); + Assert.AreEqual(1, resolvedArgs.Length); + Assert.IsNull(resolvedArgs[0]); + } + + [Test] + public void PrepareArguments_WhenArgumentShouldComeFromSchema_HasNoSuppliedValueHasNoDefaultValueIsNullable_ValueIsResolved() + { + var serviceInstance = new ServiceForExecutionArgumentTest(); + + var builder = new TestServerBuilder(TestOptions.UseCodeDeclaredNames); + builder.AddGraphQL(o => + { + o.AddType(); + o.DeclarationOptions.ArgumentBindingRule = SchemaArgumentBindingRules.ParametersPreferQueryResolution; + }); + + var testServer = builder.Build(); + + var template = new ObjectGraphTypeTemplate(typeof(ObjectWithFields)); + template.Parse(); + template.ValidateOrThrow(); + + var fieldMetadata = template + .FieldTemplates + .Values + .FirstOrDefault(x => x.InternalName == nameof(ObjectWithFields.FieldWithNullableSchemaArgument)) + .CreateResolverMetaData(); + + var context = testServer.CreateFieldExecutionContext( + nameof(ObjectWithFields.FieldWithNullableSchemaArgument), + new ObjectWithFields()); + + // mimic a situation where no values are parsed from a query (no execution args) + // and nothing is available from DI + // but the parameter declares a default value + var argSet = new ExecutionArgumentCollection() as IExecutionArgumentCollection; + argSet = argSet.ForContext(context); + + var resolvedArgs = argSet.PrepareArguments(fieldMetadata); + Assert.IsNotNull(resolvedArgs); + Assert.AreEqual(1, resolvedArgs.Length); + Assert.IsNull(resolvedArgs[0]); + } + + [Test] + public void PrepareArguments_WhenArgumentShouldComeFromSchema_HasNoSuppliedValueAndIsNotNullableHasDefaultValue_ValueIsResolved() + { + var serviceInstance = new ServiceForExecutionArgumentTest(); + + var builder = new TestServerBuilder(TestOptions.UseCodeDeclaredNames); + builder.AddGraphQL(o => + { + o.AddType(); + o.DeclarationOptions.ArgumentBindingRule = SchemaArgumentBindingRules.ParametersPreferQueryResolution; + }); + + var testServer = builder.Build(); + + var template = new ObjectGraphTypeTemplate(typeof(ObjectWithFields)); + template.Parse(); + template.ValidateOrThrow(); + + var fieldMetadata = template + .FieldTemplates + .Values + .FirstOrDefault(x => x.InternalName == nameof(ObjectWithFields.FieldWithNonNullableSchemaArgumentThatHasDefaultValue)) + .CreateResolverMetaData(); + + var context = testServer.CreateFieldExecutionContext( + nameof(ObjectWithFields.FieldWithNonNullableSchemaArgumentThatHasDefaultValue), + new ObjectWithFields()); + + // mimic a situation where no values are parsed from a query (no execution args) + // and nothing is available from DI + // but the parameter declares a default value + var argSet = new ExecutionArgumentCollection() as IExecutionArgumentCollection; + argSet = argSet.ForContext(context); + + var resolvedArgs = argSet.PrepareArguments(fieldMetadata); + Assert.IsNotNull(resolvedArgs); + Assert.AreEqual(1, resolvedArgs.Length); + Assert.AreEqual(3, resolvedArgs[0]); + } + + [Test] + public void PrepareArguments_WhenArgumentShouldComeFromQuery_AndIsNotSupplied_AndIsNotNullable_ExecutionExceptionOccurs() + { + var serviceInstance = new ServiceForExecutionArgumentTest(); + + var builder = new TestServerBuilder(TestOptions.UseCodeDeclaredNames); + builder.AddGraphQL(o => + { + o.AddType(); + o.DeclarationOptions.ArgumentBindingRule = SchemaArgumentBindingRules.ParametersPreferQueryResolution; + }); + + var testServer = builder.Build(); + + var template = new ObjectGraphTypeTemplate(typeof(ObjectWithFields)); + template.Parse(); + template.ValidateOrThrow(); + + var fieldMetadata = template + .FieldTemplates + .Values + .FirstOrDefault(x => x.InternalName == nameof(ObjectWithFields.FieldWithNotNullableQueryArgument)) + .CreateResolverMetaData(); + + var context = testServer.CreateFieldExecutionContext( + nameof(ObjectWithFields.FieldWithNotNullableQueryArgument), + new ObjectWithFields()); + + // mimic a situation where no values are parsed from a query (no execution args) + // but the argument expected there to be + var argSet = new ExecutionArgumentCollection() as IExecutionArgumentCollection; + argSet = argSet.ForContext(context); + + Assert.Throws(() => + { + var resolvedArgs = argSet.PrepareArguments(fieldMetadata); + }); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionRuntimeFieldTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionRuntimeFieldTests.cs index f1993a2ec..548e23eaf 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionRuntimeFieldTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionRuntimeFieldTests.cs @@ -353,6 +353,8 @@ public async Task BasicMappedQuery_WithImplicitlyDeclaredInjectedService_Returni serverBuilder.AddGraphQL(o => { + o.DeclarationOptions.ArgumentBindingRule = SchemaArgumentBindingRules.ParametersPreferQueryResolution; + o.MapQuery("/field1/field2") .AddResolver((int a, int b, IInjectedService injectedService) => { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/SchemaItemValidators/GraphArgumentValidatorTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/SchemaItemValidators/GraphArgumentValidatorTests.cs new file mode 100644 index 000000000..04c522cd9 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/SchemaItemValidators/GraphArgumentValidatorTests.cs @@ -0,0 +1,86 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.Generation.SchemaItemValidators +{ + using System; + using GraphQL.AspNet.Execution.Exceptions; + using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Schemas.Generation.SchemaItemValidators; + using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + using GraphQL.AspNet.Tests.Common.Interfaces; + using Moq; + using NUnit.Framework; + + [TestFixture] + public class GraphArgumentValidatorTests + { + private enum EnumNotInSchema + { + value1, + Value2, + } + + [Test] + public void NullArgument_ThrowsCastException() + { + var validator = GraphArgumentValidator.Instance; + + var item = new Mock(); + var schema = new GraphSchema(); + + Assert.Throws(() => + { + validator.ValidateOrThrow(item.Object, schema); + }); + } + + [Test] + public void ObjectTypeIsInterface_ThrowsDeclarationException() + { + var validator = GraphArgumentValidator.Instance; + + var item = new Mock(); + item.Setup(x => x.ObjectType).Returns(typeof(ISinglePropertyObject)); + + var schema = new GraphSchema(); + Assert.Throws(() => + { + validator.ValidateOrThrow(item.Object, schema); + }); + } + + [Test] + public void ObjectTypeIsNotInSchema_ThrowsDeclarationException() + { + var validator = GraphArgumentValidator.Instance; + + var item = new Mock(); + item.Setup(x => x.ObjectType).Returns(typeof(TwoPropertyObject)); + item.Setup(x => x.Name).Returns("theName"); + + var schema = new Mock(); + var typesCollection = new Mock(); + + // the tested type is not found + typesCollection + .Setup(x => x.FindGraphType(It.IsAny(), It.IsAny())) + .Returns(null as IGraphType); + + schema.Setup(x => x.KnownTypes).Returns(typesCollection.Object); + + Assert.Throws(() => + { + validator.ValidateOrThrow(item.Object, schema.Object); + }); + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/FieldMaker_InputFieldTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/FieldMaker_InputFieldTests.cs index f0e13757a..051311d1a 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/FieldMaker_InputFieldTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/FieldMaker_InputFieldTests.cs @@ -10,11 +10,8 @@ namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers { using System.Linq; - using GraphQL.AspNet.Schemas; - using GraphQL.AspNet.Schemas.Generation; using GraphQL.AspNet.Schemas.Generation.TypeMakers; using GraphQL.AspNet.Tests.Common.CommonHelpers; - using GraphQL.AspNet.Tests.CommonHelpers; using GraphQL.AspNet.Tests.Framework; using GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData; using NUnit.Framework; @@ -32,9 +29,7 @@ public void Parse_NotRequiredValueTypePropertyCheck() .Values .Single(x => x.Name == nameof(InputTestObject.NotRequiredValueTypeField)); - var factory = server.CreateMakerFactory(); - - var graphField = new GraphFieldMaker(server.Schema, factory).CreateField(fieldTemplate).Field; + var graphField = new GraphFieldMaker(server.Schema, new GraphArgumentMaker(server.Schema)).CreateField(fieldTemplate).Field; Assert.AreEqual("notRequiredValueTypeField", graphField.Name); Assert.IsFalse(graphField.IsRequired); @@ -61,9 +56,7 @@ public void Parse_RequiredValueTypePropertyCheck() .Values .Single(x => x.Name == nameof(InputTestObject.RequiredValueTypeField)); - var factory = server.CreateMakerFactory(); - - var graphField = new GraphFieldMaker(server.Schema, factory).CreateField(fieldTemplate).Field; + var graphField = new GraphFieldMaker(server.Schema, new GraphArgumentMaker(server.Schema)).CreateField(fieldTemplate).Field; Assert.AreEqual("requiredValueTypeField", graphField.Name); Assert.IsTrue(graphField.IsRequired); @@ -87,9 +80,7 @@ public void Parse_NotRequiredReferenceTypePropertyCheck() .Values .Single(x => x.Name == nameof(InputTestObject.NotRequiredReferenceTypeField)); - var factory = server.CreateMakerFactory(); - - var graphField = new GraphFieldMaker(server.Schema, factory).CreateField(fieldTemplate).Field; + var graphField = new GraphFieldMaker(server.Schema, new GraphArgumentMaker(server.Schema)).CreateField(fieldTemplate).Field; Assert.AreEqual("notRequiredReferenceTypeField", graphField.Name); Assert.IsFalse(graphField.IsRequired); @@ -115,9 +106,7 @@ public void Parse_RequiredReferenceTypePropertyCheck() .Values .Single(x => x.Name == nameof(InputTestObject.RequiredReferenceTypeField)); - var factory = server.CreateMakerFactory(); - - var graphField = new GraphFieldMaker(server.Schema, factory).CreateField(fieldTemplate).Field; + var graphField = new GraphFieldMaker(server.Schema, new GraphArgumentMaker(server.Schema)).CreateField(fieldTemplate).Field; Assert.AreEqual("requiredReferenceTypeField", graphField.Name); @@ -145,8 +134,7 @@ public void Parse_RequiredNonNullableReferenceTypePropertyCheck() .Values .Single(x => x.Name == nameof(InputTestObject.RequiredReferenceExplicitNonNullTypeField)); - var factory = server.CreateMakerFactory(); - var graphField = new GraphFieldMaker(server.Schema, factory).CreateField(fieldTemplate).Field; + var graphField = new GraphFieldMaker(server.Schema, new GraphArgumentMaker(server.Schema)).CreateField(fieldTemplate).Field; Assert.AreEqual("requiredReferenceExplicitNonNullTypeField", graphField.Name); Assert.IsTrue(graphField.IsRequired); @@ -172,9 +160,7 @@ public void Parse_RequiredGraphIdPropertyCheck() .Values .Single(x => x.Name == nameof(InputTestObject.GraphIdRequired)); - var factory = server.CreateMakerFactory(); - - var graphField = new GraphFieldMaker(server.Schema, factory).CreateField(fieldTemplate).Field; + var graphField = new GraphFieldMaker(server.Schema, new GraphArgumentMaker(server.Schema)).CreateField(fieldTemplate).Field; Assert.AreEqual("graphIdRequired", graphField.Name); Assert.IsTrue(graphField.IsRequired); @@ -199,9 +185,7 @@ public void Parse_NotRequiredGraphIdPropertyCheck() .Values .Single(x => x.Name == nameof(InputTestObject.GraphIdNotRequired)); - var factory = server.CreateMakerFactory(); - - var graphField = new GraphFieldMaker(server.Schema, factory).CreateField(fieldTemplate).Field; + var graphField = new GraphFieldMaker(server.Schema, new GraphArgumentMaker(server.Schema)).CreateField(fieldTemplate).Field; Assert.AreEqual("graphIdNotRequired", graphField.Name); Assert.IsFalse(graphField.IsRequired); @@ -225,9 +209,7 @@ public void Parse_NotRequiredNullableGraphIdPropertyCheck() .Values .Single(x => x.Name == nameof(InputTestObject.GraphIdNullable)); - var factory = server.CreateMakerFactory(); - - var graphField = new GraphFieldMaker(server.Schema, factory).CreateField(fieldTemplate).Field; + var graphField = new GraphFieldMaker(server.Schema, new GraphArgumentMaker(server.Schema)).CreateField(fieldTemplate).Field; Assert.AreEqual("graphIdNullable", graphField.Name); Assert.IsFalse(graphField.IsRequired); diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/FieldMaker_StandardFieldTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/FieldMaker_StandardFieldTests.cs index 6fbf46e09..3c7ad638f 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/FieldMaker_StandardFieldTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/FieldMaker_StandardFieldTests.cs @@ -10,6 +10,7 @@ namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers { using System.Linq; + using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Schemas.Generation; @@ -64,9 +65,7 @@ public void Parse_PolicyOnController_IsInheritedByField() Assert.AreEqual(1, template.SecurityPolicies.Count()); Assert.AreEqual(0, actionMethod.SecurityPolicies.Count()); - var factory = server.CreateMakerFactory(); - - var graphField = new GraphFieldMaker(server.Schema, factory).CreateField(actionMethod).Field; + var graphField = new GraphFieldMaker(server.Schema, new GraphArgumentMaker(server.Schema)).CreateField(actionMethod).Field; Assert.AreEqual(1, graphField.SecurityGroups.Count()); var group = graphField.SecurityGroups.First(); @@ -86,9 +85,7 @@ public void Parse_PolicyOnController_AndOnMethod_IsInheritedByField_InCorrectOrd Assert.AreEqual(1, template.SecurityPolicies.Count()); Assert.AreEqual(1, actionMethod.SecurityPolicies.Count()); - var factory = server.CreateMakerFactory(); - - var graphField = new GraphFieldMaker(server.Schema, factory).CreateField(actionMethod).Field; + var graphField = new GraphFieldMaker(server.Schema, new GraphArgumentMaker(server.Schema)).CreateField(actionMethod).Field; Assert.AreEqual(2, graphField.SecurityGroups.Count()); @@ -115,9 +112,7 @@ public void Parse_MethodWithNullableEnum_ParsesCorrectly() Assert.AreEqual(typeof(NullableEnumController.LengthType), arg.ObjectType); Assert.AreEqual(NullableEnumController.LengthType.Yards, arg.DefaultValue); - var factory = server.CreateMakerFactory(); - - var graphField = new GraphFieldMaker(server.Schema, factory).CreateField(field).Field; + var graphField = new GraphFieldMaker(server.Schema, new GraphArgumentMaker(server.Schema)).CreateField(field).Field; Assert.IsNotNull(graphField); var graphArg = graphField.Arguments.FirstOrDefault(); @@ -254,5 +249,86 @@ public void Arguments_DirectivesAreApplied() Assert.AreEqual(typeof(DirectiveWithArgs), appliedDirective.DirectiveType); CollectionAssert.AreEqual(new object[] { 15, "arg arg" }, appliedDirective.ArgumentValues); } + + [TestCase( + SchemaArgumentBindingRules.ParametersRequireFromServicesDeclaration, + nameof(ObjectWithAttributedFieldArguments.FieldWithExplicitServiceArg), + false)] + [TestCase( + SchemaArgumentBindingRules.ParametersRequireFromGraphQLDeclaration, + nameof(ObjectWithAttributedFieldArguments.FieldWithExplicitServiceArg), + false)] + [TestCase( + SchemaArgumentBindingRules.ParametersPreferQueryResolution, + nameof(ObjectWithAttributedFieldArguments.FieldWithExplicitServiceArg), + false)] + [TestCase( + SchemaArgumentBindingRules.ParametersRequireFromServicesDeclaration, + nameof(ObjectWithAttributedFieldArguments.FieldWithExplicitSchemArg), + true)] + [TestCase( + SchemaArgumentBindingRules.ParametersRequireFromGraphQLDeclaration, + nameof(ObjectWithAttributedFieldArguments.FieldWithExplicitSchemArg), + true)] + [TestCase( + SchemaArgumentBindingRules.ParametersPreferQueryResolution, + nameof(ObjectWithAttributedFieldArguments.FieldWithExplicitSchemArg), + true)] + [TestCase( + SchemaArgumentBindingRules.ParametersRequireFromServicesDeclaration, + nameof(ObjectWithAttributedFieldArguments.FieldWithImplicitArgThatShouldBeServiceInjected), + true)] + [TestCase( + SchemaArgumentBindingRules.ParametersRequireFromGraphQLDeclaration, + nameof(ObjectWithAttributedFieldArguments.FieldWithImplicitArgThatShouldBeServiceInjected), + false)] + [TestCase( + SchemaArgumentBindingRules.ParametersPreferQueryResolution, + nameof(ObjectWithAttributedFieldArguments.FieldWithImplicitArgThatShouldBeServiceInjected), + false)] + [TestCase( + SchemaArgumentBindingRules.ParametersRequireFromServicesDeclaration, + nameof(ObjectWithAttributedFieldArguments.FieldWithImplicitArgThatShouldBeInGraph), + true)] + [TestCase( + SchemaArgumentBindingRules.ParametersRequireFromGraphQLDeclaration, + nameof(ObjectWithAttributedFieldArguments.FieldWithImplicitArgThatShouldBeInGraph), + false)] + [TestCase( + SchemaArgumentBindingRules.ParametersPreferQueryResolution, + nameof(ObjectWithAttributedFieldArguments.FieldWithImplicitArgThatShouldBeInGraph), + true)] + public void Arguments_ArgumentBindingRuleTests(SchemaArgumentBindingRules bindingRule, string fieldName, bool argumentShouldBeIncluded) + { + var server = new TestServerBuilder() + .AddGraphQL(o => + { + o.DeclarationOptions.ArgumentBindingRule = bindingRule; + }) + .Build(); + + var obj = new Mock(); + obj.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/Item0")); + obj.Setup(x => x.InternalFullName).Returns("LongItem0"); + obj.Setup(x => x.InternalName).Returns("Item0"); + obj.Setup(x => x.ObjectType).Returns(typeof(ObjectWithAttributedFieldArguments)); + + var parent = obj.Object; + var methodInfo = typeof(ObjectWithAttributedFieldArguments).GetMethod(fieldName); + var template = new MethodGraphFieldTemplate(parent, methodInfo, TypeKind.OBJECT); + template.Parse(); + template.ValidateOrThrow(); + + // Fact: The field has no attributes on it but could be included in the schema. + // Fact: The schema is defined to require [FromGraphQL] for things to be included. + // Conclusion: the argument should be ignored. + var maker = new GraphFieldMaker(server.Schema, new GraphArgumentMaker(server.Schema)); + var field = maker.CreateField(template).Field; + + if (argumentShouldBeIncluded) + Assert.AreEqual(1, field.Arguments.Count); + else + Assert.AreEqual(0, field.Arguments.Count); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/GraphTypeMakerTestBase.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/GraphTypeMakerTestBase.cs index 5dca1481d..9b39ee539 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/GraphTypeMakerTestBase.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/GraphTypeMakerTestBase.cs @@ -47,10 +47,7 @@ protected GraphTypeCreationResult MakeGraphType( protected IGraphField MakeGraphField(IGraphFieldTemplate fieldTemplate) { var testServer = new TestServerBuilder().Build(); - - var factory = testServer.CreateMakerFactory(); - - var maker = factory.CreateFieldMaker(); + var maker = new GraphFieldMaker(testServer.Schema, new GraphArgumentMaker(testServer.Schema)); return maker.CreateField(fieldTemplate).Field; } diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ObjectWithAttributedFieldArguments.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ObjectWithAttributedFieldArguments.cs new file mode 100644 index 000000000..2b0291e18 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ObjectWithAttributedFieldArguments.cs @@ -0,0 +1,43 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData +{ + using GraphQL.AspNet.Attributes; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + using GraphQL.AspNet.Tests.Common.Interfaces; + using Microsoft.AspNetCore.Mvc; + + public class ObjectWithAttributedFieldArguments + { + [GraphField] + public int FieldWithExplicitServiceArg([FromServices] int arg1) + { + return 0; + } + + [GraphField] + public int FieldWithExplicitSchemArg([FromGraphQL] ISinglePropertyObject arg1) + { + return 0; + } + + [GraphField] + public int FieldWithImplicitArgThatShouldBeServiceInjected(ISinglePropertyObject arg1) + { + return 0; + } + + [GraphField] + public int FieldWithImplicitArgThatShouldBeInGraph(TwoPropertyObject arg1) + { + return 0; + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ArgumentTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ArgumentTemplateTests.cs index f5acce68f..3c364133c 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ArgumentTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ArgumentTemplateTests.cs @@ -298,16 +298,14 @@ public void IncompatiableTypeExpressionNullToNotNull_ThrowsException() public void FromGraphQLDeclaration_SetsParamModifierAppropriately() { var template = this.ExtractParameterTemplate("justFromGraphQLDeclaration", out var paramInfo); - Assert.AreEqual(GraphArgumentModifiers.ExplicitSchemaItem, template.ArgumentModifiers); + Assert.AreEqual(GraphArgumentModifiers.ExplicitSchemaItem, template.ArgumentModifier); } [Test] public void FromServiceDeclaration_SetsParamModifierAppropriately() { - // actual type expression [Int] - // declared as [Int!]! - var template = this.ExtractParameterTemplate("compatiableTypeExpressionList", out var paramInfo); - Assert.AreEqual(GraphArgumentModifiers.ExplicitInjected, template.ArgumentModifiers); + var template = this.ExtractParameterTemplate("justFromServicesDeclaration", out var paramInfo); + Assert.AreEqual(GraphArgumentModifiers.ExplicitInjected, template.ArgumentModifier); } [Test] diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/TypeExtensionFieldTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/TypeExtensionFieldTemplateTests.cs index 7e62435ef..1c72d5bcb 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/TypeExtensionFieldTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/TypeExtensionFieldTemplateTests.cs @@ -65,7 +65,7 @@ public void ClassTypeExtension_PropertyCheck() Assert.AreEqual(FieldResolutionMode.PerSourceItem, template.Mode); // first arg should be declared for the source data - Assert.IsTrue(template.Arguments[0].ArgumentModifiers.HasFlag(GraphArgumentModifiers.ParentFieldResult)); + Assert.IsTrue(template.Arguments[0].ArgumentModifier.HasFlag(GraphArgumentModifiers.ParentFieldResult)); } [Test] @@ -85,7 +85,7 @@ public void ClassBatchExtension_PropertyCheck() Assert.AreEqual(FieldResolutionMode.Batch, template.Mode); // first arg should be declared for the source data - Assert.IsTrue(template.Arguments[0].ArgumentModifiers.HasFlag(GraphArgumentModifiers.ParentFieldResult)); + Assert.IsTrue(template.Arguments[0].ArgumentModifier.HasFlag(GraphArgumentModifiers.ParentFieldResult)); } [Test] @@ -111,7 +111,7 @@ public void StructTypeExtension_PropertyCheck() Assert.AreEqual(FieldResolutionMode.PerSourceItem, template.Mode); // first arg should be declared for the source data - Assert.IsTrue(template.Arguments[0].ArgumentModifiers.HasFlag(GraphArgumentModifiers.ParentFieldResult)); + Assert.IsTrue(template.Arguments[0].ArgumentModifier.HasFlag(GraphArgumentModifiers.ParentFieldResult)); } [Test] @@ -131,7 +131,7 @@ public void StructBatchExtension_PropertyCheck() Assert.AreEqual(FieldResolutionMode.Batch, template.Mode); // first arg should be declared for the source data - Assert.IsTrue(template.Arguments[0].ArgumentModifiers.HasFlag(GraphArgumentModifiers.ParentFieldResult)); + Assert.IsTrue(template.Arguments[0].ArgumentModifier.HasFlag(GraphArgumentModifiers.ParentFieldResult)); } [Test] @@ -157,7 +157,7 @@ public void InterfaceTypeExtension_PropertyCheck() Assert.AreEqual(FieldResolutionMode.PerSourceItem, template.Mode); // first arg should be declared for the source data - Assert.IsTrue(template.Arguments[0].ArgumentModifiers.HasFlag(GraphArgumentModifiers.ParentFieldResult)); + Assert.IsTrue(template.Arguments[0].ArgumentModifier.HasFlag(GraphArgumentModifiers.ParentFieldResult)); } [Test] @@ -177,7 +177,7 @@ public void InterfaceBatchExtension_PropertyCheck() Assert.AreEqual(FieldResolutionMode.Batch, template.Mode); // first arg should be declared for the source data - Assert.IsTrue(template.Arguments[0].ArgumentModifiers.HasFlag(GraphArgumentModifiers.ParentFieldResult)); + Assert.IsTrue(template.Arguments[0].ArgumentModifier.HasFlag(GraphArgumentModifiers.ParentFieldResult)); } [Test] diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTypeCollectionTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTypeCollectionTests.cs index 4b7d782f3..74766d862 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTypeCollectionTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTypeCollectionTests.cs @@ -55,9 +55,7 @@ private IGraphField MakeGraphField(IGraphFieldTemplate fieldTemplate) { var testServer = new TestServerBuilder().Build(); - var factory = testServer.CreateMakerFactory(); - - var maker = new GraphFieldMaker(testServer.Schema, factory); + var maker = new GraphFieldMaker(testServer.Schema, new GraphArgumentMaker(testServer.Schema)); return maker.CreateField(fieldTemplate).Field; } From 916505bd1ec5e5de8f6beca20415fa740e263e58 Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Sat, 15 Jul 2023 16:27:04 -0700 Subject: [PATCH 37/63] WIP, simple minimal api directives working --- .../CompleteSubscriptionGraphActionResult.cs | 2 +- .../SubscriptionGraphControllerTemplate.cs | 2 +- ...chemaItemDefinitionExtensions_Internals.cs | 5 +- .../ServiceCollectionExtensions.cs | 4 + .../BatchBuilder{TSource,TResult,TKey}.cs | 2 +- .../ActionResults/GraphActionResult.cs | 11 ++- ... => OperationCompleteGraphActionResult.cs} | 6 +- .../UnspecifiedCancellationResult.cs} | 11 ++- .../ActionResults/DirectiveOkActionResult.cs | 34 -------- .../GraphDirective_ActionResults.cs | 6 +- .../Directives/RuntimeExecutionDirective.cs | 40 +++++++++ .../DefaultGraphQLSchemaFactory_GraphTypes.cs | 9 ++ ...GraphQLSchemaFactory_RuntimeDefinitions.cs | 17 +++- .../Engine/DefaultGraphQLTypeMakerFactory.cs | 72 ++++++++++------ .../GraphControllerActionResolverBase.cs | 2 +- .../Engine/IGraphQLTypeMakerFactory.cs | 6 +- ...InfoProvider.cs => IMemberInfoProvider.cs} | 2 +- .../RuntimeDirectiveActionDefinition.cs | 16 +++- .../Generation/TypeMakers/DirectiveMaker.cs | 8 +- .../TypeTemplates/GraphControllerTemplate.cs | 6 +- .../GraphDirectiveMethodTemplate.cs | 22 ++++- .../TypeTemplates/GraphDirectiveTemplate.cs | 54 ++++++++++-- .../InterfaceGraphTypeTemplate.cs | 2 +- .../TypeTemplates/MemberInfoProvider.cs | 4 +- .../NonLeafGraphTypeTemplateBase.cs | 6 +- .../TypeTemplates/ObjectGraphTypeTemplate.cs | 2 +- .../RuntimeGraphControllerTemplate.cs | 33 +++++--- .../RuntimeGraphDirectiveTemplate.cs | 82 +++++++++++++++++++ .../TypeCollections/ConcreteTypeCollection.cs | 8 +- src/graphql-aspnet/graphql-aspnet.csproj | 4 + .../Controllers/ControllerExtensionTests.cs | 4 +- .../SingleMethodGraphControllerTemplate.cs | 2 +- .../ActionResults/ActionResultTests.cs | 2 +- .../Controllers/GraphControllerTests.cs | 4 +- .../Engine/DefaultSchemaFactoryTests.cs | 26 ++++++ .../GeneralQueryExecutionRuntimeFieldTests.cs | 53 +++++++++++- .../ControllerWithInjectedService.cs | 23 ++++++ .../SampleDelegatesForMinimalApi.cs | 0 .../TestSchemaWithDescription.cs | 0 .../MappedDirectiveTemplateTests.cs | 16 +++- .../TypeMakers/InterfaceTypeMakerTests.cs | 9 -- .../PropertyTestData/SimplePropertyObject.cs | 2 +- 42 files changed, 475 insertions(+), 144 deletions(-) rename src/graphql-aspnet/Controllers/ActionResults/{ObjectReturnedGraphActionResult.cs => OperationCompleteGraphActionResult.cs} (82%) rename src/graphql-aspnet/{Directives/ActionResults/DirectiveCancelPipelineResult.cs => Controllers/ActionResults/UnspecifiedCancellationResult.cs} (65%) delete mode 100644 src/graphql-aspnet/Directives/ActionResults/DirectiveOkActionResult.cs create mode 100644 src/graphql-aspnet/Directives/RuntimeExecutionDirective.cs rename src/graphql-aspnet/Interfaces/Internal/{IFieldMemberInfoProvider.cs => IMemberInfoProvider.cs} (96%) create mode 100644 src/graphql-aspnet/Schemas/Generation/TypeTemplates/RuntimeGraphDirectiveTemplate.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Execution/TestData/RuntimeFieldTestData/ControllerWithInjectedService.cs rename src/unit-tests/graphql-aspnet-tests/Execution/TestData/{RuntimeFieldTest => RuntimeFieldTestData}/SampleDelegatesForMinimalApi.cs (100%) rename src/unit-tests/graphql-aspnet-tests/Execution/TestData/{ => RuntimeFieldTestData}/TestSchemaWithDescription.cs (100%) diff --git a/src/graphql-aspnet-subscriptions/Controllers/ActionResults/CompleteSubscriptionGraphActionResult.cs b/src/graphql-aspnet-subscriptions/Controllers/ActionResults/CompleteSubscriptionGraphActionResult.cs index 6b5e5b85f..77af70ae7 100644 --- a/src/graphql-aspnet-subscriptions/Controllers/ActionResults/CompleteSubscriptionGraphActionResult.cs +++ b/src/graphql-aspnet-subscriptions/Controllers/ActionResults/CompleteSubscriptionGraphActionResult.cs @@ -23,7 +23,7 @@ namespace GraphQL.AspNet.Controllers.ActionResults /// additional events will be raised. /// [DebuggerDisplay("Has Object: {_result?.GetType().FriendlyName()}")] - public class CompleteSubscriptionGraphActionResult : ObjectReturnedGraphActionResult + public class CompleteSubscriptionGraphActionResult : OperationCompleteGraphActionResult { /// /// Applies the appropriate session information to the field context to instruct diff --git a/src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionGraphControllerTemplate.cs b/src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionGraphControllerTemplate.cs index 26aeacc3a..84719c609 100644 --- a/src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionGraphControllerTemplate.cs +++ b/src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionGraphControllerTemplate.cs @@ -35,7 +35,7 @@ public SubscriptionGraphControllerTemplate(Type controllerType) } /// - protected override IGraphFieldTemplate CreateFieldTemplate(IFieldMemberInfoProvider member) + protected override IGraphFieldTemplate CreateFieldTemplate(IMemberInfoProvider member) { if (member?.MemberInfo == null || !(member.MemberInfo is MethodInfo)) return null; diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Internals.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Internals.cs index ca62af9a2..2efaf2bd8 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Internals.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Internals.cs @@ -57,13 +57,14 @@ private static IGraphQLRuntimeTypeExtensionDefinition MapTypeExtensionInternal( return field; } - private static IGraphQLRuntimeDirectiveDefinition MapDirectiveInternal(this SchemaOptions schemaOptions, string directiveName) + private static IGraphQLRuntimeDirectiveDefinition MapDirectiveInternal( + this SchemaOptions schemaOptions, + string directiveName) { while (directiveName != null && directiveName.StartsWith(TokenTypeNames.STRING_AT_SYMBOL)) directiveName = directiveName.Substring(1); var directive = new RuntimeDirectiveActionDefinition(schemaOptions, directiveName); - schemaOptions.AddRuntimeSchemaItem(directive); return directive; } diff --git a/src/graphql-aspnet/Configuration/ServiceCollectionExtensions.cs b/src/graphql-aspnet/Configuration/ServiceCollectionExtensions.cs index 579280279..123a4cf8f 100644 --- a/src/graphql-aspnet/Configuration/ServiceCollectionExtensions.cs +++ b/src/graphql-aspnet/Configuration/ServiceCollectionExtensions.cs @@ -10,6 +10,7 @@ namespace GraphQL.AspNet.Configuration { using GraphQL.AspNet.Controllers; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; @@ -28,7 +29,10 @@ public static class ServiceCollectionExtensions public static IServiceCollection AddRuntimeFieldExecutionSupport(this IServiceCollection serviceCollection) { if (serviceCollection != null) + { serviceCollection.TryAddTransient(); + serviceCollection.TryAddTransient(); + } return serviceCollection; } diff --git a/src/graphql-aspnet/Controllers/ActionResults/Batching/BatchBuilder{TSource,TResult,TKey}.cs b/src/graphql-aspnet/Controllers/ActionResults/Batching/BatchBuilder{TSource,TResult,TKey}.cs index 75092b472..fca27b2da 100644 --- a/src/graphql-aspnet/Controllers/ActionResults/Batching/BatchBuilder{TSource,TResult,TKey}.cs +++ b/src/graphql-aspnet/Controllers/ActionResults/Batching/BatchBuilder{TSource,TResult,TKey}.cs @@ -131,7 +131,7 @@ public IGraphActionResult Complete() dictionary.Add(sourceItem, sourceResults); } - return new ObjectReturnedGraphActionResult(dictionary); + return new OperationCompleteGraphActionResult(dictionary); } /// diff --git a/src/graphql-aspnet/Controllers/ActionResults/GraphActionResult.cs b/src/graphql-aspnet/Controllers/ActionResults/GraphActionResult.cs index a6ebf2ce6..8ba8e8842 100644 --- a/src/graphql-aspnet/Controllers/ActionResults/GraphActionResult.cs +++ b/src/graphql-aspnet/Controllers/ActionResults/GraphActionResult.cs @@ -30,7 +30,7 @@ public static class GraphActionResult /// IGraphActionResult<TResult>. public static IGraphActionResult Ok(object item) { - return new ObjectReturnedGraphActionResult(item); + return new OperationCompleteGraphActionResult(item); } /// @@ -144,5 +144,14 @@ public static BatchBuilder StartBatch(IGraphField targetField) Validation.ThrowIfNull(targetField, nameof(targetField)); return new BatchBuilder(targetField); } + + /// + /// Silently cancels the current execution context without supplying an error or reason code. + /// + /// IGraphActionResult. + public static IGraphActionResult Cancel() + { + return new UnspecifiedCancellationResult(); + } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Controllers/ActionResults/ObjectReturnedGraphActionResult.cs b/src/graphql-aspnet/Controllers/ActionResults/OperationCompleteGraphActionResult.cs similarity index 82% rename from src/graphql-aspnet/Controllers/ActionResults/ObjectReturnedGraphActionResult.cs rename to src/graphql-aspnet/Controllers/ActionResults/OperationCompleteGraphActionResult.cs index 9945faf49..5dee49dfc 100644 --- a/src/graphql-aspnet/Controllers/ActionResults/ObjectReturnedGraphActionResult.cs +++ b/src/graphql-aspnet/Controllers/ActionResults/OperationCompleteGraphActionResult.cs @@ -18,15 +18,15 @@ namespace GraphQL.AspNet.Controllers.ActionResults /// A result indicating an ok return status and an object to be rendered to the graph. /// [DebuggerDisplay("Has Object: {_result?.GetType().FriendlyName()}")] - public class ObjectReturnedGraphActionResult : IGraphActionResult + public class OperationCompleteGraphActionResult : IGraphActionResult { private readonly object _result; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The object to return. - public ObjectReturnedGraphActionResult(object objectToReturn) + public OperationCompleteGraphActionResult(object objectToReturn) { _result = objectToReturn; } diff --git a/src/graphql-aspnet/Directives/ActionResults/DirectiveCancelPipelineResult.cs b/src/graphql-aspnet/Controllers/ActionResults/UnspecifiedCancellationResult.cs similarity index 65% rename from src/graphql-aspnet/Directives/ActionResults/DirectiveCancelPipelineResult.cs rename to src/graphql-aspnet/Controllers/ActionResults/UnspecifiedCancellationResult.cs index f7f9678d9..cba3fefe3 100644 --- a/src/graphql-aspnet/Directives/ActionResults/DirectiveCancelPipelineResult.cs +++ b/src/graphql-aspnet/Controllers/ActionResults/UnspecifiedCancellationResult.cs @@ -7,22 +7,21 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Directives.ActionResults +namespace GraphQL.AspNet.Controllers.ActionResults { using System.Threading.Tasks; using GraphQL.AspNet.Execution.Contexts; using GraphQL.AspNet.Interfaces.Controllers; /// - /// A directive action result that generates a response indicating the in-progress pipeline - /// should be abandoned. + /// A action result that generates a a canceled context without indicating any specific error. /// - public class DirectiveCancelPipelineResult : IGraphActionResult + public class UnspecifiedCancellationResult : IGraphActionResult { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - public DirectiveCancelPipelineResult() + public UnspecifiedCancellationResult() { } diff --git a/src/graphql-aspnet/Directives/ActionResults/DirectiveOkActionResult.cs b/src/graphql-aspnet/Directives/ActionResults/DirectiveOkActionResult.cs deleted file mode 100644 index a575cd8ab..000000000 --- a/src/graphql-aspnet/Directives/ActionResults/DirectiveOkActionResult.cs +++ /dev/null @@ -1,34 +0,0 @@ -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - -namespace GraphQL.AspNet.Directives.ActionResults -{ - using System.Threading.Tasks; - using GraphQL.AspNet.Execution.Contexts; - using GraphQL.AspNet.Interfaces.Controllers; - - /// - /// An action reslt indicating a successful completion of a directive with no returned value. - /// - public class DirectiveOkActionResult : IGraphActionResult - { - /// - /// Initializes a new instance of the class. - /// - public DirectiveOkActionResult() - { - } - - /// - public Task CompleteAsync(SchemaItemResolutionContext context) - { - return Task.CompletedTask; - } - } -} \ No newline at end of file diff --git a/src/graphql-aspnet/Directives/GraphDirective_ActionResults.cs b/src/graphql-aspnet/Directives/GraphDirective_ActionResults.cs index eec00bc0e..9405c519e 100644 --- a/src/graphql-aspnet/Directives/GraphDirective_ActionResults.cs +++ b/src/graphql-aspnet/Directives/GraphDirective_ActionResults.cs @@ -10,7 +10,7 @@ namespace GraphQL.AspNet.Directives { using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Directives.ActionResults; + using GraphQL.AspNet.Controllers.ActionResults; using GraphQL.AspNet.Interfaces.Controllers; using GraphQL.AspNet.Interfaces.Execution; @@ -25,7 +25,7 @@ public abstract partial class GraphDirective : GraphControllerBaseIGraphActionResult<TResult>. protected virtual IGraphActionResult Ok() { - return new DirectiveOkActionResult(); + return GraphActionResult.Ok(); } /// @@ -36,7 +36,7 @@ protected virtual IGraphActionResult Ok() /// IGraphActionResult. protected virtual IGraphActionResult Cancel() { - return new DirectiveCancelPipelineResult(); + return GraphActionResult.Cancel(); } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Directives/RuntimeExecutionDirective.cs b/src/graphql-aspnet/Directives/RuntimeExecutionDirective.cs new file mode 100644 index 000000000..41fcf122d --- /dev/null +++ b/src/graphql-aspnet/Directives/RuntimeExecutionDirective.cs @@ -0,0 +1,40 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Controllers +{ + using GraphQL.AspNet.Common.Generics; + using GraphQL.AspNet.Directives; + using GraphQL.AspNet.Interfaces.Execution; + + /// + /// A special directive instance for executing runtime configured directive + /// actions (e.g. minimal api defined directives). + /// + internal sealed class RuntimeExecutionDirective : GraphDirective + { + /// + protected override object CreateAndInvokeAction(IGraphFieldResolverMetaData metadata, object[] invocationArguments) + { + // minimal api resolvers are allowed to be static since there is no + // extra context to setup or make available such as 'this.User' etc. + if (metadata.Method.IsStatic) + { + var invoker = InstanceFactory.CreateStaticMethodInvoker(metadata.Method); + return invoker(invocationArguments); + } + else + { + var invoker = InstanceFactory.CreateInstanceMethodInvoker(metadata.Method); + var instance = InstanceFactory.CreateInstance(metadata.Method.DeclaringType); + return invoker(ref instance, invocationArguments); + } + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_GraphTypes.cs b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_GraphTypes.cs index 9585de7fc..c6e1ee7e7 100644 --- a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_GraphTypes.cs +++ b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_GraphTypes.cs @@ -96,6 +96,15 @@ protected virtual void EnsureGraphType(Type type, TypeKind? typeKind = null) makerResult = maker.CreateGraphType(template); } + this.AddMakerResult(makerResult); + } + + /// + /// Processes the result of creating a graph type from a template and adds its contents to the schema. + /// + /// The maker result to process. + protected virtual void AddMakerResult(GraphTypeCreationResult makerResult) + { if (makerResult != null) { this.Schema.KnownTypes.EnsureGraphType(makerResult.GraphType, makerResult.ConcreteType); diff --git a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_RuntimeDefinitions.cs b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_RuntimeDefinitions.cs index c240ba265..62bf743ec 100644 --- a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_RuntimeDefinitions.cs +++ b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_RuntimeDefinitions.cs @@ -10,9 +10,12 @@ namespace GraphQL.AspNet.Engine { using System; + using System.Reflection.Metadata; using GraphQL.AspNet.Common; using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; + using GraphQL.AspNet.Schemas.Generation.RuntimeSchemaItemDefinitions; using GraphQL.AspNet.Schemas.Generation.TypeTemplates; + using GraphQL.AspNet.Schemas.TypeSystem; /// /// The default schema factory, capable of creating instances of @@ -44,10 +47,18 @@ protected virtual void AddRuntimeSchemaItemDefinition(IGraphQLRuntimeSchemaItemD /// /// Adds a new directive to the schema based on the runtime definition created during program startup. /// - /// The directive definition to add. - protected virtual void AddRuntimeDirectiveDefinition(IGraphQLRuntimeDirectiveDefinition directiveDef) + /// The directive definition. + protected virtual void AddRuntimeDirectiveDefinition(IGraphQLRuntimeDirectiveDefinition directiveDefinition) { - throw new NotImplementedException(); + Validation.ThrowIfNull(directiveDefinition, nameof(directiveDefinition)); + var template = new RuntimeGraphDirectiveTemplate(directiveDefinition); + + template.Parse(); + template.ValidateOrThrow(); + + var maker = this.MakerFactory.CreateTypeMaker(kind: TypeKind.DIRECTIVE); + var result = maker.CreateGraphType(template); + this.AddMakerResult(result); } /// diff --git a/src/graphql-aspnet/Engine/DefaultGraphQLTypeMakerFactory.cs b/src/graphql-aspnet/Engine/DefaultGraphQLTypeMakerFactory.cs index 780d528a8..900a3bd5e 100644 --- a/src/graphql-aspnet/Engine/DefaultGraphQLTypeMakerFactory.cs +++ b/src/graphql-aspnet/Engine/DefaultGraphQLTypeMakerFactory.cs @@ -35,42 +35,64 @@ public virtual IGraphTypeTemplate MakeTemplate(Type objectType, TypeKind? kind = } /// - public virtual IGraphTypeMaker CreateTypeMaker(Type objectType, TypeKind? kind = null) + public virtual IGraphTypeMaker CreateTypeMaker(Type objectType = null, TypeKind? kind = null) { if (objectType == null) - return null; + { + if (!kind.HasValue) + return null; + } + else + { + objectType = GlobalTypes.FindBuiltInScalarType(objectType) ?? objectType; + + if (Validation.IsCastable(objectType)) + kind = TypeKind.SCALAR; + else if (objectType.IsEnum) + kind = TypeKind.ENUM; + else if (objectType.IsInterface) + kind = TypeKind.INTERFACE; + else if (Validation.IsCastable(objectType)) + kind = TypeKind.DIRECTIVE; + else if (Validation.IsCastable(objectType)) + kind = TypeKind.CONTROLLER; + else if (Validation.IsCastable(objectType)) + kind = TypeKind.UNION; + else if (!kind.HasValue || kind.Value != TypeKind.INPUT_OBJECT) + kind = TypeKind.OBJECT; + } - objectType = GlobalTypes.FindBuiltInScalarType(objectType) ?? objectType; + switch (kind.Value) + { + case TypeKind.SCALAR: + return new ScalarGraphTypeMaker(this.Schema.Configuration); - if (Validation.IsCastable(objectType)) - return new ScalarGraphTypeMaker(this.Schema.Configuration); + case TypeKind.INTERFACE: + return new InterfaceGraphTypeMaker(this.Schema.Configuration, this.CreateFieldMaker()); - if (objectType.IsEnum) - return new EnumGraphTypeMaker(this.Schema.Configuration); + case TypeKind.UNION: + return new UnionGraphTypeMaker(this.Schema.Configuration); - if (objectType.IsInterface) - return new InterfaceGraphTypeMaker(this.Schema.Configuration, this.CreateFieldMaker()); + case TypeKind.ENUM: + return new EnumGraphTypeMaker(this.Schema.Configuration); - if (Validation.IsCastable(objectType)) - return new DirectiveMaker(this.Schema.Configuration, this.CreateArgumentMaker()); + case TypeKind.INPUT_OBJECT: + return new InputObjectGraphTypeMaker( + this.Schema.Configuration, + this.CreateFieldMaker()); - if (Validation.IsCastable(objectType)) - return null; + case TypeKind.OBJECT: + return new ObjectGraphTypeMaker( + this.Schema.Configuration, + this.CreateFieldMaker()); - if (Validation.IsCastable(objectType)) - return new UnionGraphTypeMaker(this.Schema.Configuration); + case TypeKind.DIRECTIVE: + return new DirectiveMaker(this.Schema.Configuration, this.CreateArgumentMaker()); - if (kind.HasValue && kind.Value == TypeKind.INPUT_OBJECT) - { - return new InputObjectGraphTypeMaker( - this.Schema.Configuration, - this.CreateFieldMaker()); + case TypeKind.CONTROLLER: + default: + return null; } - - // when all else fails just use an object maker - return new ObjectGraphTypeMaker( - this.Schema.Configuration, - this.CreateFieldMaker()); } /// diff --git a/src/graphql-aspnet/Execution/Resolvers/GraphControllerActionResolverBase.cs b/src/graphql-aspnet/Execution/Resolvers/GraphControllerActionResolverBase.cs index 059d4a1ed..fe6344a46 100644 --- a/src/graphql-aspnet/Execution/Resolvers/GraphControllerActionResolverBase.cs +++ b/src/graphql-aspnet/Execution/Resolvers/GraphControllerActionResolverBase.cs @@ -31,7 +31,7 @@ protected virtual IGraphActionResult EnsureGraphActionResult(object result) if (result is IGraphActionResult actionResult) return actionResult; - return new ObjectReturnedGraphActionResult(result); + return new OperationCompleteGraphActionResult(result); } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Engine/IGraphQLTypeMakerFactory.cs b/src/graphql-aspnet/Interfaces/Engine/IGraphQLTypeMakerFactory.cs index fa5a2f739..b85ddf261 100644 --- a/src/graphql-aspnet/Interfaces/Engine/IGraphQLTypeMakerFactory.cs +++ b/src/graphql-aspnet/Interfaces/Engine/IGraphQLTypeMakerFactory.cs @@ -40,11 +40,11 @@ public interface IGraphQLTypeMakerFactory /// /// Parses the provided type, extracting the metadata used in type generation for the object graph. /// - /// The type of the object to parse. + /// The type of the object to inspect and determine a valid type maker. /// The graph to create a template for. If not supplied the template provider - /// will attempt to assign the best graph type possible. + /// will attempt to assign the best graph type possible for the supplied . /// IGraphTypeTemplate. - IGraphTypeMaker CreateTypeMaker(Type objectType, TypeKind? kind = null); + IGraphTypeMaker CreateTypeMaker(Type objectType = null, TypeKind? kind = null); /// /// Creates a maker that can generate valid graph fields diff --git a/src/graphql-aspnet/Interfaces/Internal/IFieldMemberInfoProvider.cs b/src/graphql-aspnet/Interfaces/Internal/IMemberInfoProvider.cs similarity index 96% rename from src/graphql-aspnet/Interfaces/Internal/IFieldMemberInfoProvider.cs rename to src/graphql-aspnet/Interfaces/Internal/IMemberInfoProvider.cs index e3b206774..259c63c10 100644 --- a/src/graphql-aspnet/Interfaces/Internal/IFieldMemberInfoProvider.cs +++ b/src/graphql-aspnet/Interfaces/Internal/IMemberInfoProvider.cs @@ -15,7 +15,7 @@ namespace GraphQL.AspNet.Interfaces.Internal /// A common interface that exposes the various attributes of a /// and to the templating system. /// - public interface IFieldMemberInfoProvider + public interface IMemberInfoProvider { /// /// Gets the member info object that defines a field. diff --git a/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeDirectiveActionDefinition.cs b/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeDirectiveActionDefinition.cs index 0c43b2e36..3427c784d 100644 --- a/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeDirectiveActionDefinition.cs +++ b/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeDirectiveActionDefinition.cs @@ -11,9 +11,12 @@ namespace GraphQL.AspNet.Schemas.Generation.RuntimeSchemaItemDefinitions { using System; using System.Diagnostics; + using System.Linq; + using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Execution; using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; + using GraphQL.AspNet.Schemas.TypeSystem; /// /// An internal implementation of the @@ -23,11 +26,13 @@ namespace GraphQL.AspNet.Schemas.Generation.RuntimeSchemaItemDefinitions internal class RuntimeDirectiveActionDefinition : BaseRuntimeControllerActionDefinition, IGraphQLRuntimeDirectiveDefinition { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The schema options where this directive will be created. /// Name of the directive to use in the schema. - public RuntimeDirectiveActionDefinition(SchemaOptions schemaOptions, string directiveName) + public RuntimeDirectiveActionDefinition( + SchemaOptions schemaOptions, + string directiveName) : base(schemaOptions, SchemaItemCollections.Directives, directiveName) { } @@ -35,7 +40,12 @@ public RuntimeDirectiveActionDefinition(SchemaOptions schemaOptions, string dire /// protected override Attribute CreatePrimaryAttribute() { - return null; + // if the user never declared any restrictions + // supply location data for ALL locations + if (this.AppendedAttributes.OfType().Any()) + return null; + + return new DirectiveLocationsAttribute(DirectiveLocation.AllExecutionLocations | DirectiveLocation.AllTypeSystemLocations); } /// diff --git a/src/graphql-aspnet/Schemas/Generation/TypeMakers/DirectiveMaker.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/DirectiveMaker.cs index a0d218e4e..5a61d3752 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeMakers/DirectiveMaker.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/DirectiveMaker.cs @@ -12,10 +12,12 @@ namespace GraphQL.AspNet.Schemas.Generation.TypeMakers using System; using System.Collections.Generic; using GraphQL.AspNet.Common; + using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Interfaces.Configuration; using GraphQL.AspNet.Interfaces.Engine; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Schemas.Generation.RuntimeSchemaItemDefinitions; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Security; @@ -80,7 +82,11 @@ public virtual GraphTypeCreationResult CreateGraphType(IGraphTypeTemplate typeTe } result.GraphType = directive; - result.ConcreteType = template.ObjectType; + + // only assign a concrete type if one was declared + if (template.ObjectType != typeof(RuntimeExecutionDirective)) + result.ConcreteType = template.ObjectType; + return result; } } diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphControllerTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphControllerTemplate.cs index 057e782dd..9115668d4 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphControllerTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphControllerTemplate.cs @@ -47,7 +47,7 @@ public GraphControllerTemplate(Type controllerType) } /// - protected override IEnumerable GatherPossibleFieldTemplates() + protected override IEnumerable GatherPossibleFieldTemplates() { return this.ObjectType.GetMethods(BindingFlags.Public | BindingFlags.Instance) .Where(x => !x.IsAbstract && !x.IsGenericMethod && !x.IsSpecialName).Cast() @@ -108,7 +108,7 @@ public override void ValidateOrThrow() } /// - protected override bool CouldBeGraphField(IFieldMemberInfoProvider fieldProvider) + protected override bool CouldBeGraphField(IMemberInfoProvider fieldProvider) { if (fieldProvider?.MemberInfo == null || !(fieldProvider.MemberInfo is MethodInfo methodInfo)) return false; @@ -121,7 +121,7 @@ protected override bool CouldBeGraphField(IFieldMemberInfoProvider fieldProvider } /// - protected override IGraphFieldTemplate CreateFieldTemplate(IFieldMemberInfoProvider member) + protected override IGraphFieldTemplate CreateFieldTemplate(IMemberInfoProvider member) { // safety check to ensure properites on controllers can never be parsed as fields if (member?.MemberInfo == null || !(member.MemberInfo is MethodInfo)) diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveMethodTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveMethodTemplate.cs index 1c23e9678..70d84e985 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveMethodTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveMethodTemplate.cs @@ -41,12 +41,26 @@ public class GraphDirectiveMethodTemplate : IGraphFieldTemplateBase /// /// The owner of this method. /// The method information. - internal GraphDirectiveMethodTemplate(IGraphTypeTemplate parent, MethodInfo method) + public GraphDirectiveMethodTemplate(IGraphTypeTemplate parent, MethodInfo method) { this.Parent = Validation.ThrowIfNullOrReturn(parent, nameof(parent)); this.Method = Validation.ThrowIfNullOrReturn(method, nameof(method)); this.Parameters = this.Method.GetParameters().ToList(); _arguments = new List(); + this.AttributeProvider = this.Method; + } + + /// + /// Initializes a new instance of the class. + /// + /// The owner of this method. + /// The method information. + /// A custom attribute provider this template will use + /// to perform its configuration. + public GraphDirectiveMethodTemplate(IGraphTypeTemplate parent, MethodInfo method, ICustomAttributeProvider attributeProvider) + : this(parent, method) + { + this.AttributeProvider = Validation.ThrowIfNullOrReturn(attributeProvider, nameof(attributeProvider)); } /// @@ -58,13 +72,13 @@ public virtual void Parse() this.ObjectType = GraphValidation.EliminateWrappersFromCoreType(this.DeclaredType); this.TypeExpression = new GraphTypeExpression(this.ObjectType.FriendlyName()); - this.Description = this.Method.SingleAttributeOrDefault()?.Description; + this.Description = this.AttributeProvider.SingleAttributeOrDefault()?.Description; this.IsAsyncField = Validation.IsCastable(this.Method.ReturnType); this.AppliedDirectives = this.ExtractAppliedDirectiveTemplates(); // deteremine all the directive locations where this method should be invoked var locations = DirectiveLocation.NONE; - foreach (var attrib in this.Method.AttributesOfType()) + foreach (var attrib in this.AttributeProvider.AttributesOfType()) { locations = locations | attrib.Locations; } @@ -284,7 +298,7 @@ public IGraphFieldResolverMetaData CreateResolverMetaData() public string InternalName => this.Method.Name; /// - public ICustomAttributeProvider AttributeProvider => this.Method; + public ICustomAttributeProvider AttributeProvider { get; } /// public IEnumerable AppliedDirectives { get; private set; } diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveTemplate.cs index 09c30e1fc..43423d5a7 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveTemplate.cs @@ -37,11 +37,14 @@ public class GraphDirectiveTemplate : GraphTypeTemplateBase, IGraphDirectiveTemp private AppliedSecurityPolicyGroup _securityPolicies; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// Type of the graph directive being described. - public GraphDirectiveTemplate(Type graphDirectiveType) - : base(graphDirectiveType) + /// The attribute provider that will supply the attributes needed to parse + /// and configure this template. is used if this parameter + /// is not supplied. + public GraphDirectiveTemplate(Type graphDirectiveType, ICustomAttributeProvider attributeProvider = null) + : base(attributeProvider ?? graphDirectiveType) { Validation.ThrowIfNotCastable(graphDirectiveType, nameof(graphDirectiveType)); @@ -67,14 +70,14 @@ protected override void ParseTemplateDefinition() this.Description = this.AttributeProvider.SingleAttributeOrDefault()?.Description; this.IsRepeatable = this.AttributeProvider.SingleAttributeOrDefault() != null; - var routeName = GraphTypeNames.ParseName(this.ObjectType, TypeKind.DIRECTIVE); + var routeName = this.DetermineDirectiveName(); this.Route = new SchemaItemPath(SchemaItemPath.Join(SchemaItemCollections.Directives, routeName)); - - foreach (var methodInfo in this.ObjectType.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)) + var potentialMethods = this.GatherPossibleDirectiveExecutionMethods(); + foreach (var methodData in potentialMethods) { - if (methodInfo.FirstAttributeOfTypeOrDefault() != null) + if (this.CouldBeDirectiveExecutionMethod(methodData)) { - var methodTemplate = new GraphDirectiveMethodTemplate(this, methodInfo); + var methodTemplate = new GraphDirectiveMethodTemplate(this, methodData.MemberInfo as MethodInfo, methodData.AttributeProvider); methodTemplate.Parse(); this.Methods.RegisterMethod(methodTemplate); } @@ -83,6 +86,41 @@ protected override void ParseTemplateDefinition() _securityPolicies = AppliedSecurityPolicyGroup.FromAttributeCollection(this.AttributeProvider); } + /// + /// Determines the name of the directive. (e.g. @name). + /// + /// System.String. + protected virtual string DetermineDirectiveName() + { + return GraphTypeNames.ParseName(this.ObjectType, TypeKind.DIRECTIVE); + } + + /// + /// Inspects the templated object and gathers all the methods with the right attribute declarations such that + /// they should be come execution methods on the directive instance. + /// + /// IEnumerable<IMemberInfoProvider>. + protected virtual IEnumerable GatherPossibleDirectiveExecutionMethods() + { + return this.ObjectType + .GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly) + .Select(x => new MemberInfoProvider(x)); + } + + /// + /// Inspects the member data and determines if it can be successfully parsed into a directive action method + /// for thi template. + /// + /// The member information to inspect. + /// true if the member data can be parsed, false otherwise. + protected virtual bool CouldBeDirectiveExecutionMethod(IMemberInfoProvider memberInfo) + { + return memberInfo?.MemberInfo is MethodInfo && + memberInfo + .AttributeProvider + .FirstAttributeOfTypeOrDefault() != null; + } + /// public IGraphFieldResolverMetaData FindMetaData(DirectiveLocation location) { diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/InterfaceGraphTypeTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/InterfaceGraphTypeTemplate.cs index 718d49cf8..027c1649d 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/InterfaceGraphTypeTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/InterfaceGraphTypeTemplate.cs @@ -41,7 +41,7 @@ public InterfaceGraphTypeTemplate(Type interfaceType) } /// - protected override IEnumerable GatherPossibleFieldTemplates() + protected override IEnumerable GatherPossibleFieldTemplates() { return this.ObjectType.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly) .Where(x => !x.IsGenericMethod && !x.IsSpecialName).Cast() diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/MemberInfoProvider.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/MemberInfoProvider.cs index 27861cbaa..d4e27f30d 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/MemberInfoProvider.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/MemberInfoProvider.cs @@ -14,10 +14,10 @@ namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates using GraphQL.AspNet.Interfaces.Internal; /// - /// A for to abstract out appropriate pieces + /// A for to abstract out appropriate pieces /// of that are exposed to the templating system. /// - public class MemberInfoProvider : IFieldMemberInfoProvider + public class MemberInfoProvider : IMemberInfoProvider { /// /// Initializes a new instance of the class. diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/NonLeafGraphTypeTemplateBase.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/NonLeafGraphTypeTemplateBase.cs index e2af0e2ed..62396749e 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/NonLeafGraphTypeTemplateBase.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/NonLeafGraphTypeTemplateBase.cs @@ -161,7 +161,7 @@ protected override void ParseTemplateDefinition() /// that might be includable in this template. /// /// IEnumerable<IFieldMemberInfoProvider>. - protected abstract IEnumerable GatherPossibleFieldTemplates(); + protected abstract IEnumerable GatherPossibleFieldTemplates(); /// /// Creates the member template from the given info. If a provided @@ -169,7 +169,7 @@ protected override void ParseTemplateDefinition() /// /// The member to templatize. /// GraphQL.AspNet.Internal.Interfaces.IGraphFieldTemplate. - protected virtual IGraphFieldTemplate CreateFieldTemplate(IFieldMemberInfoProvider fieldProvider) + protected virtual IGraphFieldTemplate CreateFieldTemplate(IMemberInfoProvider fieldProvider) { if (fieldProvider?.MemberInfo == null) return null; @@ -194,7 +194,7 @@ protected virtual IGraphFieldTemplate CreateFieldTemplate(IFieldMemberInfoProvid /// The member information to check. /// /// true if the info represents a possible graph field; otherwise, false. - protected virtual bool CouldBeGraphField(IFieldMemberInfoProvider fieldProvider) + protected virtual bool CouldBeGraphField(IMemberInfoProvider fieldProvider) { // always skip those marked as such regardless of anything else if (fieldProvider.AttributeProvider.HasAttribute()) diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/ObjectGraphTypeTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/ObjectGraphTypeTemplate.cs index f3c872288..7fde579de 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/ObjectGraphTypeTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/ObjectGraphTypeTemplate.cs @@ -33,7 +33,7 @@ public ObjectGraphTypeTemplate(Type objectType) } /// - protected override IEnumerable GatherPossibleFieldTemplates() + protected override IEnumerable GatherPossibleFieldTemplates() { return this.ObjectType.GetMethods(BindingFlags.Public | BindingFlags.Instance) .Where(x => !x.IsAbstract && !x.IsGenericMethod && !x.IsSpecialName).Cast() diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/RuntimeGraphControllerTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/RuntimeGraphControllerTemplate.cs index 169aef51a..ce54c7b84 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/RuntimeGraphControllerTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/RuntimeGraphControllerTemplate.cs @@ -21,7 +21,8 @@ namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates /// internal class RuntimeGraphControllerTemplate : GraphControllerTemplate { - private readonly IFieldMemberInfoProvider _fieldProvider; + private readonly IMemberInfoProvider _fieldProvider; + private readonly IGraphQLRuntimeResolvedFieldDefinition _fieldDefinition; /// /// Initializes a new instance of the class. @@ -31,28 +32,38 @@ internal class RuntimeGraphControllerTemplate : GraphControllerTemplate public RuntimeGraphControllerTemplate(IGraphQLRuntimeResolvedFieldDefinition fieldDefinition) : base(typeof(RuntimeFieldExecutionController)) { - if (fieldDefinition.Resolver?.Method == null) + _fieldDefinition = fieldDefinition; + if (fieldDefinition.Resolver?.Method != null) { - throw new GraphTypeDeclarationException( - $"Unable to templatize the runtime field definition of '{fieldDefinition.Route}' the resolver " + - $"is not properly configured."); + _fieldProvider = new MemberInfoProvider( + fieldDefinition.Resolver.Method, + new RuntimeSchemaItemAttributeProvider(fieldDefinition)); } - - _fieldProvider = new MemberInfoProvider( - fieldDefinition.Resolver.Method, - new RuntimeSchemaItemAttributeProvider(fieldDefinition)); } /// - protected override IEnumerable GatherPossibleFieldTemplates() + protected override IEnumerable GatherPossibleFieldTemplates() { yield return _fieldProvider; } /// - protected override bool CouldBeGraphField(IFieldMemberInfoProvider fieldProvider) + protected override bool CouldBeGraphField(IMemberInfoProvider fieldProvider) { return fieldProvider != null && fieldProvider == _fieldProvider; } + + /// + public override void ValidateOrThrow() + { + if (_fieldDefinition?.Resolver?.Method == null) + { + throw new GraphTypeDeclarationException( + $"Unable to templatize the runtime field definition of '{_fieldDefinition?.Route.Path ?? "~null~"}' the resolver " + + $"is not properly configured."); + } + + base.ValidateOrThrow(); + } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/RuntimeGraphDirectiveTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/RuntimeGraphDirectiveTemplate.cs new file mode 100644 index 000000000..c829310ff --- /dev/null +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/RuntimeGraphDirectiveTemplate.cs @@ -0,0 +1,82 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates +{ + using System.Collections.Generic; + using System.Diagnostics; + using GraphQL.AspNet.Controllers; + using GraphQL.AspNet.Execution.Exceptions; + using GraphQL.AspNet.Interfaces.Internal; + using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; + + /// + /// A "controller template" representing a single runtime configured field (e.g. minimal api). + /// This template is never cached. + /// + [DebuggerDisplay("{Route.Name} - RuntimeDirective")] + internal class RuntimeGraphDirectiveTemplate : GraphDirectiveTemplate + { + private readonly IMemberInfoProvider _fieldProvider; + private readonly IGraphQLRuntimeDirectiveDefinition _directiveDefinition; + + /// + /// Initializes a new instance of the class. + /// + /// A single, runtime configured, directive definition + /// to templatize for a specfic schema. + public RuntimeGraphDirectiveTemplate(IGraphQLRuntimeDirectiveDefinition directiveDef) + : base(typeof(RuntimeExecutionDirective), new RuntimeSchemaItemAttributeProvider(directiveDef)) + { + _directiveDefinition = directiveDef; + if (directiveDef?.Resolver?.Method != null) + { + _fieldProvider = new MemberInfoProvider( + directiveDef.Resolver.Method, + new RuntimeSchemaItemAttributeProvider(directiveDef)); + } + } + + /// + protected override IEnumerable GatherPossibleDirectiveExecutionMethods() + { + yield return this._fieldProvider; + } + + /// + protected override bool CouldBeDirectiveExecutionMethod(IMemberInfoProvider memberInfgo) + { + return memberInfgo != null + && memberInfgo == _fieldProvider + && base.CouldBeDirectiveExecutionMethod(memberInfgo); + } + + /// + protected override string DetermineDirectiveName() + { + if (_directiveDefinition != null) + return _directiveDefinition?.Route.Name; + + return base.DetermineDirectiveName(); + } + + /// + public override void ValidateOrThrow() + { + if (_directiveDefinition?.Resolver?.Method == null) + { + throw new GraphTypeDeclarationException( + $"Unable to templatize the runtime directive definition of '{_directiveDefinition?.Route.Path ?? "~null~"}' the resolver " + + $"is not properly configured."); + } + + base.ValidateOrThrow(); + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/TypeSystem/TypeCollections/ConcreteTypeCollection.cs b/src/graphql-aspnet/Schemas/TypeSystem/TypeCollections/ConcreteTypeCollection.cs index 58759f537..8eb21d580 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/TypeCollections/ConcreteTypeCollection.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/TypeCollections/ConcreteTypeCollection.cs @@ -15,9 +15,12 @@ namespace GraphQL.AspNet.Schemas.TypeSystem.TypeCollections using System.Linq; using GraphQL.AspNet.Common; using GraphQL.AspNet.Common.Extensions; + using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Directives; using GraphQL.AspNet.Execution.Exceptions; + using GraphQL.AspNet.Execution.RulesEngine.RuleSets.DocumentValidation.QueryFragmentSteps; using GraphQL.AspNet.Interfaces.Schema; + using Microsoft.Extensions.DependencyInjection; /// /// A colleciton of and their associated concrete .NET . @@ -200,8 +203,9 @@ private void EnsureGraphTypeToConcreteTypeAssociationOrThrow(IGraphType graphTyp $"The concrete type '{associatedType.FriendlyName()}' is an enum. It cannot be associated to a graph type of '{graphType.Kind.ToString()}'."); } - // directives must be assigned to a concrete type and it must inherit from GraphDirective. - if (graphType.Kind == TypeKind.DIRECTIVE && (associatedType == null || !Validation.IsCastable(associatedType))) + // if a directive is assigned to a concrete type + // it must inherit from GraphDirective. + if (graphType.Kind == TypeKind.DIRECTIVE && associatedType != null && !Validation.IsCastable(associatedType)) { throw new GraphTypeDeclarationException( $"The directive type '{graphType.Name}' cannnot be associated to the concrete type '{associatedType.FriendlyName()}'. Directive graph types " + diff --git a/src/graphql-aspnet/graphql-aspnet.csproj b/src/graphql-aspnet/graphql-aspnet.csproj index 5260e555c..221d0a47d 100644 --- a/src/graphql-aspnet/graphql-aspnet.csproj +++ b/src/graphql-aspnet/graphql-aspnet.csproj @@ -12,4 +12,8 @@ + + + + \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Controllers/ControllerExtensionTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Controllers/ControllerExtensionTests.cs index 701a3794d..152e88997 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Controllers/ControllerExtensionTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Controllers/ControllerExtensionTests.cs @@ -44,7 +44,7 @@ public async Task PublishSubEvent_PublishesEventWithCorrectData() // ensure the method executed completely Assert.IsNotNull(result); - Assert.IsTrue(result is ObjectReturnedGraphActionResult); + Assert.IsTrue(result is OperationCompleteGraphActionResult); // ensure the event collection was created on the context Assert.IsTrue(resolutionContext.Session.Items.ContainsKey(SubscriptionConstants.ContextDataKeys.RAISED_EVENTS_COLLECTION)); @@ -107,7 +107,7 @@ public async Task PublishSubEvent_ExistingEventCollectionisAppendedTo() // ensure the method executed completely Assert.IsNotNull(result); - Assert.IsTrue(result is ObjectReturnedGraphActionResult); + Assert.IsTrue(result is OperationCompleteGraphActionResult); Assert.AreEqual(1, eventCollection.Count); } diff --git a/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/SingleMethodGraphControllerTemplate.cs b/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/SingleMethodGraphControllerTemplate.cs index b36536a29..89c0dbb5a 100644 --- a/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/SingleMethodGraphControllerTemplate.cs +++ b/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/SingleMethodGraphControllerTemplate.cs @@ -41,7 +41,7 @@ public SingleMethodGraphControllerTemplate(string methodName = null) /// /// The member information to check. /// true if the info represents a possible graph field; otherwise, false. - protected override bool CouldBeGraphField(IFieldMemberInfoProvider memberInfo) + protected override bool CouldBeGraphField(IMemberInfoProvider memberInfo) { if (_methodName != null && memberInfo.MemberInfo.Name != _methodName) return false; diff --git a/src/unit-tests/graphql-aspnet-tests/Controllers/ActionResults/ActionResultTests.cs b/src/unit-tests/graphql-aspnet-tests/Controllers/ActionResults/ActionResultTests.cs index 74d60e5e9..8fa2aa3ca 100644 --- a/src/unit-tests/graphql-aspnet-tests/Controllers/ActionResults/ActionResultTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Controllers/ActionResults/ActionResultTests.cs @@ -157,7 +157,7 @@ public async Task ObjectRetrunedGraph_ReturnsSameItemGivenToIt() { var testObject = new object(); - var actionResult = new ObjectReturnedGraphActionResult(testObject); + var actionResult = new OperationCompleteGraphActionResult(testObject); var context = this.CreateResolutionContext(); await actionResult.CompleteAsync(context); diff --git a/src/unit-tests/graphql-aspnet-tests/Controllers/GraphControllerTests.cs b/src/unit-tests/graphql-aspnet-tests/Controllers/GraphControllerTests.cs index c54882415..b580a56a4 100644 --- a/src/unit-tests/graphql-aspnet-tests/Controllers/GraphControllerTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Controllers/GraphControllerTests.cs @@ -39,7 +39,7 @@ public async Task MethodInvocation_EnsureInternalPropertiesAreSet() var result = await controller.InvokeActionAsync(fieldContextBuilder.ResolverMetaData.Object, resolutionContext); Assert.IsNotNull(result); - Assert.IsTrue(result is ObjectReturnedGraphActionResult); + Assert.IsTrue(result is OperationCompleteGraphActionResult); Assert.AreEqual(3, controller.CapturedItems.Count); @@ -67,7 +67,7 @@ public async Task MethodInvocation_SyncMethodReturnsObjectNotTask() var result = await controller.InvokeActionAsync(fieldContextBuilder.ResolverMetaData.Object, resolutionContext); Assert.IsNotNull(result); - Assert.IsTrue(result is ObjectReturnedGraphActionResult); + Assert.IsTrue(result is OperationCompleteGraphActionResult); } [Test] diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTests.cs b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTests.cs index 829404bef..355166b94 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTests.cs @@ -573,5 +573,31 @@ public void SchemaItemValidators_AreInvoked() runtimeItemDefinitions: options.RuntimeTemplates); }); } + + [Test] + public void RuntimeFieldDefs_HaveSamePath_ThrowException() + { + var collection = this.SetupCollection(); + + var factory = new DefaultGraphQLSchemaFactory(includeBuiltInDirectives: false); + var options = new SchemaOptions(collection); + options.DeclarationOptions.DisableIntrospection = true; + + // same field path + options.MapQuery("field1", (int arg1) => 0); + options.MapQuery("field1", (int arg1) => 0); + + var provider = collection.BuildServiceProvider(); + var scope = provider.CreateScope(); + var config = options.CreateConfiguration(); + + var ex = Assert.Throws(() => + { + var instance = factory.CreateInstance( + scope, + config, + runtimeItemDefinitions: options.RuntimeTemplates); + }); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionRuntimeFieldTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionRuntimeFieldTests.cs index 548e23eaf..68718e429 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionRuntimeFieldTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionRuntimeFieldTests.cs @@ -12,7 +12,7 @@ namespace GraphQL.AspNet.Tests.Execution using System.Threading.Tasks; using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Controllers.ActionResults; - using GraphQL.AspNet.Interfaces.Controllers; + using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Execution.TestData.RuntimeFieldTest; using GraphQL.AspNet.Tests.Execution.TestData.RuntimeFieldTestData; @@ -24,6 +24,8 @@ namespace GraphQL.AspNet.Tests.Execution [TestFixture] public class GeneralQueryExecutionRuntimeFieldTests { + private static int _resolvedDirectiveValue = 0; + [Test] public async Task BasicMappedQuery_ExecutesMethod() { @@ -378,5 +380,54 @@ public async Task BasicMappedQuery_WithImplicitlyDeclaredInjectedService_Returni }", result); } + + [Test] + public async Task ServiceInjectedOnControllerAction_ResolvesCorrectly() + { + var serverBuilder = new TestServerBuilder(); + serverBuilder.AddTransient(); + serverBuilder.AddController(); + + var server = serverBuilder.Build(); + var builder = server.CreateQueryContextBuilder(); + + // injected service will supply 23 + builder.AddQueryText(@"query { add(arg1: 5) }"); + + var result = await server.RenderResult(builder); + CommonAssertions.AreEqualJsonStrings( + @"{ + ""data"": { + ""add"" : 28 + } + }", + result); + } + + [Test] + public void Runtime_TypeSystemDirective_IsInvokedCorrectly() + { + var serverBuilder = new TestServerBuilder(); + + var refData = new TwoPropertyObject(); + serverBuilder.AddGraphQL(o => + { + o.AddType(); + o.MapDirective("@myObjectDirective") + .RestrictLocations(DirectiveLocation.OBJECT) + .AddResolver((int a, int b) => + { + _resolvedDirectiveValue = a + b; + return GraphActionResult.Ok(); + }); + + o.ApplyDirective("myObjectDirective") + .ToItems(x => x.IsObjectGraphType()) + .WithArguments(5, 18); + }); + + var server = serverBuilder.Build(); + Assert.AreEqual(23, _resolvedDirectiveValue); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/RuntimeFieldTestData/ControllerWithInjectedService.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/RuntimeFieldTestData/ControllerWithInjectedService.cs new file mode 100644 index 000000000..f1f8535ee --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/RuntimeFieldTestData/ControllerWithInjectedService.cs @@ -0,0 +1,23 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Execution.TestData.RuntimeFieldTestData +{ + using GraphQL.AspNet.Attributes; + using GraphQL.AspNet.Controllers; + + public class ControllerWithInjectedService : GraphController + { + [QueryRoot] + public int Add(int arg1, IInjectedService arg2) + { + return arg1 + arg2.FetchValue(); + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/RuntimeFieldTest/SampleDelegatesForMinimalApi.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/RuntimeFieldTestData/SampleDelegatesForMinimalApi.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Execution/TestData/RuntimeFieldTest/SampleDelegatesForMinimalApi.cs rename to src/unit-tests/graphql-aspnet-tests/Execution/TestData/RuntimeFieldTestData/SampleDelegatesForMinimalApi.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/TestSchemaWithDescription.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/RuntimeFieldTestData/TestSchemaWithDescription.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Execution/TestData/TestSchemaWithDescription.cs rename to src/unit-tests/graphql-aspnet-tests/Execution/TestData/RuntimeFieldTestData/TestSchemaWithDescription.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedDirectiveTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedDirectiveTemplateTests.cs index 5d22873a4..256c9b275 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedDirectiveTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedDirectiveTemplateTests.cs @@ -38,6 +38,13 @@ public void MapDirective_ByOptions_AddsDirectiveToOptions() Assert.AreEqual("[directive]/myDirective", directive.Route.Path); Assert.IsNull(directive.ReturnType); Assert.IsNull(directive.Resolver); + + // by default ALL locations are allowed + Assert.AreEqual(1, directive.Attributes.Count()); + var locationAttib = directive.Attributes.First() as DirectiveLocationsAttribute; + Assert.IsNotNull(locationAttib); + + Assert.AreEqual(DirectiveLocation.AllExecutionLocations | DirectiveLocation.AllTypeSystemLocations, locationAttib.Locations); } [Test] @@ -100,7 +107,8 @@ public void MappedDirective_WhenAllowAnonymousAdded_AddsAnonymousAttribute() directive.AllowAnonymous(); - Assert.AreEqual(1, directive.Attributes.Count()); + // [AllowANonymous] [DirectiveLocations] + Assert.AreEqual(2, directive.Attributes.Count()); Assert.IsNotNull(directive.Attributes.FirstOrDefault(x => x is AllowAnonymousAttribute)); } @@ -114,7 +122,8 @@ public void MappedDirective_WhenRequireAuthAdded_AddsAuthAttribute() directive.RequireAuthorization("policy1", "roles1"); - Assert.AreEqual(1, directive.Attributes.Count()); + // [AllowANonymous] [DirectiveLocations] + Assert.AreEqual(2, directive.Attributes.Count()); var attrib = directive.Attributes.FirstOrDefault(x => x is AuthorizeAttribute) as AuthorizeAttribute; Assert.IsNotNull(attrib); Assert.AreEqual("policy1", attrib.Policy); @@ -148,7 +157,8 @@ public void MappedDirective_WhenRepeatableAdded_AddsAttribute() directive.IsRepeatable(); - Assert.AreEqual(1, directive.Attributes.Count()); + // [AllowANonymous] [DirectiveLocations] + Assert.AreEqual(2, directive.Attributes.Count()); var attrib = directive.Attributes.FirstOrDefault(x => x is RepeatableAttribute) as RepeatableAttribute; Assert.IsNotNull(attrib); } diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/InterfaceTypeMakerTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/InterfaceTypeMakerTests.cs index 1d3b9f528..49b1cb7c1 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/InterfaceTypeMakerTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/InterfaceTypeMakerTests.cs @@ -7,15 +7,6 @@ // License: MIT // ************************************************************* -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers { using System.Linq; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyTestData/SimplePropertyObject.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyTestData/SimplePropertyObject.cs index f941fe7fe..a3ca8bf3a 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyTestData/SimplePropertyObject.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyTestData/SimplePropertyObject.cs @@ -70,6 +70,6 @@ public class ShoeData public PropertyProxy UnionProxyProperty { get; set; } - public ObjectReturnedGraphActionResult ActionResultProperty { get; set; } + public OperationCompleteGraphActionResult ActionResultProperty { get; set; } } } \ No newline at end of file From 4cc1b6b3b826cc26933cc4d9ed9aca31452cfb4d Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Sat, 15 Jul 2023 20:55:29 -0700 Subject: [PATCH 38/63] WIP, runtime directive arguments fixed --- .../Engine/DefaultGraphQLSchemaFactory.cs | 18 +- .../DefaultGraphQLSchemaFactory_Directives.cs | 5 +- .../Engine/DefaultGraphQLTypeMakerFactory.cs | 2 +- .../Execution/DirectiveProcessorTypeSystem.cs | 21 +- .../Generation/TypeMakers/DirectiveMaker.cs | 14 +- .../TypeMakers/GraphArgumentMaker.cs | 44 +++++ .../Generation/TypeMakers/GraphFieldMaker.cs | 42 +--- .../TypeTemplates/GraphArgumentTemplate.cs | 1 + .../Execution/RuntimeDirectiveTests.cs | 184 ++++++++++++++++++ ...timeFieldTests.cs => RuntimeFieldTests.cs} | 30 +-- .../Execution/RuntimeTypeExtensionTests.cs | 15 ++ .../SingleFieldController.cs | 23 +++ .../TypeMakers/DirectiveTypeMakerTests.cs | 107 +++++++++- .../ArgCheckExplicitInjectedItemDirective.cs | 26 +++ ...CheckExplicitInvalidSchemaItemDirective.cs | 25 +++ ...rgCheckExplicitValidSchemaItemDirective.cs | 26 +++ .../ArgCheckImplicitInjectedItemDirective.cs | 26 +++ .../ArgCheckImplicitSchemaItemDirective.cs | 26 +++ .../TestData/RepeatableDirective.cs | 1 + 19 files changed, 534 insertions(+), 102 deletions(-) create mode 100644 src/unit-tests/graphql-aspnet-tests/Execution/RuntimeDirectiveTests.cs rename src/unit-tests/graphql-aspnet-tests/Execution/{GeneralQueryExecutionRuntimeFieldTests.cs => RuntimeFieldTests.cs} (93%) create mode 100644 src/unit-tests/graphql-aspnet-tests/Execution/RuntimeTypeExtensionTests.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Execution/TestData/RuntimeDirectiveTestData/SingleFieldController.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ArgCheckExplicitInjectedItemDirective.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ArgCheckExplicitInvalidSchemaItemDirective.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ArgCheckExplicitValidSchemaItemDirective.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ArgCheckImplicitInjectedItemDirective.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ArgCheckImplicitSchemaItemDirective.cs diff --git a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory.cs b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory.cs index db9390468..42ad498ae 100644 --- a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory.cs +++ b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory.cs @@ -128,16 +128,24 @@ public virtual TSchema CreateInstance( foreach (var extension in schemaExtensions) extension.EnsureSchema(this.Schema); + // VALIDATE: Run initial validation checks to ensure schema integrity BEFORE type + // system directives are applied + // -------------------------------------- + this.ValidateSchemaIntegrity(); + // Step 5: apply all queued type system directives to the now filled schema // -------------------------------------- if (this.ProcessTypeSystemDirectives) - this.ApplyTypeSystemDirectives(); + { + var totalApplied = this.ApplyTypeSystemDirectives(); - // Step 6: Run final validations to ensure the schema is internally consistant - // -------------------------------------- - this.ValidateSchemaIntegrity(); + // VALIDATE: Run final validations to ensure the schema is internally consistant + // -------------------------------------- + if (totalApplied > 0) + this.ValidateSchemaIntegrity(); + } - // Step 7: Rebuild introspection data to match the now completed schema instance + // Step 6: Rebuild introspection data to match the now completed schema instance // -------------------------------------- if (!this.Schema.Configuration.DeclarationOptions.DisableIntrospection) this.RebuildIntrospectionData(); diff --git a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Directives.cs b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Directives.cs index 0035a512f..aab3b2468 100644 --- a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Directives.cs +++ b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Directives.cs @@ -24,13 +24,14 @@ public partial class DefaultGraphQLSchemaFactory /// type system directives. When found, applies each directive as approprate to the /// target schema item. /// - protected virtual void ApplyTypeSystemDirectives() + /// The total number of type system directives across the entire schema. + protected virtual int ApplyTypeSystemDirectives() { var processor = new DirectiveProcessorTypeSystem( this.ServiceProvider, new QuerySession()); - processor.ApplyDirectives(this.Schema); + return processor.ApplyDirectives(this.Schema); } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Engine/DefaultGraphQLTypeMakerFactory.cs b/src/graphql-aspnet/Engine/DefaultGraphQLTypeMakerFactory.cs index 900a3bd5e..871263bdf 100644 --- a/src/graphql-aspnet/Engine/DefaultGraphQLTypeMakerFactory.cs +++ b/src/graphql-aspnet/Engine/DefaultGraphQLTypeMakerFactory.cs @@ -87,7 +87,7 @@ public virtual IGraphTypeMaker CreateTypeMaker(Type objectType = null, TypeKind? this.CreateFieldMaker()); case TypeKind.DIRECTIVE: - return new DirectiveMaker(this.Schema.Configuration, this.CreateArgumentMaker()); + return new DirectiveMaker(this.Schema, this.CreateArgumentMaker()); case TypeKind.CONTROLLER: default: diff --git a/src/graphql-aspnet/Execution/DirectiveProcessorTypeSystem.cs b/src/graphql-aspnet/Execution/DirectiveProcessorTypeSystem.cs index 0bdded28d..009da89cb 100644 --- a/src/graphql-aspnet/Execution/DirectiveProcessorTypeSystem.cs +++ b/src/graphql-aspnet/Execution/DirectiveProcessorTypeSystem.cs @@ -59,26 +59,31 @@ public DirectiveProcessorTypeSystem(IServiceProvider serviceProvider, IQuerySess /// using standard directive pipeline. /// /// The schema to apply directives too. - public void ApplyDirectives(TSchema schema) + /// The total number of directives applied across the entire schema. + public int ApplyDirectives(TSchema schema) { Validation.ThrowIfNull(schema, nameof(schema)); // all schema items - var anyDirectivesApplied = false; + var totalApplied = 0; foreach (var item in schema.AllSchemaItems()) { - anyDirectivesApplied = this.ApplyDirectivesToItem(schema, item) || anyDirectivesApplied; + totalApplied += this.ApplyDirectivesToItem(schema, item); } + + return totalApplied; } /// - /// Applies the directives to item. + /// Applies queued directives to item. /// - /// The schema. - /// The item. - private bool ApplyDirectivesToItem(TSchema schema, ISchemaItem item) + /// The schema the belongs to. + /// The item to apply directives on. + /// The total number of directives applied to . + private int ApplyDirectivesToItem(TSchema schema, ISchemaItem item) { var invokedDirectives = new HashSet(); + foreach (var appliedDirective in item.AppliedDirectives) { var scopedProvider = _serviceProvider.CreateScope(); @@ -211,7 +216,7 @@ private bool ApplyDirectivesToItem(TSchema schema, ISchemaItem item) } } - return item.AppliedDirectives.Count > 0; + return item.AppliedDirectives.Count; } private IInputArgumentCollection GatherInputArguments(IDirective targetDirective, object[] arguments) diff --git a/src/graphql-aspnet/Schemas/Generation/TypeMakers/DirectiveMaker.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/DirectiveMaker.cs index 5a61d3752..0f2a4bfea 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeMakers/DirectiveMaker.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/DirectiveMaker.cs @@ -9,7 +9,6 @@ namespace GraphQL.AspNet.Schemas.Generation.TypeMakers { - using System; using System.Collections.Generic; using GraphQL.AspNet.Common; using GraphQL.AspNet.Controllers; @@ -17,7 +16,6 @@ namespace GraphQL.AspNet.Schemas.Generation.TypeMakers using GraphQL.AspNet.Interfaces.Engine; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Schemas.Generation.RuntimeSchemaItemDefinitions; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Security; @@ -26,17 +24,17 @@ namespace GraphQL.AspNet.Schemas.Generation.TypeMakers /// public class DirectiveMaker : IGraphTypeMaker { - private readonly ISchemaConfiguration _config; + private readonly ISchema _schema; private readonly IGraphArgumentMaker _argMaker; /// /// Initializes a new instance of the class. /// - /// The configuration used when setting up new directive types. + /// The schema this maker will create directives for. /// The maker used to generate new arguments on any created directives. - public DirectiveMaker(ISchemaConfiguration config, IGraphArgumentMaker argumentMaker) + public DirectiveMaker(ISchema schema, IGraphArgumentMaker argumentMaker) { - _config = Validation.ThrowIfNullOrReturn(config, nameof(config)); + _schema = Validation.ThrowIfNullOrReturn(schema, nameof(schema)); _argMaker = Validation.ThrowIfNullOrReturn(argumentMaker, nameof(argumentMaker)); } @@ -46,7 +44,7 @@ public virtual GraphTypeCreationResult CreateGraphType(IGraphTypeTemplate typeTe if (!(typeTemplate is IGraphDirectiveTemplate template)) return null; - var formatter = _config.DeclarationOptions.GraphNamingFormatter; + var formatter = _schema.Configuration.DeclarationOptions.GraphNamingFormatter; var securityGroups = new List(); @@ -72,7 +70,7 @@ public virtual GraphTypeCreationResult CreateGraphType(IGraphTypeTemplate typeTe // can use any method to fill the arg field list foreach (var argTemplate in template.Arguments) { - if (argTemplate.ArgumentModifier.CouldBePartOfTheSchema()) + if (GraphArgumentMaker.IsArgumentPartOfSchema(argTemplate, _schema)) { var argumentResult = _argMaker.CreateArgument(directive, argTemplate); directive.Arguments.AddArgument(argumentResult.Argument); diff --git a/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphArgumentMaker.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphArgumentMaker.cs index 7fabbf828..9af077396 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphArgumentMaker.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphArgumentMaker.cs @@ -89,5 +89,49 @@ public GraphArgumentCreationResult CreateArgument(ISchemaItem owner, IGraphArgum return result; } + + /// + /// Determines whether the provided argument template should be included as part of the schema. + /// + /// The argument template to evaluate. + /// The schema to evaluate against. + /// true if the template should be rendered into the schema; otherwise, false. + public static bool IsArgumentPartOfSchema(IGraphArgumentTemplate argTemplate, ISchema schema) + { + Validation.ThrowIfNull(argTemplate, nameof(argTemplate)); + Validation.ThrowIfNull(schema, nameof(schema)); + + if (argTemplate.ArgumentModifier.IsExplicitlyPartOfTheSchema()) + return true; + + if (!argTemplate.ArgumentModifier.CouldBePartOfTheSchema()) + return false; + + // teh argument contains no explicit inclusion or exclusion modifiers + // what do we do with it? + switch (schema.Configuration.DeclarationOptions.ArgumentBindingRule) + { + case Configuration.SchemaArgumentBindingRules.ParametersRequireFromGraphQLDeclaration: + + // arg didn't explicitly have [FromGraphQL] so it should NOT be part of the schema + return false; + + case Configuration.SchemaArgumentBindingRules.ParametersRequireFromServicesDeclaration: + + // arg didn't explicitly have [FromServices] so it should be part of the schema + return true; + + case Configuration.SchemaArgumentBindingRules.ParametersPreferQueryResolution: + default: + + // only exclude types that could never be correct as an input argument + // --- + // interfaces can never be valid input object types + if (argTemplate.ObjectType.IsInterface) + return false; + + return true; + } + } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphFieldMaker.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphFieldMaker.cs index 092378338..a1c4cc3b2 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphFieldMaker.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphFieldMaker.cs @@ -70,7 +70,7 @@ public virtual GraphFieldCreationResult CreateField(IGraphFieldTemp { foreach (var argTemplate in template.Arguments) { - if (this.IsArgumentPartOfSchema(argTemplate)) + if (GraphArgumentMaker.IsArgumentPartOfSchema(argTemplate, _schema)) { var argumentResult = _argMaker.CreateArgument(field, argTemplate); field.Arguments.AddArgument(argumentResult.Argument); @@ -227,45 +227,5 @@ protected virtual MethodGraphField CreateFieldInstance( throw new ArgumentOutOfRangeException($"Template field source of {template.FieldSource.ToString()} is not supported by {this.GetType().FriendlyName()}."); } } - - /// - /// Determines whether the provided argument template should be included as part of the schema. - /// - /// The argument template to evaluate. - /// true if the template should be rendered into the schema; otherwise, false. - protected virtual bool IsArgumentPartOfSchema(IGraphArgumentTemplate argTemplate) - { - if (argTemplate.ArgumentModifier.IsExplicitlyPartOfTheSchema()) - return true; - - if (!argTemplate.ArgumentModifier.CouldBePartOfTheSchema()) - return false; - - // teh argument contains no explicit inclusion or exclusion modifiers - // what do we do with it? - switch (_schema.Configuration.DeclarationOptions.ArgumentBindingRule) - { - case Configuration.SchemaArgumentBindingRules.ParametersRequireFromGraphQLDeclaration: - - // arg didn't explicitly have [FromGraphQL] so it should NOT be part of the schema - return false; - - case Configuration.SchemaArgumentBindingRules.ParametersRequireFromServicesDeclaration: - - // arg didn't explicitly have [FromServices] so it should be part of the schema - return true; - - case Configuration.SchemaArgumentBindingRules.ParametersPreferQueryResolution: - default: - - // only exclude types that could never be correct as an input argument - // --- - // interfaces can never be valid input object types - if (argTemplate.ObjectType.IsInterface) - return false; - - return true; - } - } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphArgumentTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphArgumentTemplate.cs index 05d22b085..b97952431 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphArgumentTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphArgumentTemplate.cs @@ -177,6 +177,7 @@ protected virtual bool IsCancellationTokenArgument() { if (this.ObjectType == typeof(CancellationToken)) { + // only one captured cancel token allowed if (this.Parent.Arguments.All(x => !x.ArgumentModifier.IsCancellationToken())) return true; } diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeDirectiveTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeDirectiveTests.cs new file mode 100644 index 000000000..4c39a0cc6 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeDirectiveTests.cs @@ -0,0 +1,184 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Execution +{ + using System.Collections.Generic; + using System.ComponentModel.DataAnnotations.Schema; + using System.Threading.Tasks; + using GraphQL.AspNet.Attributes; + using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Controllers.ActionResults; + using GraphQL.AspNet.Execution.Exceptions; + using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + using GraphQL.AspNet.Tests.Execution.TestData.RuntimeDirectiveTestData; + using GraphQL.AspNet.Tests.Execution.TestData.RuntimeFieldTestData; + using GraphQL.AspNet.Tests.Framework; + using Microsoft.Extensions.DependencyInjection; + using NUnit.Framework; + + [TestFixture] + public class RuntimeDirectiveTests + { + private static Dictionary _values = new Dictionary(); + + [Test] + public void Runtime_TypeSystemDirective_IsInvokedCorrectly() + { + var serverBuilder = new TestServerBuilder(); + + serverBuilder.AddGraphQL(o => + { + o.AddType(); + o.MapDirective("@myObjectDirective") + .RestrictLocations(DirectiveLocation.OBJECT) + .AddResolver((int a, int b) => + { + _values["generalTypeSystemDirective"] = a + b; + return GraphActionResult.Ok(); + }); + + o.ApplyDirective("myObjectDirective") + .ToItems(x => x.IsObjectGraphType()) + .WithArguments(5, 18); + }); + + var server = serverBuilder.Build(); + Assert.AreEqual(23, _values["generalTypeSystemDirective"]); + } + + [Test] + public void Runtime_TypeSystemDirective_InjectedService_IsInvokedCorrectly() + { + var serverBuilder = new TestServerBuilder(); + serverBuilder.AddTransient(); + + serverBuilder.AddGraphQL(o => + { + o.AddType(); + o.MapDirective("@myObjectDirective") + .RestrictLocations(DirectiveLocation.OBJECT) + .AddResolver((int a, IInjectedService service) => + { + _values["injectedService"] = a + service.FetchValue(); + return GraphActionResult.Ok(); + }); + + o.ApplyDirective("myObjectDirective") + .ToItems(x => x.IsObjectGraphType()) + .WithArguments(5); + }); + + var server = serverBuilder.Build(); + + // injected services supplies 23 + Assert.AreEqual(28, _values["injectedService"]); + } + + [Test] + public void Runtime_TypeSystemDirective_InterfaceAsExplicitSchemaItem_ThrowsException() + { + var serverBuilder = new TestServerBuilder(); + serverBuilder.AddTransient(); + + serverBuilder.AddGraphQL(o => + { + o.AddType(); + o.MapDirective("@myObjectDirective") + .RestrictLocations(DirectiveLocation.OBJECT) + .AddResolver((int a, [FromGraphQL] IInjectedService service) => + { + _values["injectedServiceWrong"] = a + service.FetchValue(); + return GraphActionResult.Ok(); + }); + + o.ApplyDirective("myObjectDirective") + .ToItems(x => x.IsObjectGraphType()) + .WithArguments(5); + }); + + Assert.Throws(() => + { + var server = serverBuilder.Build(); + }); + } + + [Test] + public async Task Runtime_ExecutionDirective_IsInvokedCorrectly() + { + var serverBuilder = new TestServerBuilder(); + serverBuilder.AddTransient(); + + serverBuilder.AddGraphQL(o => + { + o.AddController(); + o.MapDirective("@myFieldDirective") + .RestrictLocations(DirectiveLocation.FIELD) + .AddResolver(() => + { + _values["fieldDirective"] = 11; + return GraphActionResult.Ok(); + }); + }); + + var server = serverBuilder.Build(); + + var builder = server.CreateQueryContextBuilder(); + builder.AddQueryText(@"query { field @myFieldDirective }"); + + var result = await server.RenderResult(builder); + CommonAssertions.AreEqualJsonStrings( + @"{ + ""data"": { + ""field"": 99 + } + }", + result); + + Assert.AreEqual(11, _values["fieldDirective"]); + } + + [Test] + public async Task Runtime_ExecutionDirective_OnMinimalApiField_IsInvokedCorrectly() + { + var serverBuilder = new TestServerBuilder(); + serverBuilder.AddTransient(); + + serverBuilder.AddGraphQL(o => + { + o.MapQuery("field", () => 3); + + o.MapDirective("@myFieldDirective") + .RestrictLocations(DirectiveLocation.FIELD) + .AddResolver(() => + { + _values["fieldDirective"] = 11; + return GraphActionResult.Ok(); + }); + }); + + var server = serverBuilder.Build(); + + var builder = server.CreateQueryContextBuilder(); + builder.AddQueryText(@"query { field @myFieldDirective }"); + + var result = await server.RenderResult(builder); + CommonAssertions.AreEqualJsonStrings( + @"{ + ""data"": { + ""field"": 3 + } + }", + result); + + Assert.AreEqual(11, _values["fieldDirective"]); + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionRuntimeFieldTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeFieldTests.cs similarity index 93% rename from src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionRuntimeFieldTests.cs rename to src/unit-tests/graphql-aspnet-tests/Execution/RuntimeFieldTests.cs index 68718e429..9aceb10d4 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionRuntimeFieldTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeFieldTests.cs @@ -22,10 +22,8 @@ namespace GraphQL.AspNet.Tests.Execution using NUnit.Framework; [TestFixture] - public class GeneralQueryExecutionRuntimeFieldTests + public class RuntimeFieldTests { - private static int _resolvedDirectiveValue = 0; - [Test] public async Task BasicMappedQuery_ExecutesMethod() { @@ -403,31 +401,5 @@ public async Task ServiceInjectedOnControllerAction_ResolvesCorrectly() }", result); } - - [Test] - public void Runtime_TypeSystemDirective_IsInvokedCorrectly() - { - var serverBuilder = new TestServerBuilder(); - - var refData = new TwoPropertyObject(); - serverBuilder.AddGraphQL(o => - { - o.AddType(); - o.MapDirective("@myObjectDirective") - .RestrictLocations(DirectiveLocation.OBJECT) - .AddResolver((int a, int b) => - { - _resolvedDirectiveValue = a + b; - return GraphActionResult.Ok(); - }); - - o.ApplyDirective("myObjectDirective") - .ToItems(x => x.IsObjectGraphType()) - .WithArguments(5, 18); - }); - - var server = serverBuilder.Build(); - Assert.AreEqual(23, _resolvedDirectiveValue); - } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeTypeExtensionTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeTypeExtensionTests.cs new file mode 100644 index 000000000..0d08371b3 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeTypeExtensionTests.cs @@ -0,0 +1,15 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Execution +{ + public class RuntimeTypeExtensionTests + { + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/RuntimeDirectiveTestData/SingleFieldController.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/RuntimeDirectiveTestData/SingleFieldController.cs new file mode 100644 index 000000000..5874654de --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/RuntimeDirectiveTestData/SingleFieldController.cs @@ -0,0 +1,23 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Execution.TestData.RuntimeDirectiveTestData +{ + using GraphQL.AspNet.Attributes; + using GraphQL.AspNet.Controllers; + + public class SingleFieldController : GraphController + { + [QueryRoot] + public int Field() + { + return 99; + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/DirectiveTypeMakerTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/DirectiveTypeMakerTests.cs index 4f5782c52..3952b9989 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/DirectiveTypeMakerTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/DirectiveTypeMakerTests.cs @@ -9,13 +9,13 @@ namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers { + using System; using System.Linq; - using GraphQL.AspNet.Engine; + using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Execution.Resolvers; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Schemas; - using GraphQL.AspNet.Schemas.Generation; using GraphQL.AspNet.Schemas.Generation.TypeMakers; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.CommonHelpers; @@ -34,8 +34,11 @@ public void Directive_BasicPropertyCheck() var factory = server.CreateMakerFactory(); - var template = factory.MakeTemplate(typeof(MultiMethodDirective), TypeKind.DIRECTIVE); - var typeMaker = new DirectiveMaker(server.Schema.Configuration, factory.CreateArgumentMaker()); + var template = new GraphDirectiveTemplate(typeof(MultiMethodDirective)); + template.Parse(); + template.ValidateOrThrow(); + + var typeMaker = new DirectiveMaker(server.Schema, new GraphArgumentMaker(server.Schema)); var directive = typeMaker.CreateGraphType(template).GraphType as IDirective; @@ -66,10 +69,11 @@ public void Directive_RepeatableAttributeIsSetWhenPresent() var builder = new TestServerBuilder(); var server = builder.Build(); - var factory = server.CreateMakerFactory(); + var template = new GraphDirectiveTemplate(typeof(RepeatableDirective)); + template.Parse(); + template.ValidateOrThrow(); - var template = factory.MakeTemplate(typeof(RepeatableDirective), TypeKind.DIRECTIVE); - var typeMaker = new DirectiveMaker(server.Schema.Configuration, factory.CreateArgumentMaker()); + var typeMaker = new DirectiveMaker(server.Schema, new GraphArgumentMaker(server.Schema)); var directive = typeMaker.CreateGraphType(template).GraphType as IDirective; @@ -92,5 +96,92 @@ public void Directive_RepeatableAttributeIsSetWhenPresent() Assert.AreEqual("secondArg", arg1.Name); Assert.AreEqual(typeof(TwoPropertyObject), arg1.ObjectType); } + + [TestCase( + SchemaArgumentBindingRules.ParametersPreferQueryResolution, + typeof(ArgCheckImplicitSchemaItemDirective), + true)] + [TestCase( + SchemaArgumentBindingRules.ParametersPreferQueryResolution, + typeof(ArgCheckImplicitInjectedItemDirective), + false)] + [TestCase( + SchemaArgumentBindingRules.ParametersPreferQueryResolution, + typeof(ArgCheckExplicitValidSchemaItemDirective), + true)] + [TestCase( + SchemaArgumentBindingRules.ParametersPreferQueryResolution, + typeof(ArgCheckExplicitInvalidSchemaItemDirective), + true)] + [TestCase( + SchemaArgumentBindingRules.ParametersPreferQueryResolution, + typeof(ArgCheckExplicitInjectedItemDirective), + false)] + + [TestCase( + SchemaArgumentBindingRules.ParametersRequireFromServicesDeclaration, + typeof(ArgCheckImplicitSchemaItemDirective), + true)] + [TestCase( + SchemaArgumentBindingRules.ParametersRequireFromServicesDeclaration, + typeof(ArgCheckImplicitInjectedItemDirective), + true)] + [TestCase( + SchemaArgumentBindingRules.ParametersRequireFromServicesDeclaration, + typeof(ArgCheckExplicitValidSchemaItemDirective), + true)] + [TestCase( + SchemaArgumentBindingRules.ParametersRequireFromServicesDeclaration, + typeof(ArgCheckExplicitInvalidSchemaItemDirective), + true)] + [TestCase( + SchemaArgumentBindingRules.ParametersRequireFromServicesDeclaration, + typeof(ArgCheckExplicitInjectedItemDirective), + false)] + + [TestCase( + SchemaArgumentBindingRules.ParametersRequireFromGraphQLDeclaration, + typeof(ArgCheckImplicitSchemaItemDirective), + false)] + [TestCase( + SchemaArgumentBindingRules.ParametersRequireFromGraphQLDeclaration, + typeof(ArgCheckImplicitInjectedItemDirective), + false)] + [TestCase( + SchemaArgumentBindingRules.ParametersRequireFromGraphQLDeclaration, + typeof(ArgCheckExplicitValidSchemaItemDirective), + true)] + [TestCase( + SchemaArgumentBindingRules.ParametersRequireFromGraphQLDeclaration, + typeof(ArgCheckExplicitInvalidSchemaItemDirective), + true)] + [TestCase( + SchemaArgumentBindingRules.ParametersRequireFromGraphQLDeclaration, + typeof(ArgCheckExplicitInjectedItemDirective), + false)] + public void ArgInclusionCheck(SchemaArgumentBindingRules bindingRule, Type directiveType, bool shouldBeIncluded) + { + var server = new TestServerBuilder() + .AddGraphQL(o => + { + o.DeclarationOptions.ArgumentBindingRule = bindingRule; + }) + .Build(); + + var template = new GraphDirectiveTemplate(directiveType); + template.Parse(); + template.ValidateOrThrow(); + + var typeMaker = new DirectiveMaker(server.Schema, new GraphArgumentMaker(server.Schema)); + + var directive = typeMaker.CreateGraphType(template).GraphType as IDirective; + + Assert.AreEqual(TypeKind.DIRECTIVE, directive.Kind); + + if (shouldBeIncluded) + Assert.AreEqual(1, directive.Arguments.Count); + else + Assert.AreEqual(0, directive.Arguments.Count); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ArgCheckExplicitInjectedItemDirective.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ArgCheckExplicitInjectedItemDirective.cs new file mode 100644 index 000000000..437c4920b --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ArgCheckExplicitInjectedItemDirective.cs @@ -0,0 +1,26 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData +{ + using GraphQL.AspNet.Attributes; + using GraphQL.AspNet.Directives; + using GraphQL.AspNet.Interfaces.Controllers; + using GraphQL.AspNet.Schemas.TypeSystem; + using Microsoft.AspNetCore.Mvc; + + public class ArgCheckExplicitInjectedItemDirective : GraphDirective + { + [DirectiveLocations(DirectiveLocation.SCALAR)] + public IGraphActionResult ForTypeSystem([FromServices] ITestInterface1 arg1) + { + return null; + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ArgCheckExplicitInvalidSchemaItemDirective.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ArgCheckExplicitInvalidSchemaItemDirective.cs new file mode 100644 index 000000000..e591cb1c7 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ArgCheckExplicitInvalidSchemaItemDirective.cs @@ -0,0 +1,25 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData +{ + using GraphQL.AspNet.Attributes; + using GraphQL.AspNet.Directives; + using GraphQL.AspNet.Interfaces.Controllers; + using GraphQL.AspNet.Schemas.TypeSystem; + + public class ArgCheckExplicitInvalidSchemaItemDirective : GraphDirective + { + [DirectiveLocations(DirectiveLocation.SCALAR)] + public IGraphActionResult ForTypeSystem([FromGraphQL] ITestInterface1 arg1) + { + return null; + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ArgCheckExplicitValidSchemaItemDirective.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ArgCheckExplicitValidSchemaItemDirective.cs new file mode 100644 index 000000000..901a5beb9 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ArgCheckExplicitValidSchemaItemDirective.cs @@ -0,0 +1,26 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData +{ + using GraphQL.AspNet.Attributes; + using GraphQL.AspNet.Directives; + using GraphQL.AspNet.Interfaces.Controllers; + using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + + public class ArgCheckExplicitValidSchemaItemDirective : GraphDirective + { + [DirectiveLocations(DirectiveLocation.SCALAR)] + public IGraphActionResult ForTypeSystem([FromGraphQL] TwoPropertyObject arg1) + { + return null; + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ArgCheckImplicitInjectedItemDirective.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ArgCheckImplicitInjectedItemDirective.cs new file mode 100644 index 000000000..7a6e2c36c --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ArgCheckImplicitInjectedItemDirective.cs @@ -0,0 +1,26 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData +{ + using GraphQL.AspNet.Attributes; + using GraphQL.AspNet.Directives; + using GraphQL.AspNet.Interfaces.Controllers; + using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + + public class ArgCheckImplicitInjectedItemDirective : GraphDirective + { + [DirectiveLocations(DirectiveLocation.SCALAR)] + public IGraphActionResult ForTypeSystem(ITestInterface1 arg1) + { + return null; + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ArgCheckImplicitSchemaItemDirective.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ArgCheckImplicitSchemaItemDirective.cs new file mode 100644 index 000000000..21f95e6b7 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ArgCheckImplicitSchemaItemDirective.cs @@ -0,0 +1,26 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData +{ + using GraphQL.AspNet.Attributes; + using GraphQL.AspNet.Directives; + using GraphQL.AspNet.Interfaces.Controllers; + using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + + public class ArgCheckImplicitSchemaItemDirective : GraphDirective + { + [DirectiveLocations(DirectiveLocation.SCALAR)] + public IGraphActionResult ForTypeSystem(TwoPropertyObject secondArg) + { + return null; + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/RepeatableDirective.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/RepeatableDirective.cs index 51a768753..c9bd738bf 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/RepeatableDirective.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/RepeatableDirective.cs @@ -9,6 +9,7 @@ namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData { + using System.Threading; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Directives; using GraphQL.AspNet.Interfaces.Controllers; From 9cf51028cb8d6badc9ca26fff444329091dee941 Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Sun, 16 Jul 2023 08:29:18 -0700 Subject: [PATCH 39/63] WIP, minimal api security check tests added. Fixed batches as well. --- .../Common/Extensions/TypeExtensions.cs | 46 +- ...ItemDefinitionExtensions_TypeExtensions.cs | 30 +- .../ActionResults/Batching/BatchBuilder.cs | 7 +- .../Batching/BatchBuilder{TSource,TKey}.cs | 8 +- .../BatchBuilder{TSource,TResult,TKey}.cs | 81 +--- ...CompleteBatchOperationGraphActionResult.cs | 127 ++++++ .../ActionResults/GraphActionResult.cs | 6 +- .../GraphController_ActionResults.cs | 2 +- .../RuntimeDirectiveActionDefinition.cs | 2 +- .../RuntimeResolvedFieldDefinition.cs | 2 +- .../RuntimeTypeExtensionDefinition.cs | 10 +- .../RuntimeVirtualFieldTemplate.cs | 2 +- .../GraphTypeExtensionFieldTemplate.cs | 11 + .../RuntimeSchemaItemAttributeProvider.cs | 3 +- .../TypeTemplates/SchemaItemTemplateBase.cs | 2 +- .../Execution/RuntimeDirectiveTests.cs | 115 ++++- .../Execution/RuntimeFieldTests.cs | 85 ++++ .../Execution/RuntimeTypeExtensionTests.cs | 392 ++++++++++++++++++ .../ChildObject.cs | 18 + ...untimeFieldTypeExtensionTestsController.cs | 85 ++++ .../ResolvedFieldTemplateTests.cs | 12 + .../PersonAttribute.cs | 17 + .../TeacherAttribute.cs | 15 + ...RuntimeSchemaItemAttributeProviderTests.cs | 85 ++++ 24 files changed, 1038 insertions(+), 125 deletions(-) create mode 100644 src/graphql-aspnet/Controllers/ActionResults/CompleteBatchOperationGraphActionResult.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Execution/TestData/RuntimeTypeExtensionTestData/ChildObject.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Execution/TestData/RuntimeTypeExtensionTestData/RuntimeFieldTypeExtensionTestsController.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/RuntimeSchemaItemAttributeProviderTestData/PersonAttribute.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/RuntimeSchemaItemAttributeProviderTestData/TeacherAttribute.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/RuntimeSchemaItemAttributeProviderTests.cs diff --git a/src/graphql-aspnet/Common/Extensions/TypeExtensions.cs b/src/graphql-aspnet/Common/Extensions/TypeExtensions.cs index d3b24852b..980465f2d 100644 --- a/src/graphql-aspnet/Common/Extensions/TypeExtensions.cs +++ b/src/graphql-aspnet/Common/Extensions/TypeExtensions.cs @@ -105,16 +105,16 @@ public static TAttribute SingleAttributeOrDefault(this Enum enumValu /// is also returned. /// /// The type of the attribute to check for. - /// The type to inspect. + /// The type to inspect. /// When true, look up the hierarchy chain for the inherited custom attribute.. /// TAttribute. - public static TAttribute SingleAttributeOrDefault(this ICustomAttributeProvider type, bool inherit = false) + public static TAttribute SingleAttributeOrDefault(this ICustomAttributeProvider attribProvider, bool inherit = false) where TAttribute : Attribute { - if (type == null) + if (attribProvider == null) return null; - var attribs = type.GetCustomAttributes(typeof(TAttribute), inherit) + var attribs = attribProvider.GetCustomAttributes(typeof(TAttribute), inherit) .Where(x => x.GetType() == typeof(TAttribute)) .Take(2); @@ -129,16 +129,16 @@ public static TAttribute SingleAttributeOrDefault(this ICustomAttrib /// that is castable to the given type, the first instance encountered is returned. /// /// The type of the attribute to check for. - /// The type to inspect. + /// The type to inspect. /// When true, look up the hierarchy chain for the inherited custom attribute.. /// TAttribute. - public static TAttribute FirstAttributeOfTypeOrDefault(this ICustomAttributeProvider type, bool inherit = false) + public static TAttribute FirstAttributeOfTypeOrDefault(this ICustomAttributeProvider attribProvider, bool inherit = false) where TAttribute : Attribute { - if (type == null) + if (attribProvider == null) return null; - var attribs = type.GetCustomAttributes(typeof(TAttribute), inherit).Where(x => x.GetType() == typeof(TAttribute)).Take(2); + var attribs = attribProvider.GetCustomAttributes(typeof(TAttribute), inherit).Where(x => x.GetType() == typeof(TAttribute)).Take(2); return attribs.FirstOrDefault() as TAttribute; } @@ -147,16 +147,16 @@ public static TAttribute FirstAttributeOfTypeOrDefault(this ICustomA /// that matches the type condition, null is returned. /// /// The type of the attribute to check for. - /// The type to inspect. + /// The type to inspect. /// When true, look up the hierarchy chain for the inherited custom attribute.. /// TAttribute. - public static TAttribute SingleAttributeOfTypeOrDefault(this ICustomAttributeProvider type, bool inherit = false) + public static TAttribute SingleAttributeOfTypeOrDefault(this ICustomAttributeProvider attribProvider, bool inherit = false) where TAttribute : Attribute { - if (type == null) + if (attribProvider == null) return null; - var attribs = type.GetCustomAttributes(typeof(TAttribute), inherit).Cast().Take(2); + var attribs = attribProvider.GetCustomAttributes(typeof(TAttribute), inherit).Cast().Take(2); if (attribs.Count() == 1) return attribs.Single(); @@ -168,16 +168,16 @@ public static TAttribute SingleAttributeOfTypeOrDefault(this ICustom /// the given an empty set is returned. /// /// The type of the attribute to check for. - /// The type from which to extract attributes. + /// The type from which to extract attributes. /// When true, look up the hierarchy chain for the inherited custom attribute.. /// TAttribute. - public static IEnumerable AttributesOfType(this ICustomAttributeProvider type, bool inherit = false) + public static IEnumerable AttributesOfType(this ICustomAttributeProvider attribProvider, bool inherit = false) where TAttribute : Attribute { - if (type == null) + if (attribProvider == null) return null; - var attribs = type.GetCustomAttributes(typeof(TAttribute), inherit) + var attribs = attribProvider.GetCustomAttributes(typeof(TAttribute), inherit) .Where(x => Validation.IsCastable(x.GetType(), typeof(TAttribute))) .Cast(); @@ -188,28 +188,28 @@ public static IEnumerable AttributesOfType(this ICustomA /// Determines if the given type had the attribute defined at least once. /// /// The type of the attribute. - /// The type from which to check. + /// The type from which to check. /// When true, look up the hierarchy chain for the inherited custom attribute.. /// TAttribute. - public static bool HasAttribute(this ICustomAttributeProvider type, bool inherit = false) + public static bool HasAttribute(this ICustomAttributeProvider attribProvider, bool inherit = false) where TAttribute : Attribute { - return type.HasAttribute(typeof(TAttribute), inherit); + return attribProvider.HasAttribute(typeof(TAttribute), inherit); } /// /// Determines if the given type had the attribute defined at least once. /// - /// The type to check. + /// The type to check. /// Type of the attribute. /// When true, look up the hierarchy chain for the inherited custom attribute.. /// TAttribute. - public static bool HasAttribute(this ICustomAttributeProvider type, Type attributeType, bool inherit = false) + public static bool HasAttribute(this ICustomAttributeProvider attribProvider, Type attributeType, bool inherit = false) { - if (type == null || attributeType == null || !Validation.IsCastable(attributeType)) + if (attribProvider == null || attributeType == null || !Validation.IsCastable(attributeType)) return false; - return type.IsDefined(attributeType, inherit); + return attribProvider.IsDefined(attributeType, inherit); } /// diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_TypeExtensions.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_TypeExtensions.cs index a5d06acb0..bf9e24144 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_TypeExtensions.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_TypeExtensions.cs @@ -14,6 +14,7 @@ namespace GraphQL.AspNet.Configuration using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Common; using GraphQL.AspNet.Execution; + using GraphQL.AspNet.Interfaces.Configuration; using GraphQL.AspNet.Interfaces.Controllers; using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; using Microsoft.AspNetCore.Authorization; @@ -100,7 +101,34 @@ public static IGraphQLRuntimeTypeExtensionDefinition AddResolver(th } /// - /// Registers a new type extension to a given type for the target schema. + /// Registers a new type extension to a given OBJECT or INTERFACE type for the target schema. + /// + /// + /// + /// This method is synonymous with using the on + /// a controller action. + /// + /// + /// The supplied resolver must declare a parameter that is of the same type as . + /// + /// + /// The concrete interface, class or struct to extend with a new field. + /// The schema builder to append the field to. + /// Name of the field to add to the . + /// The resolver method to be called when the field is requested. + /// IGraphQLResolvedFieldTemplate. + public static IGraphQLRuntimeTypeExtensionDefinition MapField(this ISchemaBuilder builder, string fieldName, Delegate resolverMethod = null) + { + Validation.ThrowIfNull(builder, nameof(builder)); + + return builder.Options.MapField( + typeof(TOwnerType), + fieldName, + resolverMethod); + } + + /// + /// Registers a new type extension to a given OBJECT or INTERFACE type for the target schema. /// /// /// diff --git a/src/graphql-aspnet/Controllers/ActionResults/Batching/BatchBuilder.cs b/src/graphql-aspnet/Controllers/ActionResults/Batching/BatchBuilder.cs index 0f342794d..2eb32e105 100644 --- a/src/graphql-aspnet/Controllers/ActionResults/Batching/BatchBuilder.cs +++ b/src/graphql-aspnet/Controllers/ActionResults/Batching/BatchBuilder.cs @@ -21,9 +21,8 @@ public class BatchBuilder : BatchBuilder /// /// Initializes a new instance of the class. /// - /// The field for witch this batch is being produced. - public BatchBuilder(IGraphField field) - : base(field, null, null, null, null) + public BatchBuilder() + : base(null, null, null, null) { } @@ -39,7 +38,7 @@ public BatchBuilder(IGraphField field) /// A batch builder with a given set of source data. public BatchBuilder FromSource(IEnumerable sourceData, Func sourceKeySelector) { - return new BatchBuilder(this.Field, sourceData, sourceKeySelector); + return new BatchBuilder(sourceData, sourceKeySelector); } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Controllers/ActionResults/Batching/BatchBuilder{TSource,TKey}.cs b/src/graphql-aspnet/Controllers/ActionResults/Batching/BatchBuilder{TSource,TKey}.cs index 838ebbae8..2847c397a 100644 --- a/src/graphql-aspnet/Controllers/ActionResults/Batching/BatchBuilder{TSource,TKey}.cs +++ b/src/graphql-aspnet/Controllers/ActionResults/Batching/BatchBuilder{TSource,TKey}.cs @@ -24,11 +24,10 @@ public class BatchBuilder : BatchBuilder /// /// Initializes a new instance of the class. /// - /// The field for witch this batch is being produced. /// The source data. /// A function to extract a single key value from each source item. - public BatchBuilder(IGraphField field, IEnumerable sourceData, Func sourceKeySelector) - : base(field, sourceData, null, sourceKeySelector, null) + public BatchBuilder(IEnumerable sourceData, Func sourceKeySelector) + : base(sourceData, null, sourceKeySelector, null) { } @@ -45,7 +44,6 @@ public BatchBuilder WithResults(IEnumerable( - this.Field, this.SourceData, resultData, this.SourceKeySelector, @@ -64,7 +62,7 @@ public BatchBuilder WithResults(IEnumerable WithResults(IEnumerable resultData, Func> resultKeySelector) where TResult : class { - return new BatchBuilder(this.Field, this.SourceData, resultData, this.SourceKeySelector, resultKeySelector); + return new BatchBuilder(this.SourceData, resultData, this.SourceKeySelector, resultKeySelector); } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Controllers/ActionResults/Batching/BatchBuilder{TSource,TResult,TKey}.cs b/src/graphql-aspnet/Controllers/ActionResults/Batching/BatchBuilder{TSource,TResult,TKey}.cs index fca27b2da..6eef553ea 100644 --- a/src/graphql-aspnet/Controllers/ActionResults/Batching/BatchBuilder{TSource,TResult,TKey}.cs +++ b/src/graphql-aspnet/Controllers/ActionResults/Batching/BatchBuilder{TSource,TResult,TKey}.cs @@ -11,9 +11,7 @@ namespace GraphQL.AspNet.Controllers.ActionResults.Batching { using System; using System.Collections.Generic; - using System.Linq; using GraphQL.AspNet.Interfaces.Controllers; - using GraphQL.AspNet.Interfaces.Schema; /// /// A builder to help construct a batch result for a field that can be properly dispursed to the source items in the batch. @@ -26,19 +24,16 @@ public class BatchBuilder : IBatchBuilder /// /// Initializes a new instance of the class. /// - /// The field for witch this batch is being produced. /// The source data. /// The result data. /// The source key selector. /// The result key selector. public BatchBuilder( - IGraphField field, IEnumerable sourceData, IEnumerable resultData, Func sourceKeySelector, Func> resultKeySelector) { - this.Field = field; this.SourceData = sourceData; this.ResultData = resultData; this.SourceKeySelector = sourceKeySelector; @@ -54,92 +49,24 @@ public IGraphActionResult Complete() if (this.SourceData == null) { return new InternalServerErrorGraphActionResult("The source data list, when attempting to finalize a " + - $"batch for field '{this.Field.Name}', was null."); + $"batch was null."); } if (this.SourceKeySelector == null) { return new InternalServerErrorGraphActionResult("The source key locator, when attempting to finalize a " + - $"batch for field '{this.Field.Name}', was null."); + $"batch was null."); } if (this.ResultData != null && this.ResultKeySelector == null) { return new InternalServerErrorGraphActionResult("The result key locator, when attempting to finalize a " + - $"batch for field '{this.Field.Name}', was null."); + $"batch was null."); } - var dictionary = new Dictionary(); - - // key out the results - var resultsByKey = new Dictionary>(); - if (this.ResultData != null) - { - // N:N relationships should complete in O(M) - // where M is the total number of keys defined across all instances - // - // 1:N relationships it should process in O(N) - // where N is the number of result items - foreach (var item in this.ResultData) - { - if (item == null) - continue; - - var keys = this.ResultKeySelector(item) ?? Enumerable.Empty(); - foreach (var key in keys) - { - if (key == null) - continue; - - if (!resultsByKey.ContainsKey(key)) - resultsByKey.Add(key, new HashSet()); - - resultsByKey[key].Add(item); - } - } - } - - var fieldReturnsAList = this.Field.TypeExpression.IsListOfItems; - - // add each source item to the reslt dictionary pulling in hte matching items from - // the results set and ensuring list vs no list depending on the executed field. - foreach (var sourceItem in this.SourceData) - { - object sourceResults = null; - var key = this.SourceKeySelector(sourceItem); - var lookupResults = resultsByKey.ContainsKey(key) ? resultsByKey[key] : null; - if (lookupResults != null) - { - if (fieldReturnsAList) - { - sourceResults = lookupResults.ToList(); - } - else - { - if (lookupResults.Count > 1) - { - return new InternalServerErrorGraphActionResult( - $"Invalid field resolution. When attempting to finalize a batch for field '{this.Field.Name}', " + - $"a source item with key '{key}' had {lookupResults.Count} result(s) in the batch was expected to have " + - "a single item."); - } - - sourceResults = lookupResults.FirstOrDefault(); - } - } - - dictionary.Add(sourceItem, sourceResults); - } - - return new OperationCompleteGraphActionResult(dictionary); + return new CompleteBatchOperationGraphActionResult(this); } - /// - /// Gets the field for witch this batch is being produced. - /// - /// The field. - public IGraphField Field { get; } - /// /// Gets or sets the source data. /// diff --git a/src/graphql-aspnet/Controllers/ActionResults/CompleteBatchOperationGraphActionResult.cs b/src/graphql-aspnet/Controllers/ActionResults/CompleteBatchOperationGraphActionResult.cs new file mode 100644 index 000000000..d39b0a37b --- /dev/null +++ b/src/graphql-aspnet/Controllers/ActionResults/CompleteBatchOperationGraphActionResult.cs @@ -0,0 +1,127 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Controllers.ActionResults +{ + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using GraphQL.AspNet.Common.Extensions; + using GraphQL.AspNet.Controllers.ActionResults.Batching; + using GraphQL.AspNet.Execution.Contexts; + using GraphQL.AspNet.Execution.RulesEngine.RuleSets.FieldResolution.FieldValidation; + using GraphQL.AspNet.Interfaces.Controllers; + + public class CompleteBatchOperationGraphActionResult : IGraphActionResult + { + private readonly BatchBuilder _batchBuilder; + + /// + /// Initializes a new instance of the class. + /// + /// The batch builder. + public CompleteBatchOperationGraphActionResult(BatchBuilder batchBuilder) + { + _batchBuilder = batchBuilder; + } + + /// + public Task CompleteAsync(SchemaItemResolutionContext context) + { + + if (!(context is FieldResolutionContext frc)) + { + context.Messages.Critical( + $"Batch Operations cannot be completed against a resolution context of type {context?.GetType().FriendlyName()}", + Constants.ErrorCodes.INVALID_BATCH_RESULT, + context.Request.Origin); + return Task.CompletedTask; + } + + if (_batchBuilder == null) + { + context.Messages.Critical( + $"No batch builder was provided. Unable to complete the requested batch operation.", + Constants.ErrorCodes.INVALID_BATCH_RESULT, + frc.Request.Origin); + return Task.CompletedTask; + } + + var field = frc.Request.Field; + var dictionary = new Dictionary(); + + // key out the results + var resultsByKey = new Dictionary>(); + if (_batchBuilder.ResultData != null) + { + // N:N relationships should complete in O(M) + // where M is the total number of keys defined across all instances + // + // 1:N relationships it should process in O(N) + // where N is the number of result items + foreach (var item in _batchBuilder.ResultData) + { + if (item == null) + continue; + + var keys = _batchBuilder.ResultKeySelector(item) ?? Enumerable.Empty(); + foreach (var key in keys) + { + if (key == null) + continue; + + if (!resultsByKey.ContainsKey(key)) + resultsByKey.Add(key, new HashSet()); + + resultsByKey[key].Add(item); + } + } + } + + var fieldReturnsAList = field.TypeExpression.IsListOfItems; + + // add each source item to the reslt dictionary pulling in hte matching items from + // the results set and ensuring list vs no list depending on the executed field. + foreach (var sourceItem in _batchBuilder.SourceData) + { + object sourceResults = null; + var key = _batchBuilder.SourceKeySelector(sourceItem); + var lookupResults = resultsByKey.ContainsKey(key) ? resultsByKey[key] : null; + if (lookupResults != null) + { + if (fieldReturnsAList) + { + sourceResults = lookupResults.ToList(); + } + else + { + if (lookupResults.Count > 1) + { + frc.Messages.Critical( + $"Invalid field resolution. When attempting to finalize a batch for field '{field.Name}', " + + $"a source item with key '{key}' had {lookupResults.Count} result(s) in the batch was expected to have " + + "a single item.", + Constants.ErrorCodes.INVALID_BATCH_RESULT, + frc.Request.Origin); + + return Task.CompletedTask; + } + + sourceResults = lookupResults.FirstOrDefault(); + } + } + + dictionary.Add(sourceItem, sourceResults); + } + + frc.Result = dictionary; + return Task.CompletedTask; + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Controllers/ActionResults/GraphActionResult.cs b/src/graphql-aspnet/Controllers/ActionResults/GraphActionResult.cs index 8ba8e8842..eb37bf6f5 100644 --- a/src/graphql-aspnet/Controllers/ActionResults/GraphActionResult.cs +++ b/src/graphql-aspnet/Controllers/ActionResults/GraphActionResult.cs @@ -137,12 +137,10 @@ public static IGraphActionResult Unauthorized(string message = null, string erro /// generated indicating an issue if the batch produced cannot fulfill the requirements of the field. /// This method will not throw an exception. /// - /// The graph field the batch will be built for. /// IGraphActionResult. - public static BatchBuilder StartBatch(IGraphField targetField) + public static BatchBuilder StartBatch() { - Validation.ThrowIfNull(targetField, nameof(targetField)); - return new BatchBuilder(targetField); + return new BatchBuilder(); } /// diff --git a/src/graphql-aspnet/Controllers/GraphController_ActionResults.cs b/src/graphql-aspnet/Controllers/GraphController_ActionResults.cs index d76a88f04..0338af2a1 100644 --- a/src/graphql-aspnet/Controllers/GraphController_ActionResults.cs +++ b/src/graphql-aspnet/Controllers/GraphController_ActionResults.cs @@ -149,7 +149,7 @@ protected virtual IGraphActionResult Unauthorized(string message = null, string /// IGraphActionResult. protected virtual BatchBuilder StartBatch() { - return GraphActionResult.StartBatch(this.Request.InvocationContext.Field); + return GraphActionResult.StartBatch(); } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeDirectiveActionDefinition.cs b/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeDirectiveActionDefinition.cs index 3427c784d..507299a4a 100644 --- a/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeDirectiveActionDefinition.cs +++ b/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeDirectiveActionDefinition.cs @@ -22,7 +22,7 @@ namespace GraphQL.AspNet.Schemas.Generation.RuntimeSchemaItemDefinitions /// An internal implementation of the /// used to generate new graphql directives via a minimal api style of coding. /// - [DebuggerDisplay("{Template}")] + [DebuggerDisplay("{Route.Path}")] internal class RuntimeDirectiveActionDefinition : BaseRuntimeControllerActionDefinition, IGraphQLRuntimeDirectiveDefinition { /// diff --git a/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeResolvedFieldDefinition.cs b/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeResolvedFieldDefinition.cs index c97aa4bfd..5f4f5f489 100644 --- a/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeResolvedFieldDefinition.cs +++ b/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeResolvedFieldDefinition.cs @@ -22,7 +22,7 @@ namespace GraphQL.AspNet.Schemas.Generation.RuntimeSchemaItemDefinitions /// An internal implementation of the /// used to generate new graphql fields via a minimal api style of coding. /// - [DebuggerDisplay("{Template}")] + [DebuggerDisplay("{Route.Path}")] internal class RuntimeResolvedFieldDefinition : BaseRuntimeControllerActionDefinition, IGraphQLRuntimeResolvedFieldDefinition { /// diff --git a/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeTypeExtensionDefinition.cs b/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeTypeExtensionDefinition.cs index 129613d0d..982ddfca7 100644 --- a/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeTypeExtensionDefinition.cs +++ b/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeTypeExtensionDefinition.cs @@ -14,6 +14,7 @@ namespace GraphQL.AspNet.Schemas.Generation.RuntimeSchemaItemDefinitions using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Execution; + using GraphQL.AspNet.Execution.RulesEngine.RuleSets.DocumentValidation.QueryInputValueSteps; using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Schemas.Structural; @@ -23,7 +24,7 @@ namespace GraphQL.AspNet.Schemas.Generation.RuntimeSchemaItemDefinitions /// An internal implementation of the /// used to generate new type extensions via a minimal api style of coding. /// - [DebuggerDisplay("{Template}")] + [DebuggerDisplay("{Route.Path}")] internal class RuntimeTypeExtensionDefinition : RuntimeResolvedFieldDefinition, IGraphQLRuntimeTypeExtensionDefinition { /// @@ -46,6 +47,7 @@ public RuntimeTypeExtensionDefinition( GraphTypeNames.ParseName(typeToExtend, TypeKind.OBJECT), fieldName)) { + _fieldName = fieldName; this.ExecutionMode = resolutionMode; this.TargetType = typeToExtend; } @@ -56,10 +58,10 @@ protected override Attribute CreatePrimaryAttribute() switch (this.ExecutionMode) { case FieldResolutionMode.PerSourceItem: - return new TypeExtensionAttribute(this.TargetType, this.Route.Name, this.ReturnType); + return new TypeExtensionAttribute(this.TargetType, _fieldName, this.ReturnType); case FieldResolutionMode.Batch: - return new BatchTypeExtensionAttribute(this.TargetType, this.Route.Name, this.ReturnType); + return new BatchTypeExtensionAttribute(this.TargetType, _fieldName, this.ReturnType); default: throw new NotSupportedException( @@ -68,6 +70,8 @@ protected override Attribute CreatePrimaryAttribute() } } + private readonly string _fieldName; + /// public FieldResolutionMode ExecutionMode { get; set; } diff --git a/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeVirtualFieldTemplate.cs b/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeVirtualFieldTemplate.cs index 24913b4e1..cfcd5ea5e 100644 --- a/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeVirtualFieldTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeVirtualFieldTemplate.cs @@ -19,7 +19,7 @@ namespace GraphQL.AspNet.Schemas.Generation.RuntimeSchemaItemDefinitions /// An internal implementation of the /// used to generate new graphql fields via a minimal api style of coding. /// - [DebuggerDisplay("{Template}")] + [DebuggerDisplay("{Route.Path}")] internal class RuntimeVirtualFieldTemplate : BaseRuntimeControllerActionDefinition, IGraphQLRuntimeFieldDefinition { /// diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphTypeExtensionFieldTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphTypeExtensionFieldTemplate.cs index e59ecd899..f6ee6b1a3 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphTypeExtensionFieldTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphTypeExtensionFieldTemplate.cs @@ -10,6 +10,7 @@ namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates { using System; + using System.Linq; using System.Reflection; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Common.Extensions; @@ -108,6 +109,16 @@ public override void ValidateOrThrow() "Only classes, structs and interfaces can be extended."); } + // a specialized redeclaration of this rule on the type extension to + // better contextualize the message to be just the template value + if (this.Route == null || !this.Route.IsValid) + { + throw new GraphTypeDeclarationException( + $"The type extension '{this.InternalFullName}' declares an invalid field name of '{_typeAttrib.Template ?? ""}'. " + + $"Each segment of the route must conform to standard graphql naming rules. (Regex: {Constants.RegExPatterns.NameRegex} )", + this.ObjectType); + } + base.ValidateOrThrow(); } diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/RuntimeSchemaItemAttributeProvider.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/RuntimeSchemaItemAttributeProvider.cs index f6b5941a2..c1713c017 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/RuntimeSchemaItemAttributeProvider.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/RuntimeSchemaItemAttributeProvider.cs @@ -70,10 +70,11 @@ public object[] GetCustomAttributes(Type attributeType, bool inherit) /// public bool IsDefined(Type attributeType, bool inherit) { + // MemberInfo defines this method to be the type or one that inherits from it var attribs = this.GetCustomAttributes(inherit); foreach (var attrib in attribs) { - if (attrib?.GetType() == attributeType) + if (attrib?.GetType() != null && Validation.IsCastable(attrib.GetType(), attributeType)) return true; } diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/SchemaItemTemplateBase.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/SchemaItemTemplateBase.cs index d16a767a5..72636ffcf 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/SchemaItemTemplateBase.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/SchemaItemTemplateBase.cs @@ -102,7 +102,7 @@ public virtual void ValidateOrThrow() if (this.Route == null || !this.Route.IsValid) { throw new GraphTypeDeclarationException( - $"The template item '{this.InternalFullName}' declares an invalid route of '{this.Route?.Path ?? ""}'. " + + $"The template item '{this.InternalFullName}' declares an invalid route of '{this.Route?.Raw ?? ""}'. " + $"Each segment of the route must conform to standard graphql naming rules. (Regex: {Constants.RegExPatterns.NameRegex} )", this.ObjectType); } diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeDirectiveTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeDirectiveTests.cs index 4c39a0cc6..5be47781f 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeDirectiveTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeDirectiveTests.cs @@ -15,6 +15,7 @@ namespace GraphQL.AspNet.Tests.Execution using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Controllers.ActionResults; + using GraphQL.AspNet.Execution; using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Tests.Common.CommonHelpers; @@ -114,7 +115,6 @@ public void Runtime_TypeSystemDirective_InterfaceAsExplicitSchemaItem_ThrowsExce public async Task Runtime_ExecutionDirective_IsInvokedCorrectly() { var serverBuilder = new TestServerBuilder(); - serverBuilder.AddTransient(); serverBuilder.AddGraphQL(o => { @@ -149,7 +149,6 @@ public async Task Runtime_ExecutionDirective_IsInvokedCorrectly() public async Task Runtime_ExecutionDirective_OnMinimalApiField_IsInvokedCorrectly() { var serverBuilder = new TestServerBuilder(); - serverBuilder.AddTransient(); serverBuilder.AddGraphQL(o => { @@ -180,5 +179,117 @@ public async Task Runtime_ExecutionDirective_OnMinimalApiField_IsInvokedCorrectl Assert.AreEqual(11, _values["fieldDirective"]); } + + [Test] + public async Task Runtime_ExecutionDirective_WithSecurityParams_AndAllowedUser_ResolvesCorrectly() + { + var serverBuilder = new TestServerBuilder(); + + serverBuilder.AddGraphQL(o => + { + o.MapQuery("field", () => 3); + + o.MapDirective("@secureDirective") + .RestrictLocations(DirectiveLocation.FIELD) + .RequireAuthorization("policy1") + .AddResolver(() => + { + _values["secureDirective1"] = 11; + return GraphActionResult.Ok(); + }); + }); + + serverBuilder.Authorization.AddClaimPolicy("policy1", "policy1Claim", "policy1Value"); + serverBuilder.UserContext + .Authenticate() + .AddUserClaim("policy1Claim", "policy1Value"); + + var server = serverBuilder.Build(); + + var builder = server.CreateQueryContextBuilder(); + builder.AddQueryText(@"query { field @secureDirective }"); + + var result = await server.RenderResult(builder); + CommonAssertions.AreEqualJsonStrings( + @"{ + ""data"": { + ""field"": 3 + } + }", + result); + + Assert.AreEqual(11, _values["secureDirective1"]); + } + + [Test] + public async Task Runtime_ExecutionDirective_WithSecurityParams_AndUnAuthenticatedUser_RendersAccessDenied() + { + var serverBuilder = new TestServerBuilder(); + + serverBuilder.AddGraphQL(o => + { + o.MapQuery("field", () => 3); + + o.MapDirective("@secureDirective") + .RestrictLocations(DirectiveLocation.FIELD) + .RequireAuthorization("policy1") + .AddResolver(() => + { + _values["secureDirective2"] = 11; + return GraphActionResult.Ok(); + }); + }); + + // no user authentication added + serverBuilder.Authorization.AddClaimPolicy("policy1", "policy1Claim", "policy1Value"); + + var server = serverBuilder.Build(); + + var builder = server.CreateQueryContextBuilder(); + builder.AddQueryText(@"query { field @secureDirective }"); + + var result = await server.ExecuteQuery(builder); + Assert.IsFalse(_values.ContainsKey("secureDirective2")); + Assert.AreEqual(1, result.Messages.Count); + Assert.AreEqual(GraphMessageSeverity.Critical, result.Messages[0].Severity); + Assert.AreEqual(Constants.ErrorCodes.ACCESS_DENIED, result.Messages[0].Code); + } + + [Test] + public async Task Runtime_ExecutionDirective_WithSecurityParams_AndUnAuthorizedUser_RendersAccessDenied() + { + var serverBuilder = new TestServerBuilder(); + + serverBuilder.AddGraphQL(o => + { + o.MapQuery("field", () => 3); + + o.MapDirective("@secureDirective") + .RestrictLocations(DirectiveLocation.FIELD) + .RequireAuthorization("policy1") + .AddResolver(() => + { + _values["secureDirective3"] = 11; + return GraphActionResult.Ok(); + }); + }); + + // wrong policy value + serverBuilder.Authorization.AddClaimPolicy("policy1", "policy1Claim", "policy1Value"); + serverBuilder.UserContext + .Authenticate() + .AddUserClaim("policy1Claim", "policy2Value"); + + var server = serverBuilder.Build(); + + var builder = server.CreateQueryContextBuilder(); + builder.AddQueryText(@"query { field @secureDirective }"); + + var result = await server.ExecuteQuery(builder); + Assert.IsFalse(_values.ContainsKey("secureDirective3")); + Assert.AreEqual(1, result.Messages.Count); + Assert.AreEqual(GraphMessageSeverity.Critical, result.Messages[0].Severity); + Assert.AreEqual(Constants.ErrorCodes.ACCESS_DENIED, result.Messages[0].Code); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeFieldTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeFieldTests.cs index 9aceb10d4..dd788ce68 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeFieldTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeFieldTests.cs @@ -12,6 +12,7 @@ namespace GraphQL.AspNet.Tests.Execution using System.Threading.Tasks; using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Controllers.ActionResults; + using GraphQL.AspNet.Execution; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Execution.TestData.RuntimeFieldTest; @@ -401,5 +402,89 @@ public async Task ServiceInjectedOnControllerAction_ResolvesCorrectly() }", result); } + + [Test] + public async Task Runtime_StandardField_WithSecurityParams_AndAllowedUser_ResolvesCorrectly() + { + var serverBuilder = new TestServerBuilder(); + + serverBuilder.AddGraphQL(o => + { + o.MapQuery("secureField", () => 3) + .RequireAuthorization("policy1"); + }); + + serverBuilder.Authorization.AddClaimPolicy("policy1", "policy1Claim", "policy1Value"); + serverBuilder.UserContext + .Authenticate() + .AddUserClaim("policy1Claim", "policy1Value"); + + var server = serverBuilder.Build(); + + var builder = server.CreateQueryContextBuilder(); + builder.AddQueryText(@"query { secureField }"); + + var result = await server.RenderResult(builder); + CommonAssertions.AreEqualJsonStrings( + @"{ + ""data"": { + ""secureField"": 3 + } + }", + result); + } + + [Test] + public async Task Runtime_StandardField_WithSecurityParams_AndUnAuthenticatedUser_RendersAccessDenied() + { + var serverBuilder = new TestServerBuilder(); + + serverBuilder.AddGraphQL(o => + { + o.MapQuery("secureField", () => 3) + .RequireAuthorization("policy1"); + }); + + // no user authentication added + serverBuilder.Authorization.AddClaimPolicy("policy1", "policy1Claim", "policy1Value"); + + var server = serverBuilder.Build(); + + var builder = server.CreateQueryContextBuilder(); + builder.AddQueryText(@"query { secureField }"); + + var result = await server.ExecuteQuery(builder); + Assert.AreEqual(1, result.Messages.Count); + Assert.AreEqual(GraphMessageSeverity.Critical, result.Messages[0].Severity); + Assert.AreEqual(Constants.ErrorCodes.ACCESS_DENIED, result.Messages[0].Code); + } + + [Test] + public async Task Runtime_StandardField_WithSecurityParams_AndUnAuthorizedUser_RendersAccessDenied() + { + var serverBuilder = new TestServerBuilder(); + + serverBuilder.AddGraphQL(o => + { + o.MapQuery("secureField", () => 3) + .RequireAuthorization("policy1"); + }); + + // wrong claim value on user + serverBuilder.Authorization.AddClaimPolicy("policy1", "policy1Claim", "policy1Value"); + serverBuilder.UserContext + .Authenticate() + .AddUserClaim("policy1Claim", "policy2Value"); + + var server = serverBuilder.Build(); + + var builder = server.CreateQueryContextBuilder(); + builder.AddQueryText(@"query { secureField }"); + + var result = await server.ExecuteQuery(builder); + Assert.AreEqual(1, result.Messages.Count); + Assert.AreEqual(GraphMessageSeverity.Critical, result.Messages[0].Severity); + Assert.AreEqual(Constants.ErrorCodes.ACCESS_DENIED, result.Messages[0].Code); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeTypeExtensionTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeTypeExtensionTests.cs index 0d08371b3..fcc553d2d 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeTypeExtensionTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeTypeExtensionTests.cs @@ -9,7 +9,399 @@ namespace GraphQL.AspNet.Tests.Execution { + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Controllers.ActionResults; + using GraphQL.AspNet.Execution; + using GraphQL.AspNet.Execution.Exceptions; + using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + using GraphQL.AspNet.Tests.Execution.TestData.RuntimeTypeExtensionTestData; + using GraphQL.AspNet.Tests.Framework; + using Microsoft.AspNetCore.Hosting.Server; + using Newtonsoft.Json.Linq; + using NUnit.Framework; + + [TestFixture] public class RuntimeTypeExtensionTests { + [Test] + public async Task TypeExtension_OfObject_ResolvesDuringExecution() + { + var server = new TestServerBuilder() + .AddGraphQL(o => + { + o.AddController(); + + o.MapField("Property3", (TwoPropertyObject source) => + { + return $"{source.Property1}-{source.Property2}"; + }); + }) + .Build(); + + var builder = server.CreateQueryContextBuilder(); + builder.AddQueryText(@"query { retrieveObject { property1 property2 property3 } }"); + + var result = await server.RenderResult(builder); + CommonAssertions.AreEqualJsonStrings( + @"{ + ""data"": { + ""retrieveObject"": { + ""property1"" : ""Prop1"", + ""property2"" : 101, + ""property3"" : ""Prop1-101"" + } + } + }", + result); + } + + [Test] + public void TypeExtension_OfObject_WithMetaNameField_ThrowsDeclarationException() + { + var builder = new TestServerBuilder() + .AddGraphQL(o => + { + o.AddController(); + + o.MapField("[Action]", (TwoPropertyObject source) => + { + return $"{source.Property1}-{source.Property2}"; + }); + }); + + var ex = Assert.Throws(() => { + builder.Build(); + }); + + // ensure the field name is in the message + Assert.IsTrue(ex.Message.Contains("[Action]")); + } + + [Test] + public async Task TypeExtension_NoSourceParameterDeclared_ResolvesCorrectly() + { + var server = new TestServerBuilder() + .AddGraphQL(o => + { + o.AddController(); + + o.MapField("property5", (int argument) => + { + return argument; + }); + }).Build(); + + var builder = server.CreateQueryContextBuilder(); + builder.AddQueryText(@"query { retrieveObject { property1 property2 property5(argument: 37) } }"); + + var result = await server.RenderResult(builder); + CommonAssertions.AreEqualJsonStrings( + @"{ + ""data"": { + ""retrieveObject"": { + ""property1"" : ""Prop1"", + ""property2"" : 101, + ""property5"" : 37 + } + } + }", + result); + } + + [Test] + public async Task TypeExtension_OfStruct_ResolvesDuringExecution() + { + var server = new TestServerBuilder() + .AddGraphQL(o => + { + o.AddController(); + + o.MapField("Property3", (TwoPropertyStruct source) => + { + return $"{source.Property1}-{source.Property2}"; + }); + }) + .Build(); + + var builder = server.CreateQueryContextBuilder(); + builder.AddQueryText(@"query { retrieveStruct { property1 property2 property3 } }"); + + var result = await server.RenderResult(builder); + CommonAssertions.AreEqualJsonStrings( + @"{ + ""data"": { + ""retrieveStruct"": { + ""property1"" : ""Prop1"", + ""property2"" : 101, + ""property3"" : ""Prop1-101"" + } + } + }", + result); + } + + [Test] + public async Task BatchExtension_OfObject_ResolvesDuringExecution() + { + var server = new TestServerBuilder() + .AddGraphQL(o => + { + o.AddController(); + + o.MapField("Property4") + .WithBatchProcessing() + .AddResolver((IEnumerable source) => + { + // leaf property dictionary + var dic = new Dictionary(); + foreach (var item in source) + { + dic.Add(item, $"{item.Property1}-{item.Property2}-Batched"); + } + + return dic; + }); + }) + .Build(); + + var builder = server.CreateQueryContextBuilder(); + builder.AddQueryText(@"query { retrieveObjects { property1 property2 property4 } }"); + + var result = await server.RenderResult(builder); + CommonAssertions.AreEqualJsonStrings( + @"{ + ""data"": { + ""retrieveObjects"": [{ + ""property1"" : ""Prop1A"", + ""property2"" : 101, + ""property4"" : ""Prop1A-101-Batched"" + },{ + ""property1"" : ""Prop1B"", + ""property2"" : 102, + ""property4"" : ""Prop1B-102-Batched"" + },{ + ""property1"" : ""Prop1C"", + ""property2"" : 103, + ""property4"" : ""Prop1C-103-Batched"" + },] + } + }", + result); + } + + [Test] + public async Task BatchExtension_OfStructs_ResolvesDuringExecution() + { + var server = new TestServerBuilder() + .AddGraphQL(o => + { + o.AddController(); + + o.MapField("Property4") + .WithBatchProcessing() + .AddResolver((IEnumerable source) => + { + var dic = new Dictionary(); + foreach (var item in source) + { + dic.Add(item, $"{item.Property1}-{item.Property2}-Batched"); + } + + return dic; + }); + }) + .Build(); + + var builder = server.CreateQueryContextBuilder(); + builder.AddQueryText(@"query { retrieveStructs { property1 property2 property4 } }"); + + var result = await server.RenderResult(builder); + CommonAssertions.AreEqualJsonStrings( + @"{ + ""data"": { + ""retrieveStructs"": [{ + ""property1"" : ""Prop1A"", + ""property2"" : 101, + ""property4"" : ""Prop1A-101-Batched"" + },{ + ""property1"" : ""Prop1B"", + ""property2"" : 102, + ""property4"" : ""Prop1B-102-Batched"" + },{ + ""property1"" : ""Prop1C"", + ""property2"" : 103, + ""property4"" : ""Prop1C-103-Batched"" + },] + } + }", + result); + } + + [Test] + public async Task BatchExtension_OfObject_ThatUsesStartBatch_ResolvesDuringExecution() + { + var server = new TestServerBuilder() + .AddGraphQL(o => + { + o.AddController(); + + o.MapField("Property5") + .WithBatchProcessing() + .AddPossibleTypes(typeof(ChildObject)) + .AddResolver((IEnumerable source) => + { + // using static batch builder for child objects + return GraphActionResult.StartBatch() + .FromSource(source, x => x.Property1) + .WithResults( + source.Select(x => new ChildObject() + { + ParentId = x.Property1, + Property1 = $"Child-Prop1-{x.Property1}", + }), + y => y.ParentId) + .Complete(); + }); + }) + .Build(); + + var builder = server.CreateQueryContextBuilder(); + builder.AddQueryText(@"query { retrieveObjects { property1 property2 property5 { property1 } } }"); + + var result = await server.RenderResult(builder); + CommonAssertions.AreEqualJsonStrings( + @"{ + ""data"": { + ""retrieveObjects"": [{ + ""property1"" : ""Prop1A"", + ""property2"" : 101, + ""property5"" : { + ""property1"": ""Child-Prop1-Prop1A"" + } + },{ + ""property1"" : ""Prop1B"", + ""property2"" : 102, + ""property5"" : { + ""property1"": ""Child-Prop1-Prop1B"" + } + },{ + ""property1"" : ""Prop1C"", + ""property2"" : 103, + ""property5"" : { + ""property1"": ""Child-Prop1-Prop1C"" + } + },] + } + }", + result); + } + + [Test] + public async Task Runtime_TypeExtension_WithSecurityParams_AndAllowedUser_ResolvesCorrectly() + { + var serverBuilder = new TestServerBuilder(); + + serverBuilder.AddGraphQL(o => + { + o.AddController(); + + o.MapField("Property3", (TwoPropertyStruct source) => + { + return $"{source.Property1}-{source.Property2}"; + }) + .RequireAuthorization("policy1"); + }); + + serverBuilder.Authorization.AddClaimPolicy("policy1", "policy1Claim", "policy1Value"); + serverBuilder.UserContext + .Authenticate() + .AddUserClaim("policy1Claim", "policy1Value"); + + var server = serverBuilder.Build(); + + var builder = server.CreateQueryContextBuilder(); + builder.AddQueryText(@"query { retrieveStruct { property1 property3 } }"); + + var result = await server.RenderResult(builder); + CommonAssertions.AreEqualJsonStrings( + @"{ + ""data"": { + ""retrieveStruct"" : { + ""property1"": ""Prop1"", + ""property3"" : ""Prop1-101"" + } + } + }", + result); + } + + [Test] + public async Task Runtime_ExecutionDirective_WithSecurityParams_AndUnAuthenticatedUser_RendersAccessDenied() + { + var serverBuilder = new TestServerBuilder(); + + serverBuilder.AddGraphQL(o => + { + o.AddController(); + + o.MapField("Property3", (TwoPropertyStruct source) => + { + return $"{source.Property1}-{source.Property2}"; + }) + .RequireAuthorization("policy1"); + }); + + // user not authenticated + serverBuilder.Authorization.AddClaimPolicy("policy1", "policy1Claim", "policy1Value"); + + var server = serverBuilder.Build(); + + var builder = server.CreateQueryContextBuilder(); + builder.AddQueryText(@"query { retrieveStruct { property1 property3 } }"); + + var result = await server.ExecuteQuery(builder); + Assert.AreEqual(1, result.Messages.Count); + Assert.AreEqual(GraphMessageSeverity.Critical, result.Messages[0].Severity); + Assert.AreEqual(Constants.ErrorCodes.ACCESS_DENIED, result.Messages[0].Code); + + + } + + [Test] + public async Task Runtime_ExecutionDirective_WithSecurityParams_AndUnAuthorizedUser_RendersAccessDenied() + { + var serverBuilder = new TestServerBuilder(); + + serverBuilder.AddGraphQL(o => + { + o.AddController(); + + o.MapField("Property3", (TwoPropertyStruct source) => + { + return $"{source.Property1}-{source.Property2}"; + }) + .RequireAuthorization("policy1"); + }); + + // incorrect claim + serverBuilder.Authorization.AddClaimPolicy("policy1", "policy1Claim", "policy1Value"); + serverBuilder.UserContext + .Authenticate() + .AddUserClaim("policy1Claim", "policy2Value"); + + var server = serverBuilder.Build(); + + var builder = server.CreateQueryContextBuilder(); + builder.AddQueryText(@"query { retrieveStruct { property1 property3 } }"); + + var result = await server.ExecuteQuery(builder); + Assert.AreEqual(1, result.Messages.Count); + Assert.AreEqual(GraphMessageSeverity.Critical, result.Messages[0].Severity); + Assert.AreEqual(Constants.ErrorCodes.ACCESS_DENIED, result.Messages[0].Code); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/RuntimeTypeExtensionTestData/ChildObject.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/RuntimeTypeExtensionTestData/ChildObject.cs new file mode 100644 index 000000000..2697897e0 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/RuntimeTypeExtensionTestData/ChildObject.cs @@ -0,0 +1,18 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Execution.TestData.RuntimeTypeExtensionTestData +{ + public class ChildObject + { + public string ParentId { get; set; } + + public string Property1 { get; set; } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/RuntimeTypeExtensionTestData/RuntimeFieldTypeExtensionTestsController.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/RuntimeTypeExtensionTestData/RuntimeFieldTypeExtensionTestsController.cs new file mode 100644 index 000000000..39ae094fb --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/RuntimeTypeExtensionTestData/RuntimeFieldTypeExtensionTestsController.cs @@ -0,0 +1,85 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Execution.TestData.RuntimeTypeExtensionTestData +{ + using System.Collections.Generic; + using GraphQL.AspNet.Attributes; + using GraphQL.AspNet.Controllers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + + public class RuntimeFieldTypeExtensionTestsController : GraphController + { + [QueryRoot] + public TwoPropertyObject RetrieveObject() + { + return new TwoPropertyObject() + { + Property1 = "Prop1", + Property2 = 101, + }; + } + + [QueryRoot] + public TwoPropertyStruct RetrieveStruct() + { + return new TwoPropertyStruct() + { + Property1 = "Prop1", + Property2 = 101, + }; + } + + [QueryRoot] + public IEnumerable RetrieveObjects() + { + var list = new List(); + list.Add(new TwoPropertyObject() + { + Property1 = "Prop1A", + Property2 = 101, + }); + list.Add(new TwoPropertyObject() + { + Property1 = "Prop1B", + Property2 = 102, + }); + list.Add(new TwoPropertyObject() + { + Property1 = "Prop1C", + Property2 = 103, + }); + + return list; + } + + [QueryRoot] + public IEnumerable RetrieveStructs() + { + var list = new List(); + list.Add(new TwoPropertyStruct() + { + Property1 = "Prop1A", + Property2 = 101, + }); + list.Add(new TwoPropertyStruct() + { + Property1 = "Prop1B", + Property2 = 102, + }); + list.Add(new TwoPropertyStruct() + { + Property1 = "Prop1C", + Property2 = 103, + }); + + return list; + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/ResolvedFieldTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/ResolvedFieldTemplateTests.cs index 874775a3f..1bb2ff69d 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/ResolvedFieldTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/ResolvedFieldTemplateTests.cs @@ -97,5 +97,17 @@ public void ResolvedField_AddPossibleTypes_AddsAppropriateAttribute() Assert.IsNotNull(possibleTypesAttrib.PossibleTypes.FirstOrDefault(x => x == typeof(TwoPropertyObject))); Assert.IsNotNull(possibleTypesAttrib.PossibleTypes.FirstOrDefault(x => x == typeof(TwoPropertyObjectV2))); } + + [Test] + public void ResolvedField_ResolverReturnsNullableT_ItsPreserved() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapQuery("/path1/path2", (string a) => (int?)1); + + // nullable int + Assert.AreEqual(typeof(int?), field.Resolver.Method.ReturnType); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/RuntimeSchemaItemAttributeProviderTestData/PersonAttribute.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/RuntimeSchemaItemAttributeProviderTestData/PersonAttribute.cs new file mode 100644 index 000000000..a35440a56 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/RuntimeSchemaItemAttributeProviderTestData/PersonAttribute.cs @@ -0,0 +1,17 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.RuntimeSchemaItemAttributeProviderTestData +{ + using System; + + public class PersonAttribute : Attribute + { + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/RuntimeSchemaItemAttributeProviderTestData/TeacherAttribute.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/RuntimeSchemaItemAttributeProviderTestData/TeacherAttribute.cs new file mode 100644 index 000000000..86a3a1e3f --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/RuntimeSchemaItemAttributeProviderTestData/TeacherAttribute.cs @@ -0,0 +1,15 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.RuntimeSchemaItemAttributeProviderTestData +{ + public class TeacherAttribute : PersonAttribute + { + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/RuntimeSchemaItemAttributeProviderTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/RuntimeSchemaItemAttributeProviderTests.cs new file mode 100644 index 000000000..ff9147645 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/RuntimeSchemaItemAttributeProviderTests.cs @@ -0,0 +1,85 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates +{ + using System; + using System.Collections.Generic; + using GraphQL.AspNet.Common.Extensions; + using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; + using GraphQL.AspNet.Tests.Middleware.FieldSecurityMiddlewareTestData; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.RuntimeSchemaItemAttributeProviderTestData; + using Moq; + using NUnit.Framework; + + [TestFixture] + public class RuntimeSchemaItemAttributeProviderTests + { + public delegate int NoParamDelegate(); + + [Teacher] + public int MethodWithTeacherAttribute() + { + return 0; + } + + [Person] + public int MethodWithPersonAttribute() + { + return 0; + } + + public int MethodWithNoAttributes() + { + return 0; + } + + [TestCase(typeof(TeacherAttribute), true)] + [TestCase(typeof(PersonAttribute), true)] + [TestCase(typeof(AuthorAttribute), false)] + public void HasAttribute_DirectlyDefinedDoesProduceValue(Type typeToSearchFor, bool shouldBeFound) + { + // sanity check to ensure the world is working right and MethodInfo + // as an attribute provider behaves as expected + var mock = new Mock(); + + var method = typeof(RuntimeSchemaItemAttributeProviderTests) + .GetMethod(nameof(MethodWithTeacherAttribute)); + + var wasFound = method.HasAttribute(typeToSearchFor); + Assert.AreEqual(shouldBeFound, wasFound); + } + + [TestCase(typeof(TeacherAttribute), true)] + [TestCase(typeof(PersonAttribute), true)] + [TestCase(typeof(AuthorAttribute), false)] + public void HasAttribute_AllProvidedExternally(Type typeToSearchFor, bool shouldBeFound) + { + var mock = new Mock(); + + var method = typeof(RuntimeSchemaItemAttributeProviderTests) + .GetMethod(nameof(MethodWithNoAttributes)); + + var del = method.CreateDelegate(this); + mock.Setup(x => x.Resolver).Returns(del); + + // append the teacher attribute to a list in the provider + // not as part of the method + var attribs = new List(); + attribs.Add(new TeacherAttribute()); + mock.Setup(x => x.Attributes).Returns(attribs); + + var provider = new RuntimeSchemaItemAttributeProvider(mock.Object); + + var wasFound = provider.HasAttribute(typeToSearchFor); + Assert.AreEqual(shouldBeFound, wasFound); + } + } +} \ No newline at end of file From 07ca7cac1b90bbfd1de8e481fe68b4cbe2092991 Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Mon, 17 Jul 2023 16:57:27 -0700 Subject: [PATCH 40/63] WIP, reworked FieldResolutionContext and DirectiveResolutionContext --- ...CompleteBatchOperationGraphActionResult.cs | 7 + .../Controllers/GraphControllerBase.cs | 56 ++++---- .../RuntimeFieldExecutionController.cs | 12 +- .../Directives/RuntimeExecutionDirective.cs | 10 +- .../Contexts/DirectiveResolutionContext.cs | 50 ++++++- .../Contexts/FieldResolutionContext.cs | 56 ++++++-- .../Contexts/SchemaItemResolutionContext.cs | 111 +++++++++++++-- .../SchemaItemResolutionContext{TRequest}.cs | 46 +++++- .../Execution/ExecutionArgumentCollection.cs | 94 +++++-------- .../Execution/GraphMessageCollection.cs | 2 +- ...tionGraphFieldResolver{TSource,TReturn}.cs | 2 +- .../GraphControllerActionResolver.cs | 1 - .../Schema_TypeGraphFieldResolver.cs | 2 +- .../Type_EnumValuesGraphFieldResolver.cs | 6 +- .../Type_TypeGraphFieldResolver.cs | 6 +- .../ObjectMethodGraphFieldResolver.cs | 10 +- .../ObjectPropertyGraphFieldResolver.cs | 4 +- .../Execution/IExecutionArgumentCollection.cs | 28 +--- .../InvokeDirectiveResolverMiddleware.cs | 13 +- .../InvokeFieldResolverMiddleware.cs | 12 +- .../TypeTemplates/GraphArgumentTemplate.cs | 25 +++- .../TypeTemplates/GraphFieldTemplateBase.cs | 6 +- .../TypeSystem/GraphArgumentModifiers.cs | 5 + .../GraphArgumentModifiersExtensions.cs | 14 +- .../Controllers/ControllerExtensionTests.cs | 10 +- .../GraphQLTemplateHelper.cs | 6 +- .../FieldContextBuilder.cs | 41 +++--- .../SingleMethodGraphControllerTemplate.cs | 15 +- ...raphControllerTemplate{TControllerType}.cs | 33 +++++ .../TestServer.cs | 133 +++++------------- .../ActionResults/ActionResultTests.cs | 2 +- .../Controllers/GraphControllerTests.cs | 12 +- .../Execution/ContextTests.cs | 28 ++-- .../Execution/ExecutionArgumentTests.cs | 106 ++++---------- .../Execution/GeneralQueryExecutionTests.cs | 2 +- .../Execution/RuntimeFieldTests.cs | 129 +++++++++++++++++ .../Execution/RuntimeTypeExtensionTests.cs | 5 +- .../TypeSystemDirectiveCommonTests.cs | 31 ++-- ...nMethodModelStateValidatedLogEntryTests.cs | 4 +- .../GeneralEventLogEntryPropertyChecks.cs | 20 +-- .../Middleware/MiddlewarePipelineTests.cs | 10 +- .../Schemas/GraphTypeExpressionTests.cs | 50 +++---- .../Security/SecurityPipelineTests.cs | 32 ++--- 43 files changed, 758 insertions(+), 489 deletions(-) create mode 100644 src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/SingleMethodGraphControllerTemplate{TControllerType}.cs diff --git a/src/graphql-aspnet/Controllers/ActionResults/CompleteBatchOperationGraphActionResult.cs b/src/graphql-aspnet/Controllers/ActionResults/CompleteBatchOperationGraphActionResult.cs index d39b0a37b..e81097d72 100644 --- a/src/graphql-aspnet/Controllers/ActionResults/CompleteBatchOperationGraphActionResult.cs +++ b/src/graphql-aspnet/Controllers/ActionResults/CompleteBatchOperationGraphActionResult.cs @@ -18,6 +18,13 @@ namespace GraphQL.AspNet.Controllers.ActionResults using GraphQL.AspNet.Execution.RulesEngine.RuleSets.FieldResolution.FieldValidation; using GraphQL.AspNet.Interfaces.Controllers; + /// + /// A graph action result that is built from a batch builder and can turn said builder into an + /// appropriate dictionary of items to resolve a type extension. + /// + /// The type of the source item identified in the type extension. + /// The type of the result item identified in the type extension. + /// The type of the key that links to . public class CompleteBatchOperationGraphActionResult : IGraphActionResult { private readonly BatchBuilder _batchBuilder; diff --git a/src/graphql-aspnet/Controllers/GraphControllerBase.cs b/src/graphql-aspnet/Controllers/GraphControllerBase.cs index 380a87f0b..4e6751cfc 100644 --- a/src/graphql-aspnet/Controllers/GraphControllerBase.cs +++ b/src/graphql-aspnet/Controllers/GraphControllerBase.cs @@ -34,49 +34,49 @@ public abstract class GraphControllerBase where TRequest : class, IDataRequest { private SchemaItemResolutionContext _schemaItemContext; - private IGraphFieldResolverMetaData _action; + private IGraphFieldResolverMetaData _resolverMetaData; /// /// Invoke the specified action method as an asynchronous operation. /// - /// The action to invoke. + /// The metadata describing the method on this controller to invoke. /// The invocation context to process. /// Task<System.Object>. [GraphSkip] internal virtual async Task InvokeActionAsync( - IGraphFieldResolverMetaData actionMetadata, + IGraphFieldResolverMetaData resolverMetadata, SchemaItemResolutionContext schemaItemContext) { // deconstruct the context for processing Validation.ThrowIfNull(schemaItemContext, nameof(schemaItemContext)); _schemaItemContext = schemaItemContext; - _action = actionMetadata; + _resolverMetaData = resolverMetadata; // ensure a field request is available var fieldRequest = schemaItemContext?.Request; Validation.ThrowIfNull(fieldRequest, nameof(fieldRequest)); - _schemaItemContext.Logger?.ActionMethodInvocationRequestStarted(_action, this.Request); + _schemaItemContext.Logger?.ActionMethodInvocationRequestStarted(_resolverMetaData, this.Request); if (_schemaItemContext.QueryRequest is IQueryExecutionWebRequest webRequest) this.HttpContext = webRequest.HttpContext; - if (_action?.Method == null) + if (_resolverMetaData?.Method == null) { return new InternalServerErrorGraphActionResult( - $"The definition for field '{this.GetType().Name}' defined no graph action to execute. Operation failed."); + $"The definition for field '{this.GetType().Name}' defined no resolver to execute. Operation failed."); } try { var modelGenerator = new ModelStateGenerator(schemaItemContext.ServiceProvider); - this.ModelState = modelGenerator.CreateStateDictionary(schemaItemContext.Arguments); + this.ModelState = modelGenerator.CreateStateDictionary(schemaItemContext.ExecutionSuppliedArguments); - _schemaItemContext.Logger?.ActionMethodModelStateValidated(_action, this.Request, this.ModelState); + _schemaItemContext.Logger?.ActionMethodModelStateValidated(_resolverMetaData, this.Request, this.ModelState); - var invocationParameters = _schemaItemContext.Arguments.PrepareArguments(_action); - var invokeReturn = this.CreateAndInvokeAction(_action, invocationParameters); - if (_action.IsAsyncField) + var invocationParameters = _schemaItemContext.ExecutionSuppliedArguments.PrepareArguments(_resolverMetaData); + var invokeReturn = this.CreateAndInvokeAction(_resolverMetaData, invocationParameters); + if (_resolverMetaData.IsAsyncField) { if (invokeReturn is Task task) { @@ -84,26 +84,26 @@ internal virtual async Task InvokeActionAsync( if (task.IsFaulted) throw task.UnwrapException(); - invokeReturn = task.ResultOfTypeOrNull(_action.ExpectedReturnType); + invokeReturn = task.ResultOfTypeOrNull(_resolverMetaData.ExpectedReturnType); } else { // given all the checking and parsing this should be imnpossible, but just in case invokeReturn = new InternalServerErrorGraphActionResult( - $"The action '{_action.InternalName}' on controller '{_action.ParentInternalName}' is defined " + + $"The action '{_resolverMetaData.InternalName}' on controller '{_resolverMetaData.ParentInternalName}' is defined " + $"as asyncronous but it did not return a {typeof(Task)}."); } } - _schemaItemContext.Logger?.ActionMethodInvocationCompleted(_action, this.Request, invokeReturn); + _schemaItemContext.Logger?.ActionMethodInvocationCompleted(_resolverMetaData, this.Request, invokeReturn); return invokeReturn; } catch (TargetInvocationException ti) { var innerException = ti.InnerException ?? ti; - _schemaItemContext.Logger?.ActionMethodInvocationException(_action, this.Request, innerException); + _schemaItemContext.Logger?.ActionMethodInvocationException(_resolverMetaData, this.Request, innerException); - return new InternalServerErrorGraphActionResult(_action, innerException); + return new InternalServerErrorGraphActionResult(_resolverMetaData, innerException); } catch (Exception ex) { @@ -113,42 +113,42 @@ internal virtual async Task InvokeActionAsync( // might happen if a method was declared differently than the actual call signature case TargetException _: case TargetParameterCountException _: - _schemaItemContext.Logger?.ActionMethodInvocationException(_action, this.Request, ex); - return new RouteNotFoundGraphActionResult(_action, ex); + _schemaItemContext.Logger?.ActionMethodInvocationException(_resolverMetaData, this.Request, ex); + return new RouteNotFoundGraphActionResult(_resolverMetaData, ex); default: // total failure by the user's action code. // record and bubble - _schemaItemContext.Logger?.ActionMethodUnhandledException(_action, this.Request, ex); + _schemaItemContext.Logger?.ActionMethodUnhandledException(_resolverMetaData, this.Request, ex); throw; } } } /// - /// Invoke the actual C# method declared by the + /// Invoke the actual C# method declared by the /// using this controller instance as the target object of the invocation. /// - /// The resolver declaration that needs to be executed. + /// The resolver declaration that needs to be executed. /// The realized set of arguments that need /// to be passed to the invocable method instance. /// The exact return value from the invoked resolver. - protected virtual object CreateAndInvokeAction(IGraphFieldResolverMetaData methodMetadata, object[] invocationArguments) + protected virtual object CreateAndInvokeAction(IGraphFieldResolverMetaData resolverMetaData, object[] invocationArguments) { - if (methodMetadata.Method.DeclaringType != this.GetType()) + if (resolverMetaData.Method.DeclaringType != this.GetType()) { - throw new TargetException($"Unable to invoke action '{_action.InternalName}' on controller '{this.GetType().FriendlyName()}'. The controller " + + throw new TargetException($"Unable to invoke action '{_resolverMetaData.InternalName}' on controller '{this.GetType().FriendlyName()}'. The controller " + "does not own the method."); } - if (methodMetadata.Method.IsStatic) + if (resolverMetaData.Method.IsStatic) { - throw new TargetException($"Unable to invoke action '{_action.InternalName}' on controller '{this.GetType().FriendlyName()}'. The method " + + throw new TargetException($"Unable to invoke action '{_resolverMetaData.InternalName}' on controller '{this.GetType().FriendlyName()}'. The method " + "is static and cannot be directly invoked on this controller instance."); } - var invoker = InstanceFactory.CreateInstanceMethodInvoker(methodMetadata.Method); + var invoker = InstanceFactory.CreateInstanceMethodInvoker(resolverMetaData.Method); var controllerRef = this as object; return invoker(ref controllerRef, invocationArguments); diff --git a/src/graphql-aspnet/Controllers/RuntimeFieldExecutionController.cs b/src/graphql-aspnet/Controllers/RuntimeFieldExecutionController.cs index aa8c365fa..60aa2d923 100644 --- a/src/graphql-aspnet/Controllers/RuntimeFieldExecutionController.cs +++ b/src/graphql-aspnet/Controllers/RuntimeFieldExecutionController.cs @@ -15,25 +15,25 @@ namespace GraphQL.AspNet.Controllers /// /// A special controller instance for executing runtime configured controller - /// actions (e.g. minimal api defined fields). + /// actions (e.g. minimal api defined fields and type exensions). /// [GraphRoot] internal sealed class RuntimeFieldExecutionController : GraphController { /// - protected override object CreateAndInvokeAction(IGraphFieldResolverMetaData metadata, object[] invocationArguments) + protected override object CreateAndInvokeAction(IGraphFieldResolverMetaData resolverMetaData, object[] invocationArguments) { // minimal api resolvers are allowed to be static since there is no // extra context to setup or make available such as 'this.User' etc. - if (metadata.Method.IsStatic) + if (resolverMetaData.Method.IsStatic) { - var invoker = InstanceFactory.CreateStaticMethodInvoker(metadata.Method); + var invoker = InstanceFactory.CreateStaticMethodInvoker(resolverMetaData.Method); return invoker(invocationArguments); } else { - var invoker = InstanceFactory.CreateInstanceMethodInvoker(metadata.Method); - var instance = InstanceFactory.CreateInstance(metadata.Method.DeclaringType); + var invoker = InstanceFactory.CreateInstanceMethodInvoker(resolverMetaData.Method); + var instance = InstanceFactory.CreateInstance(resolverMetaData.Method.DeclaringType); return invoker(ref instance, invocationArguments); } } diff --git a/src/graphql-aspnet/Directives/RuntimeExecutionDirective.cs b/src/graphql-aspnet/Directives/RuntimeExecutionDirective.cs index 41fcf122d..a2119052a 100644 --- a/src/graphql-aspnet/Directives/RuntimeExecutionDirective.cs +++ b/src/graphql-aspnet/Directives/RuntimeExecutionDirective.cs @@ -20,19 +20,19 @@ namespace GraphQL.AspNet.Controllers internal sealed class RuntimeExecutionDirective : GraphDirective { /// - protected override object CreateAndInvokeAction(IGraphFieldResolverMetaData metadata, object[] invocationArguments) + protected override object CreateAndInvokeAction(IGraphFieldResolverMetaData resolverMetaData, object[] invocationArguments) { // minimal api resolvers are allowed to be static since there is no // extra context to setup or make available such as 'this.User' etc. - if (metadata.Method.IsStatic) + if (resolverMetaData.Method.IsStatic) { - var invoker = InstanceFactory.CreateStaticMethodInvoker(metadata.Method); + var invoker = InstanceFactory.CreateStaticMethodInvoker(resolverMetaData.Method); return invoker(invocationArguments); } else { - var invoker = InstanceFactory.CreateInstanceMethodInvoker(metadata.Method); - var instance = InstanceFactory.CreateInstance(metadata.Method.DeclaringType); + var invoker = InstanceFactory.CreateInstanceMethodInvoker(resolverMetaData.Method); + var instance = InstanceFactory.CreateInstance(resolverMetaData.Method.DeclaringType); return invoker(ref instance, invocationArguments); } } diff --git a/src/graphql-aspnet/Execution/Contexts/DirectiveResolutionContext.cs b/src/graphql-aspnet/Execution/Contexts/DirectiveResolutionContext.cs index 64cb85b81..d572aa125 100644 --- a/src/graphql-aspnet/Execution/Contexts/DirectiveResolutionContext.cs +++ b/src/graphql-aspnet/Execution/Contexts/DirectiveResolutionContext.cs @@ -9,35 +9,73 @@ namespace GraphQL.AspNet.Execution.Contexts { + using System; using System.Diagnostics; using System.Security.Claims; + using System.Threading; + using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Interfaces.Execution; + using GraphQL.AspNet.Interfaces.Logging; using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Schemas.Structural; /// /// A context passed to a directive resolver to complete its resolution task for the field its attached to. /// + [GraphSkip] [DebuggerDisplay("Directive: {Request.InvocationContext.Directive.Name}")] public class DirectiveResolutionContext : SchemaItemResolutionContext { + private IGraphDirectiveRequest _directiveRequest; + /// /// Initializes a new instance of the class. /// + /// The service provider instance that should be used to resolve any + /// needed services or non-schema arguments to the target resolver. + /// The query session governing the request. /// The schema in scope for this resolution context. - /// The parent context from which this resolution context should - /// extract is base data values. + /// The master query request being executed. /// The resolution request to carry with the context. /// The arguments to be passed to the resolver when its executed. - /// Optional. The user context that authenticated and authorized for this + /// The messages. + /// (Optional) A logger instance that can be used to record scoped log entries. + /// (Optional) The user context that authenticated and authorized for this /// resolution context. + /// The cancel token governing the resolution of the schema item. public DirectiveResolutionContext( + IServiceProvider serviceProvider, + IQuerySession querySession, ISchema targetSchema, - IGraphQLMiddlewareExecutionContext parentContext, + IQueryExecutionRequest queryRequest, IGraphDirectiveRequest request, IExecutionArgumentCollection arguments, - ClaimsPrincipal user = null) - : base(targetSchema, parentContext, request, arguments, user) + IGraphMessageCollection messages = null, + IGraphEventLogger logger = null, + ClaimsPrincipal user = null, + CancellationToken cancelToken = default) + : base( + serviceProvider, + querySession, + targetSchema, + queryRequest, + request, + arguments, + messages, + logger, + user, + cancelToken) { + _directiveRequest = request; } + + /// + public override SchemaItemPath Route => _directiveRequest?.Directive.Route; + + /// + public override IGraphArgumentCollection SchemaDefinedArguments => _directiveRequest?.Directive.Arguments; + + /// + public override object SourceData => null; } } \ No newline at end of file diff --git a/src/graphql-aspnet/Execution/Contexts/FieldResolutionContext.cs b/src/graphql-aspnet/Execution/Contexts/FieldResolutionContext.cs index 61bed5335..a2f88a0fc 100644 --- a/src/graphql-aspnet/Execution/Contexts/FieldResolutionContext.cs +++ b/src/graphql-aspnet/Execution/Contexts/FieldResolutionContext.cs @@ -9,35 +9,64 @@ namespace GraphQL.AspNet.Execution.Contexts { + using System; using System.Diagnostics; using System.Security.Claims; + using System.Threading; + using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Interfaces.Execution; + using GraphQL.AspNet.Interfaces.Logging; using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Schemas.Structural; /// /// A context passed to a field resolver to complete its resolution task and generate data for a field. /// + [GraphSkip] [DebuggerDisplay("Field: {Request.Field.Route.Path} (Mode = {Request.Field.Mode})")] public class FieldResolutionContext : SchemaItemResolutionContext { + private readonly IGraphFieldRequest _fieldRequest; + /// /// Initializes a new instance of the class. /// + /// The service provider instance that should be used to resolve any + /// needed services or non-schema arguments to the target resolver. + /// The query session governing the request. /// The schema in scope for this resolution context. - /// The parent context from which this field resolution context is created. - /// The request to resolve a specific field. - /// The execution arguments that need to be passed to the field - /// resolver. - /// Optional. The user context that authenticated and authorized for this + /// The master query request being executed. + /// The resolution request to carry with the context. + /// The arguments to be passed to the resolver when its executed. + /// The messages. + /// (Optional) A logger instance that can be used to record scoped log entries. + /// (Optional) The user context that authenticated and authorized for this /// resolution context. + /// The cancel token governing the resolution of the schema item. public FieldResolutionContext( + IServiceProvider serviceProvider, + IQuerySession querySession, ISchema targetSchema, - IGraphQLMiddlewareExecutionContext parentContext, - IGraphFieldRequest fieldRequest, + IQueryExecutionRequest queryRequest, + IGraphFieldRequest request, IExecutionArgumentCollection arguments, - ClaimsPrincipal user = null) - : base(targetSchema, parentContext, fieldRequest, arguments, user) + IGraphMessageCollection messages = null, + IGraphEventLogger logger = null, + ClaimsPrincipal user = null, + CancellationToken cancelToken = default) + : base( + serviceProvider, + querySession, + targetSchema, + queryRequest, + request, + arguments, + messages, + logger, + user, + cancelToken) { + _fieldRequest = request; } /// @@ -45,5 +74,14 @@ public FieldResolutionContext( /// /// The result of executing a field's resolver. public object Result { get; set; } + + /// + public override SchemaItemPath Route => _fieldRequest?.Field.Route; + + /// + public override IGraphArgumentCollection SchemaDefinedArguments => _fieldRequest.Field.Arguments; + + /// + public override object SourceData => _fieldRequest?.Data?.Value; } } \ No newline at end of file diff --git a/src/graphql-aspnet/Execution/Contexts/SchemaItemResolutionContext.cs b/src/graphql-aspnet/Execution/Contexts/SchemaItemResolutionContext.cs index 14eb31d2d..db0a7bb26 100644 --- a/src/graphql-aspnet/Execution/Contexts/SchemaItemResolutionContext.cs +++ b/src/graphql-aspnet/Execution/Contexts/SchemaItemResolutionContext.cs @@ -9,47 +9,107 @@ namespace GraphQL.AspNet.Execution.Contexts { + using System; using System.Security.Claims; + using System.Threading; using GraphQL.AspNet.Common; using GraphQL.AspNet.Interfaces.Execution; + using GraphQL.AspNet.Interfaces.Logging; using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Schemas.Structural; /// /// A base context used by all field and directive resolution contexts in order to successfully invoke /// a controller action, object method or object property and retrieve a data value for a field. /// - public abstract class SchemaItemResolutionContext : MiddlewareExecutionContextBase + public abstract class SchemaItemResolutionContext { /// /// Initializes a new instance of the class. /// + /// The service provider instance that should be used to resolve any + /// needed services or non-schema arguments to the target resolver. + /// The query session governing the request. /// The schema in scope for this resolution context. - /// The parent context from which this resolution context should - /// extract is base data values. + /// The master query request being executed. /// The resolution request to carry with the context. /// The arguments to be passed to the resolver when its executed. + /// (Optional) A collection of messages that can be written to during resolution. These messages + /// will be transmitted to the requestor. + /// (Optional) A logger instance that can be used to record scoped log entries. /// (Optional) The user context that authenticated and authorized for this /// resolution context. + /// The cancel token governing the resolution of the schema item. protected SchemaItemResolutionContext( + IServiceProvider serviceProvider, + IQuerySession querySession, ISchema targetSchema, - IGraphQLMiddlewareExecutionContext parentContext, + IQueryExecutionRequest queryRequest, IDataRequest request, IExecutionArgumentCollection arguments, - ClaimsPrincipal user = null) - : base(parentContext) + IGraphMessageCollection messages = null, + IGraphEventLogger logger = null, + ClaimsPrincipal user = null, + CancellationToken cancelToken = default) { + this.Session = Validation.ThrowIfNullOrReturn(querySession, nameof(querySession)); + this.ServiceProvider = Validation.ThrowIfNullOrReturn(serviceProvider, nameof(serviceProvider)); + this.QueryRequest = Validation.ThrowIfNullOrReturn(queryRequest, nameof(queryRequest)); this.Request = Validation.ThrowIfNullOrReturn(request, nameof(request)); - this.Arguments = Validation.ThrowIfNullOrReturn(arguments, nameof(arguments)); + this.ExecutionSuppliedArguments = Validation.ThrowIfNullOrReturn(arguments, nameof(arguments)); this.User = user; + this.Logger = logger; this.Schema = Validation.ThrowIfNullOrReturn(targetSchema, nameof(targetSchema)); + this.ExecutionSuppliedArguments = this.ExecutionSuppliedArguments.ForContext(this); + this.Messages = messages ?? new GraphMessageCollection(); + this.CancellationToken = cancelToken; } + /// + /// Cancels this resolution context indicating it did not complete successfully. + /// + public virtual void Cancel() + { + this.IsCancelled = true; + } + + /// + /// Gets a value indicating whether this resolution context was canceled, indicating it did not complete + /// its resolution operation successfully. + /// + /// true if this instance is canceled; otherwise, false. + public virtual bool IsCancelled { get; private set; } + /// /// Gets the set of argument, if any, to be supplied to the method the resolver will call to /// complete its operation. /// /// The arguments. - public IExecutionArgumentCollection Arguments { get; } + public IExecutionArgumentCollection ExecutionSuppliedArguments { get; } + + /// + /// Gets a collection of messages that be written to. These messages will be transmitted to the requestor. + /// + /// The message collection available to this context. + public IGraphMessageCollection Messages { get; } + + /// + /// Gets the cancellation token governing this resolution. Any raised cancel requests via this token should be obeyed. + /// + /// The cancellation token governing the resolution of the target schema item. + public CancellationToken CancellationToken { get; } + + /// + /// Gets a service provider instance that can be used to resolve services during this schema item's resolution cycle. + /// + /// The service provider instance available for resolution of services. + public IServiceProvider ServiceProvider { get; } + + /// + /// Gets the master query request that was initially supplied to the runtime. + /// + /// The query request. + public IQueryExecutionRequest QueryRequest { get; } /// /// Gets the request governing the resolver's operation. @@ -64,10 +124,45 @@ protected SchemaItemResolutionContext( /// The user. public ClaimsPrincipal User { get; } + /// + /// Gets a logger instance can be written to to record scoped log entries. + /// + /// The logger. + public IGraphEventLogger Logger { get; } + /// /// Gets the schema that is targeted by this context. /// /// The schema. public ISchema Schema { get; } + + /// + /// Gets the route to the item being resolved. + /// + /// The route. + public abstract SchemaItemPath Route { get; } + + /// + /// Gets the set of arguments defined on the schema that are to be resolved to fulfill this request. + /// + /// The set of arguments to use in resolution. + public abstract IGraphArgumentCollection SchemaDefinedArguments { get; } + + /// + /// Gets the source data item resolved from a parent resolver, if any. May be null. + /// + /// The source data item supplied to this context. + public abstract object SourceData { get; } + + /// + /// Gets the object used to track runtime session data for a single query. + /// + /// + /// This is an internal entity reserved for use by graphql's pipelines and + /// should not be utilized upon by controller action methods. Modification of the data within + /// the session can cause the query execution to break. + /// + /// The active query session. + public IQuerySession Session { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Execution/Contexts/SchemaItemResolutionContext{TRequest}.cs b/src/graphql-aspnet/Execution/Contexts/SchemaItemResolutionContext{TRequest}.cs index 6cbdd2c4c..cbdd045cb 100644 --- a/src/graphql-aspnet/Execution/Contexts/SchemaItemResolutionContext{TRequest}.cs +++ b/src/graphql-aspnet/Execution/Contexts/SchemaItemResolutionContext{TRequest}.cs @@ -7,10 +7,22 @@ // License: MIT // ************************************************************* +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + namespace GraphQL.AspNet.Execution.Contexts { + using System; using System.Security.Claims; + using System.Threading; using GraphQL.AspNet.Interfaces.Execution; + using GraphQL.AspNet.Interfaces.Logging; using GraphQL.AspNet.Interfaces.Schema; /// @@ -24,20 +36,40 @@ public abstract class SchemaItemResolutionContext : SchemaItemResoluti /// /// Initializes a new instance of the class. /// + /// The service provider instance that should be used to resolve any + /// needed services or non-schema arguments to the target resolver. + /// The query session governing the request. /// The schema in scope for this resolution context. - /// The parent context from which this resolution context should - /// extract is base data values. + /// The master query request being executed. /// The resolution request to carry with the context. /// The arguments to be passed to the resolver when its executed. - /// Optional. The user context that authenticated and authorized for this + /// The messages. + /// (Optional) A logger instance that can be used to record scoped log entries. + /// (Optional) The user context that authenticated and authorized for this /// resolution context. + /// The cancel token governing the resolution of the schema item. protected SchemaItemResolutionContext( + IServiceProvider serviceProvider, + IQuerySession querySession, ISchema targetSchema, - IGraphQLMiddlewareExecutionContext parentContext, - TRequest request, + IQueryExecutionRequest queryRequest, + IDataRequest request, IExecutionArgumentCollection arguments, - ClaimsPrincipal user = null) - : base(targetSchema, parentContext, request, arguments, user) + IGraphMessageCollection messages = null, + IGraphEventLogger logger = null, + ClaimsPrincipal user = null, + CancellationToken cancelToken = default) + : base( + serviceProvider, + querySession, + targetSchema, + queryRequest, + request, + arguments, + messages, + logger, + user, + cancelToken) { } diff --git a/src/graphql-aspnet/Execution/ExecutionArgumentCollection.cs b/src/graphql-aspnet/Execution/ExecutionArgumentCollection.cs index 6162d83f0..1dcf40511 100644 --- a/src/graphql-aspnet/Execution/ExecutionArgumentCollection.cs +++ b/src/graphql-aspnet/Execution/ExecutionArgumentCollection.cs @@ -16,6 +16,7 @@ namespace GraphQL.AspNet.Execution using GraphQL.AspNet.Execution.Contexts; using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Interfaces.Execution; + using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Schemas.TypeSystem; /// @@ -25,9 +26,8 @@ namespace GraphQL.AspNet.Execution [DebuggerDisplay("Count = {Count}")] internal class ExecutionArgumentCollection : IExecutionArgumentCollection { - private readonly Dictionary _arguments; - private readonly GraphDirectiveExecutionContext _directiveContext; - private readonly GraphFieldExecutionContext _fieldContext; + private readonly Dictionary _suppliedArgumentDataValues; + private readonly SchemaItemResolutionContext _resolutionContext; /// /// Initializes a new instance of the class. @@ -35,7 +35,7 @@ internal class ExecutionArgumentCollection : IExecutionArgumentCollection /// The initial capacity of the collection, if known. public ExecutionArgumentCollection(int? capacity = null) { - _arguments = capacity.HasValue + _suppliedArgumentDataValues = capacity.HasValue ? new Dictionary(capacity.Value) : new Dictionary(); } @@ -44,45 +44,26 @@ public ExecutionArgumentCollection(int? capacity = null) /// Initializes a new instance of the class. /// /// The argument list keyed by the argument's name in the graph. - /// The field context. + /// The resolution context. private ExecutionArgumentCollection( IDictionary argumentList, - GraphFieldExecutionContext fieldContext) + SchemaItemResolutionContext resolutionContext) { - _arguments = new Dictionary(argumentList); - _fieldContext = fieldContext; - } - - /// - /// Initializes a new instance of the class. - /// - /// The argument list keyed by the argument's name in the graph. - /// The directive context. - private ExecutionArgumentCollection( - IDictionary argumentList, - GraphDirectiveExecutionContext directiveContext) - { - _arguments = new Dictionary(argumentList); - _directiveContext = directiveContext; + _suppliedArgumentDataValues = new Dictionary(argumentList); + _resolutionContext = resolutionContext; } /// public void Add(ExecutionArgument argument) { Validation.ThrowIfNull(argument, nameof(argument)); - _arguments.Add(argument.Name, argument); + _suppliedArgumentDataValues.Add(argument.Name, argument); } /// - public IExecutionArgumentCollection ForContext(GraphFieldExecutionContext fieldContext) + public IExecutionArgumentCollection ForContext(SchemaItemResolutionContext resolutionContext) { - return new ExecutionArgumentCollection(_arguments, fieldContext); - } - - /// - public IExecutionArgumentCollection ForContext(GraphDirectiveExecutionContext directiveContext) - { - return new ExecutionArgumentCollection(_arguments, directiveContext); + return new ExecutionArgumentCollection(_suppliedArgumentDataValues, resolutionContext); } /// @@ -137,10 +118,18 @@ private object ResolveParameterValue(IGraphFieldResolverParameterMetaData paramD Validation.ThrowIfNull(paramDef, nameof(paramDef)); if (paramDef.ArgumentModifiers.IsSourceParameter()) - return this.SourceData; + return _resolutionContext?.SourceData; if (paramDef.ArgumentModifiers.IsCancellationToken()) - return _fieldContext?.CancellationToken ?? default; + return _resolutionContext?.CancellationToken; + + if (paramDef.ArgumentModifiers.IsResolverContext()) + { + if (_resolutionContext != null && Validation.IsCastable(_resolutionContext.GetType(), paramDef.ExpectedType)) + return _resolutionContext; + + return null; + } // if there an argument supplied on the query for this parameter, use that if (this.TryGetValue(paramDef.InternalName, out var arg)) @@ -151,17 +140,8 @@ private object ResolveParameterValue(IGraphFieldResolverParameterMetaData paramD { // additional checks and coersion if this the value is // being supplied from a query - var graphArgument = _fieldContext? - .Request - .Field - .Arguments - .FindArgumentByParameterName(paramDef.InternalName); - - graphArgument = graphArgument ?? - _directiveContext? - .Request - .Directive - .Arguments + var graphArgument = _resolutionContext? + .SchemaDefinedArguments? .FindArgumentByParameterName(paramDef.InternalName); if (graphArgument != null) @@ -182,7 +162,7 @@ private object ResolveParameterValue(IGraphFieldResolverParameterMetaData paramD // but captured here as a saftey net for users // doing custom extensions or implementations // this prevents resolver execution with indeterminate or unexpected data - var path = _fieldContext?.Request?.Field?.Route.Path ?? _directiveContext?.Request?.Directive?.Route.Path ?? "~unknown~"; + var path = _resolutionContext?.Route.Path; throw new GraphExecutionException( $"The parameter '{paramDef.InternalName}' for schema item '{path}' could not be resolved from the query document " + "or variable collection and no default value was found."); @@ -190,11 +170,7 @@ private object ResolveParameterValue(IGraphFieldResolverParameterMetaData paramD } // its not a formal argument in the schema, try and resolve from DI container - object serviceResolvedValue = null; - if (_fieldContext != null) - serviceResolvedValue = _fieldContext.ServiceProvider?.GetService(paramDef.ExpectedType); - else if (_directiveContext != null) - serviceResolvedValue = _directiveContext.ServiceProvider?.GetService(paramDef.ExpectedType); + object serviceResolvedValue = _resolutionContext?.ServiceProvider?.GetService(paramDef.ExpectedType); // the service was found in the DI container!! *happy* if (serviceResolvedValue != null) @@ -204,8 +180,7 @@ private object ResolveParameterValue(IGraphFieldResolverParameterMetaData paramD if (paramDef.HasDefaultValue) return paramDef.DefaultValue; - var schemaItem = _fieldContext?.Request.Field.Route.Path - ?? _directiveContext?.Request.Directive.Route.Path + var schemaItem = _resolutionContext?.Route.Path ?? paramDef.InternalFullName; // error unable to resolve correctly. *womp womp* @@ -216,33 +191,30 @@ private object ResolveParameterValue(IGraphFieldResolverParameterMetaData paramD } /// - public bool ContainsKey(string key) => _arguments.ContainsKey(key); + public bool ContainsKey(string key) => _suppliedArgumentDataValues.ContainsKey(key); /// public bool TryGetValue(string key, out ExecutionArgument value) { - return _arguments.TryGetValue(key, out value); + return _suppliedArgumentDataValues.TryGetValue(key, out value); } /// - public ExecutionArgument this[string key] => _arguments[key]; - - /// - public IEnumerable Keys => _arguments.Keys; + public ExecutionArgument this[string key] => _suppliedArgumentDataValues[key]; /// - public IEnumerable Values => _arguments.Values; + public IEnumerable Keys => _suppliedArgumentDataValues.Keys; /// - public int Count => _arguments.Count; + public IEnumerable Values => _suppliedArgumentDataValues.Values; /// - public object SourceData => _fieldContext?.Request?.Data?.Value; + public int Count => _suppliedArgumentDataValues.Count; /// public IEnumerator> GetEnumerator() { - return _arguments.GetEnumerator(); + return _suppliedArgumentDataValues.GetEnumerator(); } /// diff --git a/src/graphql-aspnet/Execution/GraphMessageCollection.cs b/src/graphql-aspnet/Execution/GraphMessageCollection.cs index 844f747f2..9fecbe3b1 100644 --- a/src/graphql-aspnet/Execution/GraphMessageCollection.cs +++ b/src/graphql-aspnet/Execution/GraphMessageCollection.cs @@ -48,7 +48,7 @@ public GraphMessageCollection(int capacity) /// public void AddRange(IGraphMessageCollection messagesToAdd) { - if (messagesToAdd == null || messagesToAdd.Count == 0) + if (messagesToAdd == null || messagesToAdd == this || messagesToAdd.Count == 0) return; lock (_messages) diff --git a/src/graphql-aspnet/Execution/Resolvers/FunctionGraphFieldResolver{TSource,TReturn}.cs b/src/graphql-aspnet/Execution/Resolvers/FunctionGraphFieldResolver{TSource,TReturn}.cs index 5361130fd..af8cef282 100644 --- a/src/graphql-aspnet/Execution/Resolvers/FunctionGraphFieldResolver{TSource,TReturn}.cs +++ b/src/graphql-aspnet/Execution/Resolvers/FunctionGraphFieldResolver{TSource,TReturn}.cs @@ -44,7 +44,7 @@ public FunctionGraphFieldResolver(Func> func) /// public async Task ResolveAsync(FieldResolutionContext context, CancellationToken cancelToken = default) { - var data = await _func(context?.Arguments.SourceData as TSource).ConfigureAwait(false); + var data = await _func(context?.SourceData as TSource).ConfigureAwait(false); context.Result = data; } diff --git a/src/graphql-aspnet/Execution/Resolvers/GraphControllerActionResolver.cs b/src/graphql-aspnet/Execution/Resolvers/GraphControllerActionResolver.cs index 2f7aefead..ea42381b9 100644 --- a/src/graphql-aspnet/Execution/Resolvers/GraphControllerActionResolver.cs +++ b/src/graphql-aspnet/Execution/Resolvers/GraphControllerActionResolver.cs @@ -37,7 +37,6 @@ public GraphControllerActionResolver(IGraphFieldResolverMetaData actionResolverM } /// - [DebuggerStepThrough] public async Task ResolveAsync(FieldResolutionContext context, CancellationToken cancelToken = default) { IGraphActionResult result; diff --git a/src/graphql-aspnet/Execution/Resolvers/Introspeection/Schema_TypeGraphFieldResolver.cs b/src/graphql-aspnet/Execution/Resolvers/Introspeection/Schema_TypeGraphFieldResolver.cs index d080e0d34..0a2fbe5d9 100644 --- a/src/graphql-aspnet/Execution/Resolvers/Introspeection/Schema_TypeGraphFieldResolver.cs +++ b/src/graphql-aspnet/Execution/Resolvers/Introspeection/Schema_TypeGraphFieldResolver.cs @@ -39,7 +39,7 @@ public Schema_TypeGraphFieldResolver(IntrospectedSchema schema) /// public Task ResolveAsync(FieldResolutionContext resolutionContext, CancellationToken cancelToken = default) { - if (!resolutionContext.Arguments.TryGetArgument("name", out var name)) + if (!resolutionContext.ExecutionSuppliedArguments.TryGetArgument("name", out var name)) { resolutionContext.Messages.Critical("Required Argument 'name' not found."); } diff --git a/src/graphql-aspnet/Execution/Resolvers/Introspeection/Type_EnumValuesGraphFieldResolver.cs b/src/graphql-aspnet/Execution/Resolvers/Introspeection/Type_EnumValuesGraphFieldResolver.cs index 91d39b49e..c2f1c1eb3 100644 --- a/src/graphql-aspnet/Execution/Resolvers/Introspeection/Type_EnumValuesGraphFieldResolver.cs +++ b/src/graphql-aspnet/Execution/Resolvers/Introspeection/Type_EnumValuesGraphFieldResolver.cs @@ -32,7 +32,7 @@ public Type_EnumValuesGraphFieldResolver() /// public Task ResolveAsync(FieldResolutionContext resolutionContext, CancellationToken cancelToken = default) { - var sourceData = resolutionContext.Arguments.SourceData as IntrospectedType; + var sourceData = resolutionContext.SourceData as IntrospectedType; if (sourceData == null) { @@ -40,8 +40,8 @@ public Task ResolveAsync(FieldResolutionContext resolutionContext, CancellationT } else { - var includedDeprecated = resolutionContext.Arguments.ContainsKey(Constants.ReservedNames.DEPRECATED_ARGUMENT_NAME) - && (bool)resolutionContext.Arguments[Constants.ReservedNames.DEPRECATED_ARGUMENT_NAME].Value; + var includedDeprecated = resolutionContext.ExecutionSuppliedArguments.ContainsKey(Constants.ReservedNames.DEPRECATED_ARGUMENT_NAME) + && (bool)resolutionContext.ExecutionSuppliedArguments[Constants.ReservedNames.DEPRECATED_ARGUMENT_NAME].Value; if (includedDeprecated) resolutionContext.Result = sourceData.EnumValues; diff --git a/src/graphql-aspnet/Execution/Resolvers/Introspeection/Type_TypeGraphFieldResolver.cs b/src/graphql-aspnet/Execution/Resolvers/Introspeection/Type_TypeGraphFieldResolver.cs index 9bbe91c61..058fbdb75 100644 --- a/src/graphql-aspnet/Execution/Resolvers/Introspeection/Type_TypeGraphFieldResolver.cs +++ b/src/graphql-aspnet/Execution/Resolvers/Introspeection/Type_TypeGraphFieldResolver.cs @@ -31,7 +31,7 @@ public Type_TypeGraphFieldResolver() /// public Task ResolveAsync(FieldResolutionContext context, CancellationToken cancelToken = default) { - var sourceData = context.Arguments.SourceData as IntrospectedType; + var sourceData = context.SourceData as IntrospectedType; if (sourceData == null) { @@ -39,8 +39,8 @@ public Task ResolveAsync(FieldResolutionContext context, CancellationToken cance } else { - var includedDeprecated = context.Arguments.ContainsKey(Constants.ReservedNames.DEPRECATED_ARGUMENT_NAME) - && (bool)context.Arguments[Constants.ReservedNames.DEPRECATED_ARGUMENT_NAME].Value; + var includedDeprecated = context.ExecutionSuppliedArguments.ContainsKey(Constants.ReservedNames.DEPRECATED_ARGUMENT_NAME) + && (bool)context.ExecutionSuppliedArguments[Constants.ReservedNames.DEPRECATED_ARGUMENT_NAME].Value; if (includedDeprecated) context.Result = sourceData.Fields; diff --git a/src/graphql-aspnet/Execution/Resolvers/ObjectMethodGraphFieldResolver.cs b/src/graphql-aspnet/Execution/Resolvers/ObjectMethodGraphFieldResolver.cs index bf64469d6..cf5ddfc65 100644 --- a/src/graphql-aspnet/Execution/Resolvers/ObjectMethodGraphFieldResolver.cs +++ b/src/graphql-aspnet/Execution/Resolvers/ObjectMethodGraphFieldResolver.cs @@ -10,6 +10,7 @@ namespace GraphQL.AspNet.Execution.Resolvers { using System; + using System.Diagnostics; using System.Reflection; using System.Threading; using System.Threading.Tasks; @@ -24,6 +25,7 @@ namespace GraphQL.AspNet.Execution.Resolvers /// A field resolver that will invoke a schema pipeline for whatever schema is beng processed /// resulting in the configured handling the request. /// + [DebuggerDisplay("Prop Resolver: {MetaData.InternalName}")] internal class ObjectMethodGraphFieldResolver : IGraphFieldResolver { private readonly MethodInfo _methodInfo; @@ -41,7 +43,7 @@ public ObjectMethodGraphFieldResolver(IGraphFieldResolverMetaData resolverMetada /// public virtual async Task ResolveAsync(FieldResolutionContext context, CancellationToken cancelToken = default) { - var sourceData = context.Arguments?.SourceData; + var sourceData = context.SourceData; if (sourceData == null) { context.Messages.Critical( @@ -54,7 +56,7 @@ public virtual async Task ResolveAsync(FieldResolutionContext context, Cancellat } var typeCheck = _methodInfo.ReflectedType ?? _methodInfo.DeclaringType; - if (context.Arguments.SourceData.GetType() != typeCheck) + if (context.SourceData?.GetType() != typeCheck) { context.Messages.Critical( "The source data provided to the field resolver " + @@ -73,10 +75,10 @@ public virtual async Task ResolveAsync(FieldResolutionContext context, Cancellat { object data = null; - var paramSet = context.Arguments.PrepareArguments(this.MetaData); + var paramSet = context.ExecutionSuppliedArguments.PrepareArguments(this.MetaData); var invoker = InstanceFactory.CreateInstanceMethodInvoker(this.MetaData.Method); - var invokableObject = context.Arguments.SourceData as object; + var invokableObject = context.SourceData as object; var invokeReturn = invoker(ref invokableObject, paramSet); if (this.MetaData.IsAsyncField) { diff --git a/src/graphql-aspnet/Execution/Resolvers/ObjectPropertyGraphFieldResolver.cs b/src/graphql-aspnet/Execution/Resolvers/ObjectPropertyGraphFieldResolver.cs index 020137ad7..8dce133c0 100644 --- a/src/graphql-aspnet/Execution/Resolvers/ObjectPropertyGraphFieldResolver.cs +++ b/src/graphql-aspnet/Execution/Resolvers/ObjectPropertyGraphFieldResolver.cs @@ -24,7 +24,7 @@ namespace GraphQL.AspNet.Execution.Resolvers /// A resolver that extracts a property from an object and returns it as a field value. /// /// - [DebuggerDisplay("Prop Resolver: {_graphMethod.Name}")] + [DebuggerDisplay("Prop Resolver: {MetaData.InternalFullName}")] internal class ObjectPropertyGraphFieldResolver : IGraphFieldResolver { /// @@ -39,7 +39,7 @@ public ObjectPropertyGraphFieldResolver(IGraphFieldResolverMetaData resolverMeta /// public async Task ResolveAsync(FieldResolutionContext context, CancellationToken cancelToken = default) { - var sourceData = context.Arguments.SourceData; + var sourceData = context.SourceData; if (sourceData == null) { context.Messages.Critical( diff --git a/src/graphql-aspnet/Interfaces/Execution/IExecutionArgumentCollection.cs b/src/graphql-aspnet/Interfaces/Execution/IExecutionArgumentCollection.cs index 56068c652..844e0ef91 100644 --- a/src/graphql-aspnet/Interfaces/Execution/IExecutionArgumentCollection.cs +++ b/src/graphql-aspnet/Interfaces/Execution/IExecutionArgumentCollection.cs @@ -20,32 +20,24 @@ namespace GraphQL.AspNet.Interfaces.Execution public interface IExecutionArgumentCollection : IReadOnlyDictionary { /// - /// Augments the collection with a source data object for a specific field execution and returns - /// a copy of itself with that data attached. + /// Augments the collection with data related the specific resolution. This is used to extract and apply + /// execution arguments supplied on the query to the target resolver. /// - /// The field context being executed. + /// The field or directive context being executed. /// IExecutionArgumentCollection. - IExecutionArgumentCollection ForContext(GraphFieldExecutionContext fieldExecutionContext); + IExecutionArgumentCollection ForContext(SchemaItemResolutionContext resolutionContext); /// - /// Augments the collection with a source data object for a specific field execution and returns - /// a copy of itself with that data attached. + /// Adds the specified argument value found at runtime. /// - /// The directive context being executed. - /// IExecutionArgumentCollection. - IExecutionArgumentCollection ForContext(GraphDirectiveExecutionContext directiveContext); - - /// - /// Adds the specified argument to the collection. - /// - /// The argument. + /// The argument value. void Add(ExecutionArgument argument); /// /// Attempts to retrieve and cast the given argument to the value provided. /// /// The type to cast to. - /// Name of the argument. + /// Name of the argument as it appears in the schema. /// The value to be filled if cast. /// true if the argument was found and cast, false otherwise. bool TryGetArgument(string argumentName, out T value); @@ -57,11 +49,5 @@ public interface IExecutionArgumentCollection : IReadOnlyDictionaryThe graph method. /// System.Object[]. object[] PrepareArguments(IGraphFieldResolverMetaData graphMethod); - - /// - /// Gets the source data, if any, that is supplying values for this execution run. - /// - /// The source data. - object SourceData { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Middleware/DirectiveExecution/Components/InvokeDirectiveResolverMiddleware.cs b/src/graphql-aspnet/Middleware/DirectiveExecution/Components/InvokeDirectiveResolverMiddleware.cs index 4a266437a..fa31c4a65 100644 --- a/src/graphql-aspnet/Middleware/DirectiveExecution/Components/InvokeDirectiveResolverMiddleware.cs +++ b/src/graphql-aspnet/Middleware/DirectiveExecution/Components/InvokeDirectiveResolverMiddleware.cs @@ -44,14 +44,19 @@ public async Task InvokeAsync(GraphDirectiveExecutionContext context, GraphMiddl } else { - executionArguments = executionArguments.ForContext(context); - + // resolution context messages + // are seperate by design var resolutionContext = new DirectiveResolutionContext( + context.ServiceProvider, + context.Session, context.Schema, - context, + context.QueryRequest, context.Request, executionArguments, - context.User); + new GraphMessageCollection(), + context.Logger, + context.User, + context.CancellationToken); // execute the directive await context diff --git a/src/graphql-aspnet/Middleware/FieldExecution/Components/InvokeFieldResolverMiddleware.cs b/src/graphql-aspnet/Middleware/FieldExecution/Components/InvokeFieldResolverMiddleware.cs index ec400e931..0c2b25283 100644 --- a/src/graphql-aspnet/Middleware/FieldExecution/Components/InvokeFieldResolverMiddleware.cs +++ b/src/graphql-aspnet/Middleware/FieldExecution/Components/InvokeFieldResolverMiddleware.cs @@ -107,14 +107,18 @@ private async Task ExecuteContextAsync(GraphFieldExecutionContext context, return false; } - executionArguments = executionArguments.ForContext(context); - + // resolution context messages are independent var resolutionContext = new FieldResolutionContext( + context.ServiceProvider, + context.Session, _schema, - context, + context.QueryRequest, context.Request, executionArguments, - context.User); + new GraphMessageCollection(), + context.Logger, + context.User, + context.CancellationToken); // Step 2: Resolve the field context.Logger?.FieldResolutionStarted(resolutionContext); diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphArgumentTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphArgumentTemplate.cs index b97952431..861e29fa3 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphArgumentTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphArgumentTemplate.cs @@ -20,6 +20,7 @@ namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates using GraphQL.AspNet.Common; using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Execution; + using GraphQL.AspNet.Execution.Contexts; using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Execution.Resolvers; using GraphQL.AspNet.Interfaces.Execution; @@ -132,10 +133,32 @@ public virtual void Parse() if (this.IsCancellationTokenArgument()) _foundModifiers.Add(GraphArgumentModifiers.CancellationToken); + if (this.IsResolutionContext()) + _foundModifiers.Add(GraphArgumentModifiers.ResolutionContext); + if (_foundModifiers.Count == 1) this.ArgumentModifier = _foundModifiers.First(); } + /// + /// Determines whether this instance represents a parameter that should be marked as a "resolution context" + /// and filled with the active context when possible. + /// + /// true if the ; otherwise, false. + public virtual bool IsResolutionContext() + { + if (this.Parent.Arguments.Any(x => x.ArgumentModifier.IsResolverContext())) + return false; + + if (Validation.IsCastable(this.ObjectType, typeof(FieldResolutionContext)) && this.Parent is IGraphFieldTemplate) + return true; + + if (Validation.IsCastable(this.ObjectType, typeof(DirectiveResolutionContext)) && this.Parent is IGraphDirectiveTemplate) + return true; + + return false; + } + /// /// Determines whether this instance represents a parameter that should be marked as the "source data" /// for the field its attached to. @@ -143,7 +166,7 @@ public virtual void Parse() /// System.Boolean. protected virtual bool IsSourceDataArgument() { - if (this.Parent.Arguments.Any(x => x.ArgumentModifier.HasFlag(GraphArgumentModifiers.ParentFieldResult))) + if (this.Parent.Arguments.Any(x => x.ArgumentModifier.IsSourceParameter())) return false; if (_foundModifiers.Count > 0) diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphFieldTemplateBase.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphFieldTemplateBase.cs index 7e484e29f..f23d96650 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphFieldTemplateBase.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphFieldTemplateBase.cs @@ -36,6 +36,7 @@ public abstract class GraphFieldTemplateBase : SchemaItemTemplateBase, IGraphFie private AppliedSecurityPolicyGroup _securityPolicies; private GraphFieldAttribute _fieldDeclaration; private bool _invalidTypeExpression; + private bool _returnsActionResult; /// /// Initializes a new instance of the class. @@ -133,6 +134,7 @@ protected override void ParseTemplateDefinition() // ------------------------------------ if (Validation.IsCastable(objectType)) { + _returnsActionResult = true; if (this.UnionProxy != null) { // if a union was decalred preserve whatever modifer elements @@ -217,9 +219,7 @@ public override void ValidateOrThrow() } // ensure the object type returned by the graph field is set correctly - bool returnsActionResult = Validation.IsCastable(this.ObjectType); var enforceUnionRules = this.UnionProxy != null; - if (this.PossibleTypes.Count == 0) { throw new GraphTypeDeclarationException( @@ -278,7 +278,7 @@ public override void ValidateOrThrow() // declarations are not required at this stage // // batch processed fields are not subject to this restriction - if (!returnsActionResult && this.Mode == FieldResolutionMode.PerSourceItem && !Validation.IsCastable(type, this.ObjectType)) + if (!_returnsActionResult && this.Mode == FieldResolutionMode.PerSourceItem && !Validation.IsCastable(type, this.ObjectType)) { throw new GraphTypeDeclarationException( $"The field '{this.InternalFullName}' returns '{this.ObjectType.FriendlyName()}' and declares a possible type of '{type.FriendlyName()}' " + diff --git a/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiers.cs b/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiers.cs index e71bb8003..f250ea2f0 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiers.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiers.cs @@ -51,5 +51,10 @@ public enum GraphArgumentModifiers /// or if the type was explicitly excluded from the graph via attributions. /// ExplicitSchemaItem, + + /// + /// This paraemter is declared to be resolved as the active resolution context being processed by a controller action. + /// + ResolutionContext, } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiersExtensions.cs b/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiersExtensions.cs index a98fa6fe6..af7b87597 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiersExtensions.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiersExtensions.cs @@ -6,15 +6,25 @@ // -- // License: MIT // ************************************************************* + namespace GraphQL.AspNet.Schemas.TypeSystem { - using System.Runtime.CompilerServices; - /// /// Extension helper methods for . /// public static class GraphArgumentModifiersExtensions { + /// + /// Determines whether the modifers indicate the argument is to contain the context of + /// the directive or field being resolved by the target resolver. + /// + /// The modifiers to check. + /// true if the parameters represent the resolver context; otherwise, false. + public static bool IsResolverContext(this GraphArgumentModifiers modifiers) + { + return modifiers == GraphArgumentModifiers.ResolutionContext; + } + /// /// Determines whether the modifers indicate the argument is to contain the source data value supplied to the resolver for the field. /// diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Controllers/ControllerExtensionTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Controllers/ControllerExtensionTests.cs index 152e88997..f3e1e8656 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Controllers/ControllerExtensionTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Controllers/ControllerExtensionTests.cs @@ -31,7 +31,7 @@ public async Task PublishSubEvent_PublishesEventWithCorrectData() .AddGraphController() .Build(); - var fieldContextBuilder = server.CreateGraphTypeFieldContextBuilder( + var fieldContextBuilder = server.CreateActionMethodFieldContextBuilder( nameof(InvokableController.MutationRaisesSubEvent)); var arg1Value = "random string"; @@ -69,7 +69,7 @@ public void PublishSubEvent_NoDataThrowsException() .AddController() .Build(); - var fieldContextBuilder = server.CreateGraphTypeFieldContextBuilder( + var fieldContextBuilder = server.CreateActionMethodFieldContextBuilder( nameof(InvokableController.MutationRaisesSubEventNoData)); var arg1Value = "random string"; @@ -92,7 +92,7 @@ public async Task PublishSubEvent_ExistingEventCollectionisAppendedTo() .AddController() .Build(); - var fieldContextBuilder = server.CreateGraphTypeFieldContextBuilder( + var fieldContextBuilder = server.CreateActionMethodFieldContextBuilder( nameof(InvokableController.MutationRaisesSubEvent)); var arg1Value = "random string"; @@ -119,7 +119,7 @@ public void PublishSubEvent_UnusableListForSubscriptionEvents_ThrowsException() .AddController() .Build(); - var fieldContextBuilder = server.CreateGraphTypeFieldContextBuilder( + var fieldContextBuilder = server.CreateActionMethodFieldContextBuilder( nameof(InvokableController.MutationRaisesSubEvent)); var arg1Value = "random string"; @@ -147,7 +147,7 @@ public void PublishSubEvent_NoEventNameFailsTheResolver_BubblesExceptionUp() .AddController() .Build(); - var fieldContextBuilder = server.CreateGraphTypeFieldContextBuilder( + var fieldContextBuilder = server.CreateActionMethodFieldContextBuilder( nameof(InvokableController.MutationRaiseSubEventWithNoEventName)); var arg1Value = "random string"; diff --git a/src/unit-tests/graphql-aspnet-testframework/GraphQLTemplateHelper.cs b/src/unit-tests/graphql-aspnet-testframework/GraphQLTemplateHelper.cs index ab9ffb6e9..9c8adc83e 100644 --- a/src/unit-tests/graphql-aspnet-testframework/GraphQLTemplateHelper.cs +++ b/src/unit-tests/graphql-aspnet-testframework/GraphQLTemplateHelper.cs @@ -56,7 +56,9 @@ public static IGraphFieldTemplate CreateActionMethodTemplate(string var template = new SingleMethodGraphControllerTemplate(methodName); template.Parse(); template.ValidateOrThrow(); - return template.FieldTemplates.FirstOrDefault(x => x.Value.InternalName.Equals(methodName, StringComparison.OrdinalIgnoreCase)).Value; + return template + .FieldTemplates + .FirstOrDefault(x => x.Value.InternalName.Equals(methodName, StringComparison.OrdinalIgnoreCase)).Value; } /// @@ -143,7 +145,6 @@ public static IGraphTypeTemplate CreateGraphTypeTemplate(Type objectType, TypeKi /// The type to create a template of. /// IObjectGraphTypeTemplate. public static IObjectGraphTypeTemplate CreateObjectTemplate() - where TObject : class { return CreateGraphTypeTemplate(TypeKind.OBJECT) as IObjectGraphTypeTemplate; } @@ -154,7 +155,6 @@ public static IObjectGraphTypeTemplate CreateObjectTemplate() /// The type to create a template of. /// IInputObjectGraphTypeTemplate. public static IInputObjectGraphTypeTemplate CreateInputObjectTemplate() - where TObject : class { return CreateGraphTypeTemplate(TypeKind.INPUT_OBJECT) as IInputObjectGraphTypeTemplate; } diff --git a/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/FieldContextBuilder.cs b/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/FieldContextBuilder.cs index 22c584209..cb80ce1fc 100644 --- a/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/FieldContextBuilder.cs +++ b/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/FieldContextBuilder.cs @@ -27,6 +27,7 @@ namespace GraphQL.AspNet.Tests.Framework.PipelineContextBuilders using Moq; using GraphQL.AspNet.Interfaces.Execution.QueryPlans.DocumentParts; using GraphQL.AspNet.Interfaces.Execution.QueryPlans.InputArguments; + using System.Threading; /// /// A builder used to create inlined mocked replacements @@ -51,13 +52,13 @@ public class FieldContextBuilder /// The user security context. /// The graph field. /// The schema. - /// The metadata describing the method/functon to be invoked by a resolver. + /// The metadata describing the method/functon to be invoked by a resolver. public FieldContextBuilder( IServiceProvider serviceProvider, IUserSecurityContext userSecurityContext, IGraphField graphField, ISchema schema, - IGraphFieldResolverMetaData metaData) + IGraphFieldResolverMetaData resolverMetadata) { _schema = Validation.ThrowIfNullOrReturn(schema, nameof(schema)); _graphField = Validation.ThrowIfNullOrReturn(graphField, nameof(graphField)); @@ -69,8 +70,8 @@ public FieldContextBuilder( Type expectedInputType = null; - if (!Validation.IsCastable(metaData.ParentObjectType) - && !Validation.IsCastable(metaData.ParentObjectType)) + if (!Validation.IsCastable(resolverMetadata.ParentObjectType) + && !Validation.IsCastable(resolverMetadata.ParentObjectType)) { if (graphField.Parent is IInterfaceGraphType iif) expectedInputType = iif.ObjectType; @@ -103,16 +104,16 @@ public FieldContextBuilder( _mockRequest.Setup(x => x.InvocationContext).Returns(_mockInvocationContext.Object); this.ResolverMetaData = new Mock(); - this.ResolverMetaData.Setup(x => x.ParentInternalFullName).Returns(metaData.ParentInternalFullName); - this.ResolverMetaData.Setup(x => x.ParentInternalName).Returns(metaData.ParentInternalName); - this.ResolverMetaData.Setup(x => x.ParentObjectType).Returns(metaData.ParentObjectType); - this.ResolverMetaData.Setup(x => x.ExpectedReturnType).Returns(metaData.ExpectedReturnType); - this.ResolverMetaData.Setup(x => x.Method).Returns(metaData.Method); - this.ResolverMetaData.Setup(x => x.IsAsyncField).Returns(metaData.IsAsyncField); - this.ResolverMetaData.Setup(x => x.InternalName).Returns(metaData.InternalName); - this.ResolverMetaData.Setup(x => x.InternalFullName).Returns(metaData.InternalFullName); - this.ResolverMetaData.Setup(x => x.InternalName).Returns(metaData.InternalName); - this.ResolverMetaData.Setup(x => x.Parameters).Returns(metaData.Parameters); + this.ResolverMetaData.Setup(x => x.ParentInternalFullName).Returns(resolverMetadata.ParentInternalFullName); + this.ResolverMetaData.Setup(x => x.ParentInternalName).Returns(resolverMetadata.ParentInternalName); + this.ResolverMetaData.Setup(x => x.ParentObjectType).Returns(resolverMetadata.ParentObjectType); + this.ResolverMetaData.Setup(x => x.ExpectedReturnType).Returns(resolverMetadata.ExpectedReturnType); + this.ResolverMetaData.Setup(x => x.Method).Returns(resolverMetadata.Method); + this.ResolverMetaData.Setup(x => x.IsAsyncField).Returns(resolverMetadata.IsAsyncField); + this.ResolverMetaData.Setup(x => x.InternalName).Returns(resolverMetadata.InternalName); + this.ResolverMetaData.Setup(x => x.InternalFullName).Returns(resolverMetadata.InternalFullName); + this.ResolverMetaData.Setup(x => x.InternalName).Returns(resolverMetadata.InternalName); + this.ResolverMetaData.Setup(x => x.Parameters).Returns(resolverMetadata.Parameters); } /// @@ -225,13 +226,17 @@ public FieldResolutionContext CreateResolutionContext() context.Messages, out var executionArguments); - executionArguments = executionArguments.ForContext(context); - return new FieldResolutionContext( + this.ServiceProvider, + context.Session, _schema, - this.CreateFakeParentMiddlewareContext(), + context.QueryRequest, this.FieldRequest, - executionArguments); + executionArguments, + context.Messages, + context.Logger, + context.User, + CancellationToken.None); } /// diff --git a/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/SingleMethodGraphControllerTemplate.cs b/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/SingleMethodGraphControllerTemplate.cs index 89c0dbb5a..9e7cab6a0 100644 --- a/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/SingleMethodGraphControllerTemplate.cs +++ b/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/SingleMethodGraphControllerTemplate.cs @@ -9,27 +9,26 @@ namespace GraphQL.AspNet.Tests.Framework.PipelineContextBuilders { - using GraphQL.AspNet.Controllers; + using System; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Schemas.Generation.TypeTemplates; /// /// A mocked controller template that will selectively parse actions instead of the whole template. /// - /// The type of the controller to templatize. - public class SingleMethodGraphControllerTemplate : GraphControllerTemplate - where TControllerType : GraphController + public class SingleMethodGraphControllerTemplate : GraphControllerTemplate { private readonly string _methodName; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// + /// Type of the controller. /// Name of the single action method to parse. When not - /// provided (e.g. null) this template will function the same as + /// provided (e.g. null) this template will function the same as /// and all methods will be parsed. - public SingleMethodGraphControllerTemplate(string methodName = null) - : base(typeof(TControllerType)) + public SingleMethodGraphControllerTemplate(Type controllerType, string methodName = null) + : base(controllerType) { _methodName = methodName; } diff --git a/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/SingleMethodGraphControllerTemplate{TControllerType}.cs b/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/SingleMethodGraphControllerTemplate{TControllerType}.cs new file mode 100644 index 000000000..978d708db --- /dev/null +++ b/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/SingleMethodGraphControllerTemplate{TControllerType}.cs @@ -0,0 +1,33 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Framework.PipelineContextBuilders +{ + using GraphQL.AspNet.Controllers; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; + + /// + /// A mocked controller template that will selectively parse actions instead of the whole template. + /// + /// The type of the controller to templatize. + public class SingleMethodGraphControllerTemplate : SingleMethodGraphControllerTemplate + where TControllerType : GraphController + { + /// + /// Initializes a new instance of the class. + /// + /// Name of the single action method to parse. When not + /// provided (e.g. null) this template will function the same as + /// and all methods will be parsed. + public SingleMethodGraphControllerTemplate(string methodName = null) + : base(typeof(TControllerType), methodName) + { + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-testframework/TestServer.cs b/src/unit-tests/graphql-aspnet-testframework/TestServer.cs index f67cd0d23..ba5bf8b2c 100644 --- a/src/unit-tests/graphql-aspnet-testframework/TestServer.cs +++ b/src/unit-tests/graphql-aspnet-testframework/TestServer.cs @@ -16,6 +16,7 @@ namespace GraphQL.AspNet.Tests.Framework using System.Text.Json; using System.Threading; using System.Threading.Tasks; + using GraphQL.AspNet.Common; using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Directives; @@ -191,124 +192,58 @@ public virtual GraphTypeCreationResult CreateGraphType(Type concreteType, TypeKi /// Creates a builder that will generate a field execution context for an action on a target controller. This /// context can be submitted against the field execution pipeline to generate a result. /// - /// The type of the controller that owns the - /// action. - /// Name of the action/field in the controller, as it exists in the schema. + /// The type of the entity that owns . + /// Name of the field as it exists on the schema. /// FieldContextBuilder. - public virtual FieldContextBuilder CreateGraphTypeFieldContextBuilder(string actionName) - where TController : GraphController + public virtual FieldContextBuilder CreateGraphTypeFieldContextBuilder(string fieldName) { - var template = GraphQLTemplateHelper.CreateFieldTemplate(actionName); + var graphType = this.Schema.KnownTypes.FindGraphType(typeof(TEntity), TypeKind.OBJECT) as IObjectGraphType; + if (graphType == null) + { + throw new InvalidOperationException($"Unknown or unregistered OBJECT graph for type {typeof(TEntity).FriendlyName()}. This method " + + $"can only create a context builder for OBJECT graph types."); + } - var fieldMaker = new GraphFieldMaker(this.Schema, new GraphArgumentMaker(this.Schema)); - var fieldResult = fieldMaker.CreateField(template); + var field = graphType.Fields.FindField(fieldName); + if (field == null) + { + throw new InvalidOperationException($"The graph type '{graphType.Name}' does not contain a field named '{fieldName}'. " + + $"Field names are case sensitive."); + } var builder = new FieldContextBuilder( this.ServiceProvider, _userSecurityContext, - fieldResult.Field, + field, this.Schema, - template.CreateResolverMetaData()); + field.Resolver.MetaData); builder.AddSourceData(new object()); return builder; } /// - /// Creates a low level field execution context that can be processed by the test server. + /// Creates a builder that will generate the various field processing contexts for an action method on a target controller.. /// - /// The concrete type representing the graph type in the schema. - /// Name of the field, on the type, as it exists in the schema. - /// The source data to use as the input to the field. This can be changed, but must be supplied. A - /// generic will be used if not supplied. - /// The collection of arguments that need to be supplied - /// to the field to properly resolve it. + /// The type of the controller that owns the + /// action. + /// Name of the action/field in the controller, as it exists in the schema. /// FieldContextBuilder. - public virtual GraphFieldExecutionContext CreateFieldExecutionContext( - string fieldName, - object sourceData, - IInputArgumentCollection arguments = null) + public virtual FieldContextBuilder CreateActionMethodFieldContextBuilder(string actionName) { - IGraphType graphType = this.Schema.KnownTypes.FindGraphType(typeof(TType)); - - if (graphType == null) - { - throw new InvalidOperationException($"Unable to locate a registered graph type that matched the supplied source data (Type: {typeof(TType).FriendlyName()})"); - } - - var typedGraphType = graphType as ITypedSchemaItem; - if (typedGraphType == null) - { - throw new InvalidOperationException($"The target graph type '{graphType.Name}' is not a strongly typed graph type and cannot be invoked via this builder."); - } - - var container = graphType as IGraphFieldContainer; - if (container == null) - { - throw new InvalidOperationException($"The target graph type '{graphType.Name}' is not a field container. No field context builder can be created."); - } - - var field = container.Fields.FindField(fieldName); - if (field == null) - { - throw new InvalidOperationException($"The target graph type '{graphType.Name}' does not contain a field named '{fieldName}'."); - } + var fieldTemplate = GraphQLTemplateHelper.CreateFieldTemplate(actionName); + var fieldMaker = new GraphFieldMaker(this.Schema, new GraphArgumentMaker(this.Schema)); + var fieldResult = fieldMaker.CreateField(fieldTemplate); - arguments = arguments ?? InputArgumentCollectionFactory.Create(); - var messages = new GraphMessageCollection(); - var metaData = new MetaDataCollection(); + var builder = new FieldContextBuilder( + this.ServiceProvider, + _userSecurityContext, + fieldResult.Field, + this.Schema, + fieldTemplate.CreateResolverMetaData()); - var queryRequest = new Mock(); - var fieldInvocationContext = new Mock(); - var parentContext = new Mock(); - var graphFieldRequest = new Mock(); - var fieldDocumentPart = new Mock(); - - queryRequest.Setup(x => x.Items).Returns(metaData); - - parentContext.Setup(x => x.QueryRequest).Returns(queryRequest.Object); - parentContext.Setup(x => x.ServiceProvider).Returns(this.ServiceProvider); - parentContext.Setup(x => x.SecurityContext).Returns(this.SecurityContext); - parentContext.Setup(x => x.Metrics).Returns(null as IQueryExecutionMetrics); - parentContext.Setup(x => x.Logger).Returns(null as IGraphEventLogger); - parentContext.Setup(x => x.Messages).Returns(() => messages); - parentContext.Setup(x => x.IsValid).Returns(() => messages.IsSucessful); - parentContext.Setup(x => x.Session).Returns(new QuerySession()); - - fieldDocumentPart.Setup(x => x.Name).Returns(field.Name); - fieldDocumentPart.Setup(x => x.Alias).Returns(field.Name); - fieldDocumentPart.Setup(x => x.Field).Returns(field); - - fieldInvocationContext.Setup(x => x.ExpectedSourceType).Returns(typeof(TType)); - fieldInvocationContext.Setup(x => x.Field).Returns(field); - fieldInvocationContext.Setup(x => x.Arguments).Returns(arguments); - fieldInvocationContext.Setup(x => x.Name).Returns(field.Name); - fieldInvocationContext.Setup(x => x.ChildContexts).Returns(new FieldInvocationContextCollection()); - fieldInvocationContext.Setup(x => x.Origin).Returns(SourceOrigin.None); - fieldInvocationContext.Setup(x => x.Schema).Returns(this.Schema); - fieldInvocationContext.Setup(x => x.FieldDocumentPart).Returns(fieldDocumentPart.Object); - - var resolvedParentDataItem = new FieldDataItem( - fieldInvocationContext.Object, - sourceData, - SourcePath.None); - - var sourceDataContainer = new FieldDataItemContainer( - sourceData, - SourcePath.None, - resolvedParentDataItem); - - var id = Guid.NewGuid(); - graphFieldRequest.Setup(x => x.Id).Returns(id); - graphFieldRequest.Setup(x => x.Origin).Returns(SourceOrigin.None); - graphFieldRequest.Setup(x => x.Field).Returns(field); - graphFieldRequest.Setup(x => x.InvocationContext).Returns(fieldInvocationContext.Object); - graphFieldRequest.Setup(x => x.Data).Returns(() => sourceDataContainer); - - return new GraphFieldExecutionContext( - parentContext.Object, - graphFieldRequest.Object, - ResolvedVariableCollectionFactory.Create()); + builder.AddSourceData(new object()); + return builder; } /// diff --git a/src/unit-tests/graphql-aspnet-tests/Controllers/ActionResults/ActionResultTests.cs b/src/unit-tests/graphql-aspnet-tests/Controllers/ActionResults/ActionResultTests.cs index 8fa2aa3ca..87795e9f8 100644 --- a/src/unit-tests/graphql-aspnet-tests/Controllers/ActionResults/ActionResultTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Controllers/ActionResults/ActionResultTests.cs @@ -34,7 +34,7 @@ private FieldResolutionContext CreateResolutionContext() .AddType() .Build(); - var builder = server.CreateGraphTypeFieldContextBuilder( + var builder = server.CreateActionMethodFieldContextBuilder( nameof(ActionableController.DoStuff)); return builder.CreateResolutionContext(); } diff --git a/src/unit-tests/graphql-aspnet-tests/Controllers/GraphControllerTests.cs b/src/unit-tests/graphql-aspnet-tests/Controllers/GraphControllerTests.cs index b580a56a4..10263c66f 100644 --- a/src/unit-tests/graphql-aspnet-tests/Controllers/GraphControllerTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Controllers/GraphControllerTests.cs @@ -29,7 +29,7 @@ public async Task MethodInvocation_EnsureInternalPropertiesAreSet() .AddGraphController() .Build(); - var fieldContextBuilder = server.CreateGraphTypeFieldContextBuilder( + var fieldContextBuilder = server.CreateActionMethodFieldContextBuilder( nameof(InvokableController.AsyncActionMethod)); fieldContextBuilder.AddInputArgument("arg1", "random string"); @@ -58,7 +58,7 @@ public async Task MethodInvocation_SyncMethodReturnsObjectNotTask() .AddGraphController() .Build(); - var fieldContextBuilder = tester.CreateGraphTypeFieldContextBuilder( + var fieldContextBuilder = tester.CreateActionMethodFieldContextBuilder( nameof(InvokableController.SyncronousActionMethod)); fieldContextBuilder.AddInputArgument("arg1", "random string"); @@ -76,7 +76,7 @@ public async Task MethodInvocation_UnawaitableAsyncMethodFlag_ResultsInInternalE var tester = new TestServerBuilder(TestOptions.UseCodeDeclaredNames) .AddGraphController() .Build(); - var fieldContextBuilder = tester.CreateGraphTypeFieldContextBuilder( + var fieldContextBuilder = tester.CreateActionMethodFieldContextBuilder( nameof(InvokableController.SyncronousActionMethod)); fieldContextBuilder.AddInputArgument("arg1", "random string"); @@ -97,7 +97,7 @@ public async Task MethodInvocation_MissingMethodInfo_ReturnsInternalServerError( var tester = new TestServerBuilder(TestOptions.UseCodeDeclaredNames) .AddGraphController() .Build(); - var fieldContextBuilder = tester.CreateGraphTypeFieldContextBuilder( + var fieldContextBuilder = tester.CreateActionMethodFieldContextBuilder( nameof(InvokableController.SyncronousActionMethod)); fieldContextBuilder.AddInputArgument("arg1", "random string"); fieldContextBuilder.ResolverMetaData.Setup(x => x.Method).Returns(null); @@ -117,7 +117,7 @@ public void MethodInvocation_UserCodeExceptionIsAllowedToThrow() var tester = new TestServerBuilder(TestOptions.UseCodeDeclaredNames) .AddGraphController() .Build(); - var fieldContextBuilder = tester.CreateGraphTypeFieldContextBuilder( + var fieldContextBuilder = tester.CreateActionMethodFieldContextBuilder( nameof(InvokableController.AsyncActionMethodToCauseException)); fieldContextBuilder.AddInputArgument("arg1", "random string"); @@ -134,7 +134,7 @@ public async Task ErrorResult() .AddType() .Build(); - var fieldContextBuilder = server.CreateGraphTypeFieldContextBuilder( + var fieldContextBuilder = server.CreateActionMethodFieldContextBuilder( nameof(InvokableController.ErrorResult)); var controller = new InvokableController(); diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/ContextTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/ContextTests.cs index 2db12c546..2b9aea746 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/ContextTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/ContextTests.cs @@ -10,6 +10,7 @@ namespace GraphQL.AspNet.Tests.Execution { using System; + using System.Security.Claims; using GraphQL.AspNet.Execution; using GraphQL.AspNet.Execution.Contexts; using GraphQL.AspNet.Interfaces.Execution; @@ -111,34 +112,35 @@ public void GraphDirectiveExecutionContext_PropertyCheck() var variableData = new Mock(); var serviceProvider = new Mock(); var logger = new Mock(); - var metrics = new Mock(); - var securityContext = new Mock(); var schema = new GraphSchema(); - - parentContext.Setup(x => x.QueryRequest).Returns(queryRequest.Object); - parentContext.Setup(x => x.ServiceProvider).Returns(serviceProvider.Object); - parentContext.Setup(x => x.SecurityContext).Returns(securityContext.Object); - parentContext.Setup(x => x.Metrics).Returns(metrics.Object); - parentContext.Setup(x => x.Logger).Returns(logger.Object); - parentContext.Setup(x => x.Session).Returns(new QuerySession()); + var user = new ClaimsPrincipal(); + var session = new QuerySession(); + var messages = new GraphMessageCollection(); var args = new Mock(); var directiveRequest = new Mock(); var sourceFieldCollection = new FieldSourceCollection(); var context = new DirectiveResolutionContext( + serviceProvider.Object, + session, schema, - parentContext.Object, + queryRequest.Object, directiveRequest.Object, - args.Object); + args.Object, + messages, + logger.Object, + user); Assert.AreEqual(queryRequest.Object, context.QueryRequest); Assert.AreEqual(directiveRequest.Object, context.Request); Assert.AreEqual(serviceProvider.Object, context.ServiceProvider); Assert.AreEqual(logger.Object, context.Logger); - Assert.AreEqual(metrics.Object, context.Metrics); - Assert.AreEqual(securityContext.Object, context.SecurityContext); + Assert.AreEqual(user, context.User); Assert.AreEqual(schema, context.Schema); + Assert.AreEqual(directiveRequest.Object, context.Request); + Assert.AreEqual(messages, context.Messages); + Assert.AreEqual(session, context.Session); } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/ExecutionArgumentTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/ExecutionArgumentTests.cs index 5be15eed7..64223ce59 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/ExecutionArgumentTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/ExecutionArgumentTests.cs @@ -82,25 +82,16 @@ public void PrepareArguments_WhenArgumentShouldComeFromDI_AndExistsInDI_IsPrepar var testServer = builder.Build(); - var template = new ObjectGraphTypeTemplate(typeof(ObjectWithFields)); - template.Parse(); - template.ValidateOrThrow(); - - var fieldMetadata = template - .FieldTemplates - .Values - .FirstOrDefault(x => x.InternalName == nameof(ObjectWithFields.FieldWithInjectedArgument)) - .CreateResolverMetaData(); + var contextBuilder = testServer + .CreateGraphTypeFieldContextBuilder(nameof(ObjectWithFields.FieldWithInjectedArgument)); - var context = testServer.CreateFieldExecutionContext( - nameof(ObjectWithFields.FieldWithInjectedArgument), - new ObjectWithFields()); + var context = contextBuilder.CreateResolutionContext(); // mimic a situation where no values are parsed from a query (no execution args) var argSet = new ExecutionArgumentCollection() as IExecutionArgumentCollection; argSet = argSet.ForContext(context); - var resolvedArgs = argSet.PrepareArguments(fieldMetadata); + var resolvedArgs = argSet.PrepareArguments(contextBuilder.ResolverMetaData.Object); Assert.IsNotNull(resolvedArgs); Assert.AreEqual(1, resolvedArgs.Length); @@ -121,19 +112,10 @@ public void PrepareArguments_WhenArgumentShouldComeFromDI_AndDoesNotExistInDI_An var testServer = builder.Build(); - var template = new ObjectGraphTypeTemplate(typeof(ObjectWithFields)); - template.Parse(); - template.ValidateOrThrow(); - - var fieldMetadata = template - .FieldTemplates - .Values - .FirstOrDefault(x => x.InternalName == nameof(ObjectWithFields.FieldWithInjectedArgument)) - .CreateResolverMetaData(); + var contextBuilder = testServer + .CreateGraphTypeFieldContextBuilder(nameof(ObjectWithFields.FieldWithInjectedArgument)); - var context = testServer.CreateFieldExecutionContext( - nameof(ObjectWithFields.FieldWithInjectedArgument), - new ObjectWithFields()); + var context = contextBuilder.CreateResolutionContext(); // mimic a situation where no values are parsed from a query (no execution args) // and no default value is present @@ -142,7 +124,7 @@ public void PrepareArguments_WhenArgumentShouldComeFromDI_AndDoesNotExistInDI_An Assert.Throws(() => { - var resolvedArgs = argSet.PrepareArguments(fieldMetadata); + var resolvedArgs = argSet.PrepareArguments(contextBuilder.ResolverMetaData.Object); }); } @@ -160,27 +142,16 @@ public void PrepareArguments_WhenArgumentShouldComeFromDI_AndDoesNotExistInDI_An var testServer = builder.Build(); - var template = new ObjectGraphTypeTemplate(typeof(ObjectWithFields)); - template.Parse(); - template.ValidateOrThrow(); - - var fieldMetadata = template - .FieldTemplates - .Values - .FirstOrDefault(x => x.InternalName == nameof(ObjectWithFields.FieldWithInjectedArgumentWithDefaultValue)) - .CreateResolverMetaData(); - - var context = testServer.CreateFieldExecutionContext( - nameof(ObjectWithFields.FieldWithInjectedArgumentWithDefaultValue), - new ObjectWithFields()); + var contextBuilder = testServer + .CreateGraphTypeFieldContextBuilder(nameof(ObjectWithFields.FieldWithInjectedArgumentWithDefaultValue)); // mimic a situation where no values are parsed from a query (no execution args) // and nothing is available from DI // but the parameter declares a default value var argSet = new ExecutionArgumentCollection() as IExecutionArgumentCollection; - argSet = argSet.ForContext(context); + argSet = argSet.ForContext(contextBuilder.CreateResolutionContext()); - var resolvedArgs = argSet.PrepareArguments(fieldMetadata); + var resolvedArgs = argSet.PrepareArguments(contextBuilder.ResolverMetaData.Object); Assert.IsNotNull(resolvedArgs); Assert.AreEqual(1, resolvedArgs.Length); Assert.IsNull(resolvedArgs[0]); @@ -204,23 +175,16 @@ public void PrepareArguments_WhenArgumentShouldComeFromSchema_HasNoSuppliedValue template.Parse(); template.ValidateOrThrow(); - var fieldMetadata = template - .FieldTemplates - .Values - .FirstOrDefault(x => x.InternalName == nameof(ObjectWithFields.FieldWithNullableSchemaArgument)) - .CreateResolverMetaData(); - - var context = testServer.CreateFieldExecutionContext( - nameof(ObjectWithFields.FieldWithNullableSchemaArgument), - new ObjectWithFields()); + var fieldBuilder = testServer + .CreateGraphTypeFieldContextBuilder(nameof(ObjectWithFields.FieldWithNullableSchemaArgument)); // mimic a situation where no values are parsed from a query (no execution args) // and nothing is available from DI // but the parameter declares a default value var argSet = new ExecutionArgumentCollection() as IExecutionArgumentCollection; - argSet = argSet.ForContext(context); + argSet = argSet.ForContext(fieldBuilder.CreateResolutionContext()); - var resolvedArgs = argSet.PrepareArguments(fieldMetadata); + var resolvedArgs = argSet.PrepareArguments(fieldBuilder.ResolverMetaData.Object); Assert.IsNotNull(resolvedArgs); Assert.AreEqual(1, resolvedArgs.Length); Assert.IsNull(resolvedArgs[0]); @@ -240,27 +204,16 @@ public void PrepareArguments_WhenArgumentShouldComeFromSchema_HasNoSuppliedValue var testServer = builder.Build(); - var template = new ObjectGraphTypeTemplate(typeof(ObjectWithFields)); - template.Parse(); - template.ValidateOrThrow(); - - var fieldMetadata = template - .FieldTemplates - .Values - .FirstOrDefault(x => x.InternalName == nameof(ObjectWithFields.FieldWithNonNullableSchemaArgumentThatHasDefaultValue)) - .CreateResolverMetaData(); - - var context = testServer.CreateFieldExecutionContext( - nameof(ObjectWithFields.FieldWithNonNullableSchemaArgumentThatHasDefaultValue), - new ObjectWithFields()); + var fieldBuilder = testServer + .CreateGraphTypeFieldContextBuilder(nameof(ObjectWithFields.FieldWithNonNullableSchemaArgumentThatHasDefaultValue)); // mimic a situation where no values are parsed from a query (no execution args) // and nothing is available from DI // but the parameter declares a default value var argSet = new ExecutionArgumentCollection() as IExecutionArgumentCollection; - argSet = argSet.ForContext(context); + argSet = argSet.ForContext(fieldBuilder.CreateResolutionContext()); - var resolvedArgs = argSet.PrepareArguments(fieldMetadata); + var resolvedArgs = argSet.PrepareArguments(fieldBuilder.ResolverMetaData.Object); Assert.IsNotNull(resolvedArgs); Assert.AreEqual(1, resolvedArgs.Length); Assert.AreEqual(3, resolvedArgs[0]); @@ -280,28 +233,17 @@ public void PrepareArguments_WhenArgumentShouldComeFromQuery_AndIsNotSupplied_An var testServer = builder.Build(); - var template = new ObjectGraphTypeTemplate(typeof(ObjectWithFields)); - template.Parse(); - template.ValidateOrThrow(); - - var fieldMetadata = template - .FieldTemplates - .Values - .FirstOrDefault(x => x.InternalName == nameof(ObjectWithFields.FieldWithNotNullableQueryArgument)) - .CreateResolverMetaData(); - - var context = testServer.CreateFieldExecutionContext( - nameof(ObjectWithFields.FieldWithNotNullableQueryArgument), - new ObjectWithFields()); + var fieldBuilder = testServer + .CreateGraphTypeFieldContextBuilder(nameof(ObjectWithFields.FieldWithNotNullableQueryArgument)); // mimic a situation where no values are parsed from a query (no execution args) // but the argument expected there to be var argSet = new ExecutionArgumentCollection() as IExecutionArgumentCollection; - argSet = argSet.ForContext(context); + argSet = argSet.ForContext(fieldBuilder.CreateResolutionContext()); Assert.Throws(() => { - var resolvedArgs = argSet.PrepareArguments(fieldMetadata); + var resolvedArgs = argSet.PrepareArguments(fieldBuilder.ResolverMetaData.Object); }); } } diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionTests.cs index 0def7e3a1..627210f02 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionTests.cs @@ -27,7 +27,7 @@ public async Task SingleFieldResolution_ViaPipeline_YieldsCorrectResult() .AddType() .Build(); - var builder = server.CreateGraphTypeFieldContextBuilder( + var builder = server.CreateActionMethodFieldContextBuilder( nameof(SimpleExecutionController.SimpleQueryMethod)); builder.AddInputArgument("arg1", "my value"); builder.AddInputArgument("arg2", 15L); diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeFieldTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeFieldTests.cs index dd788ce68..05cfd4f2a 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeFieldTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeFieldTests.cs @@ -9,10 +9,13 @@ namespace GraphQL.AspNet.Tests.Execution { + using System; + using System.Linq; using System.Threading.Tasks; using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Controllers.ActionResults; using GraphQL.AspNet.Execution; + using GraphQL.AspNet.Execution.Contexts; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Execution.TestData.RuntimeFieldTest; @@ -486,5 +489,131 @@ public async Task Runtime_StandardField_WithSecurityParams_AndUnAuthorizedUser_R Assert.AreEqual(GraphMessageSeverity.Critical, result.Messages[0].Severity); Assert.AreEqual(Constants.ErrorCodes.ACCESS_DENIED, result.Messages[0].Code); } + + [Test] + public async Task Runtime_StandardField_ReturnsNullableT_RendersValue() + { + var serverBuilder = new TestServerBuilder(); + + serverBuilder.AddGraphQL(o => + { + o.MapQuery("field", () => new int?(3)); + }); + + var server = serverBuilder.Build(); + + var field = server.Schema.Operations[GraphOperationType.Query].Fields.Single(x => x.Name == "field"); + Assert.AreEqual(typeof(int), field.ObjectType); + Assert.AreEqual("Int", field.TypeExpression.ToString()); // no !, not required + + var builder = server.CreateQueryContextBuilder(); + builder.AddQueryText(@"query { field }"); + + var result = await server.RenderResult(builder); + CommonAssertions.AreEqualJsonStrings( + @"{ + ""data"": { + ""field"": 3 + } + }", + result); + } + + [Test] + public async Task Runtime_StandardField_ReturnsNullableT_RendersNull() + { + var serverBuilder = new TestServerBuilder(); + + serverBuilder.AddGraphQL(o => + { + o.MapQuery("field", () => + { + int? value = null; + return value; + }); + }); + + var server = serverBuilder.Build(); + + var field = server.Schema.Operations[GraphOperationType.Query].Fields.Single(x => x.Name == "field"); + Assert.AreEqual(typeof(int), field.ObjectType); + Assert.AreEqual("Int", field.TypeExpression.ToString()); // no !, not required + + var builder = server.CreateQueryContextBuilder(); + builder.AddQueryText(@"query { field }"); + + var result = await server.RenderResult(builder); + CommonAssertions.AreEqualJsonStrings( + @"{ + ""data"": { + ""field"": null + } + }", + result); + } + + [Test] + public async Task Runtime_StandardField_ReturnsNullableT_ThroughActionResult() + { + var serverBuilder = new TestServerBuilder(); + + serverBuilder.AddGraphQL(o => + { + o.MapQuery("field", () => + { + return GraphActionResult.Ok(3); + }) + .AddPossibleTypes(typeof(int?)); + }); + + var server = serverBuilder.Build(); + + var field = server.Schema.Operations[GraphOperationType.Query].Fields.Single(x => x.Name == "field"); + Assert.AreEqual(typeof(int), field.ObjectType); + Assert.AreEqual("Int", field.TypeExpression.ToString()); // no !, not required + + var builder = server.CreateQueryContextBuilder(); + builder.AddQueryText(@"query { field }"); + + var result = await server.RenderResult(builder); + CommonAssertions.AreEqualJsonStrings( + @"{ + ""data"": { + ""field"": 3 + } + }", + result); + } + + [Test] + public async Task Runtime_StandardField_FieldResolutionContext_IsInjected_WhenRequested() + { + var serverBuilder = new TestServerBuilder(); + + serverBuilder.AddGraphQL(o => + { + o.MapQuery("field", (FieldResolutionContext context) => + { + if (context != null && context.Request.Field != null) + return 1; + + return 0; + }); + }); + + var server = serverBuilder.Build(); + + var builder = server.CreateQueryContextBuilder(); + builder.AddQueryText(@"query { field }"); + + var result = await server.RenderResult(builder); + CommonAssertions.AreEqualJsonStrings( + @"{ + ""data"": { + ""field"": 1 + } + }", + result); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeTypeExtensionTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeTypeExtensionTests.cs index fcc553d2d..bbc51ebbc 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeTypeExtensionTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeTypeExtensionTests.cs @@ -73,7 +73,8 @@ public void TypeExtension_OfObject_WithMetaNameField_ThrowsDeclarationException( }); }); - var ex = Assert.Throws(() => { + var ex = Assert.Throws(() => + { builder.Build(); }); @@ -367,8 +368,6 @@ public async Task Runtime_ExecutionDirective_WithSecurityParams_AndUnAuthenticat Assert.AreEqual(1, result.Messages.Count); Assert.AreEqual(GraphMessageSeverity.Critical, result.Messages[0].Severity); Assert.AreEqual(Constants.ErrorCodes.ACCESS_DENIED, result.Messages[0].Code); - - } [Test] diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TypeSystemDirectiveCommonTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TypeSystemDirectiveCommonTests.cs index 039a710a9..94fa2f39f 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TypeSystemDirectiveCommonTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TypeSystemDirectiveCommonTests.cs @@ -30,10 +30,12 @@ public async Task ExtendAResolver_DirectiveDeclaredByType() LastName = "Smith", }; - var context = server.CreateFieldExecutionContext( - nameof(TestPersonWithResolverExtensionDirectiveByType.Name), - person); + var contextBuilder = server.CreateGraphTypeFieldContextBuilder( + nameof(TestPersonWithResolverExtensionDirectiveByType.Name)); + contextBuilder.AddSourceData(person); + + var context = contextBuilder.CreateExecutionContext(); await server.ExecuteField(context); var data = context.Result?.ToString(); @@ -54,10 +56,12 @@ public async Task ExtendAResolver_DirectiveDeclaredByName() LastName = "Smith", }; - var context = server.CreateFieldExecutionContext( - nameof(TestPersonWithResolverExtensionDirectiveByName.Name), - person); + var contextBuilder = server.CreateGraphTypeFieldContextBuilder( + nameof(TestPersonWithResolverExtensionDirectiveByName.Name)); + + contextBuilder.AddSourceData(person); + var context = contextBuilder.CreateExecutionContext(); await server.ExecuteField(context); var data = context.Result?.ToString(); @@ -80,10 +84,12 @@ public async Task DirectiveDeclaredByName_AndDirectiveHasCustomName_IsFoundAndEx LastName = "Smith", }; - var context = server.CreateFieldExecutionContext( - nameof(TestPersonWithResolverExtensionDirectiveByName.Name), - person); + var contextBuilder = server.CreateGraphTypeFieldContextBuilder( + nameof(TestPersonWithResolverExtensionDirectiveByName.Name)); + contextBuilder.AddSourceData(person); + + var context = contextBuilder.CreateExecutionContext(); await server.ExecuteField(context); var data = context.Result?.ToString(); @@ -104,9 +110,10 @@ public async Task ExtendAnObjectType_AddField_DirectiveDeclaredByType() Property2 = "prop 2", }; - var context = server.CreateFieldExecutionContext( - "property3", - obj); + var contextBuilder = server.CreateGraphTypeFieldContextBuilder("property3") + .AddSourceData(obj); + + var context = contextBuilder.CreateExecutionContext(); await server.ExecuteField(context); diff --git a/src/unit-tests/graphql-aspnet-tests/Logging/ActionMethodModelStateValidatedLogEntryTests.cs b/src/unit-tests/graphql-aspnet-tests/Logging/ActionMethodModelStateValidatedLogEntryTests.cs index 9b12dcf51..7df8d572c 100644 --- a/src/unit-tests/graphql-aspnet-tests/Logging/ActionMethodModelStateValidatedLogEntryTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Logging/ActionMethodModelStateValidatedLogEntryTests.cs @@ -110,7 +110,7 @@ public void InvalidModelItem_BuildsLogEntry() .AddType() .Build(); - var builder = server.CreateGraphTypeFieldContextBuilder( + var builder = server.CreateActionMethodFieldContextBuilder( nameof(LogTestController.ValidatableInputObject)); var context = builder.CreateExecutionContext(); @@ -140,7 +140,7 @@ public void ValidModelItem_BuildsLogEntry() .AddType() .Build(); - var builder = server.CreateGraphTypeFieldContextBuilder( + var builder = server.CreateActionMethodFieldContextBuilder( nameof(LogTestController.ValidatableInputObject)); var context = builder.CreateExecutionContext(); diff --git a/src/unit-tests/graphql-aspnet-tests/Logging/GeneralEventLogEntryPropertyChecks.cs b/src/unit-tests/graphql-aspnet-tests/Logging/GeneralEventLogEntryPropertyChecks.cs index efe574a46..875f93b8c 100644 --- a/src/unit-tests/graphql-aspnet-tests/Logging/GeneralEventLogEntryPropertyChecks.cs +++ b/src/unit-tests/graphql-aspnet-tests/Logging/GeneralEventLogEntryPropertyChecks.cs @@ -241,7 +241,7 @@ public void FieldResolutionStartedLogEntry() .AddType() .Build(); - var package = server.CreateGraphTypeFieldContextBuilder( + var package = server.CreateActionMethodFieldContextBuilder( nameof(LogTestController.ExecuteField2)); var resolutionContext = package.CreateResolutionContext(); @@ -261,7 +261,7 @@ public void FieldResolutionCompletedLogEntry() .AddType() .Build(); - var package = server.CreateGraphTypeFieldContextBuilder( + var package = server.CreateActionMethodFieldContextBuilder( nameof(LogTestController.ExecuteField2)); var resolutionContext = package.CreateResolutionContext(); var fieldRequest = package.FieldRequest; @@ -287,7 +287,7 @@ public void FieldAuthorizationStartedLogEntry() builder.UserContext.Authenticate("bobSmith"); var server = builder.Build(); - var package = server.CreateGraphTypeFieldContextBuilder( + var package = server.CreateActionMethodFieldContextBuilder( nameof(LogTestController.ExecuteField2)); var fieldRequest = package.FieldRequest; @@ -312,7 +312,7 @@ public void FieldAuthorizationCompletedLogEntry() builder.UserContext.Authenticate("bobSmith"); var server = builder.Build(); - var package = server.CreateGraphTypeFieldContextBuilder( + var package = server.CreateActionMethodFieldContextBuilder( nameof(LogTestController.ExecuteField2)); var fieldRequest = package.FieldRequest; var authContext = package.CreateSecurityContext(); @@ -339,7 +339,7 @@ public void FieldAuthenticationStartedLogEntry() builder.UserContext.Authenticate("bobSmith"); var server = builder.Build(); - var package = server.CreateGraphTypeFieldContextBuilder( + var package = server.CreateActionMethodFieldContextBuilder( nameof(LogTestController.ExecuteField2)); var fieldRequest = package.FieldRequest; @@ -372,7 +372,7 @@ public void FieldAuthenticationCompletedLogEntry() authResult.Setup(x => x.AuthenticationScheme).Returns("testScheme"); authResult.Setup(x => x.Suceeded).Returns(true); - var package = server.CreateGraphTypeFieldContextBuilder( + var package = server.CreateActionMethodFieldContextBuilder( nameof(LogTestController.ExecuteField2)); var fieldRequest = package.FieldRequest; @@ -400,7 +400,7 @@ public void ActionMethodInvocationStartedLogEntry() .AddType() .Build(); var graphMethod = GraphQLTemplateHelper.CreateActionMethodTemplate(nameof(LogTestController.ExecuteField2)).CreateResolverMetaData(); - var package = server.CreateGraphTypeFieldContextBuilder( + var package = server.CreateActionMethodFieldContextBuilder( nameof(LogTestController.ExecuteField2)); var fieldRequest = package.FieldRequest; @@ -422,7 +422,7 @@ public void ActionMethodInvocationCompletedLogEntry() .Build(); var metaData = GraphQLTemplateHelper.CreateActionMethodTemplate(nameof(LogTestController.ExecuteField2)).CreateResolverMetaData(); - var package = server.CreateGraphTypeFieldContextBuilder( + var package = server.CreateActionMethodFieldContextBuilder( nameof(LogTestController.ExecuteField2)); var resolutionContext = package.CreateResolutionContext(); var fieldRequest = package.FieldRequest; @@ -447,7 +447,7 @@ public void ActionMethodInvocationExceptionLogEntry() .Build(); var metaData = GraphQLTemplateHelper.CreateActionMethodTemplate(nameof(LogTestController.ExecuteField2)).CreateResolverMetaData(); - var package = server.CreateGraphTypeFieldContextBuilder( + var package = server.CreateActionMethodFieldContextBuilder( nameof(LogTestController.ExecuteField2)); var fieldRequest = package.FieldRequest; @@ -477,7 +477,7 @@ public void ActionMethodUnhandledExceptionLogEntry() .AddType() .Build(); - var package = server.CreateGraphTypeFieldContextBuilder( + var package = server.CreateActionMethodFieldContextBuilder( nameof(LogTestController.ExecuteField2)); var template = GraphQLTemplateHelper.CreateActionMethodTemplate(nameof(LogTestController.ExecuteField2)); var metaData = template.CreateResolverMetaData(); diff --git a/src/unit-tests/graphql-aspnet-tests/Middleware/MiddlewarePipelineTests.cs b/src/unit-tests/graphql-aspnet-tests/Middleware/MiddlewarePipelineTests.cs index aaa6791e4..798be0150 100644 --- a/src/unit-tests/graphql-aspnet-tests/Middleware/MiddlewarePipelineTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Middleware/MiddlewarePipelineTests.cs @@ -60,7 +60,7 @@ public async Task SingularPipelineInvokesComponentsInOrder() // fake a graph ql request context var server = serverBuilder.Build(); - var fieldBuilder = server.CreateGraphTypeFieldContextBuilder( + var fieldBuilder = server.CreateActionMethodFieldContextBuilder( nameof(MiddlewareController.FieldOfData)); var executionContext = fieldBuilder.CreateExecutionContext(); @@ -111,7 +111,7 @@ public void NoFoundMiddlewareComponent_ThrowsException() // fake a graph ql request context var server = serverBuilder.Build(); - var fieldBuilder = server.CreateGraphTypeFieldContextBuilder( + var fieldBuilder = server.CreateActionMethodFieldContextBuilder( nameof(MiddlewareController.FieldOfData)); var executionContext = fieldBuilder.CreateExecutionContext(); @@ -143,7 +143,7 @@ public async Task MiddlewareComponentThrowsExceptions_MiddlewareInvokerShouldUnw // fake a graph ql request context var server = serverBuilder.Build(); - var builder = server.CreateGraphTypeFieldContextBuilder( + var builder = server.CreateActionMethodFieldContextBuilder( nameof(MiddlewareController.FieldOfData)); var context = builder.CreateExecutionContext(); @@ -188,7 +188,7 @@ public async Task SingletonMiddlewareComponent_IsNeverInstantiatedMoreThanOnce() // fake a graph ql request context var server = serverBuilder.Build(); - var builder = server.CreateGraphTypeFieldContextBuilder( + var builder = server.CreateActionMethodFieldContextBuilder( nameof(MiddlewareController.FieldOfData)); // execute the pipeline multiple times @@ -238,7 +238,7 @@ public async Task SingletonMiddlewareWithUserProvidedInstance_NeverAttemptsToCre Assert.IsNotNull(pipeline); var server = serverBuilder.Build(); - var builder = server.CreateGraphTypeFieldContextBuilder( + var builder = server.CreateActionMethodFieldContextBuilder( nameof(MiddlewareController.FieldOfData)); // make an empty service collection (preventing creation if the middleware isnt found) diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GraphTypeExpressionTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GraphTypeExpressionTests.cs index fd893cd34..65c9b7d92 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/GraphTypeExpressionTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GraphTypeExpressionTests.cs @@ -165,34 +165,36 @@ public void ParseDeclaration( } } - [TestCase(null, "String", false)] - [TestCase("String", null, false)] - [TestCase(null, null, false)] - [TestCase("String", "String", true)] - [TestCase("String", "String", true)] - [TestCase("[String]", "[String]", true)] - [TestCase("[String!]", "[String!]", true)] - [TestCase("[String]!", "[String]!", true)] - [TestCase("[String!]!", "[String!]!", true)] - [TestCase("String", "Int", false)] - [TestCase("String", "string", false)] - [TestCase("String", "String!", true)] - [TestCase("String", "[String]", false)] - [TestCase("[String]", "String", false)] - [TestCase("[Int]", "[Int]!", true)] - [TestCase("[Int!]", "[Int]", false)] - [TestCase("[Int]", "[Int!]", true)] - [TestCase("[Int]", "[[Int]]", false)] - [TestCase("[[[Int]!]]", "[[[Int!]!]!]!", true)] - [TestCase("[[[Int]!]]!", "[[[Int!]!]!]!", true)] - [TestCase("[[[Int!]]!]", "[[[Int!]!]!]!", true)] - [TestCase("[[[String!]]!]", "[[[Float!]!]!]!", false)] - public void AreCompatiable(string targetExpression, string suppliedExpression, bool shouldBeCompatiable) + [TestCase(null, "String", true, false)] + [TestCase("String", null, true, false)] + [TestCase(null, null, true, false)] + [TestCase("String", "String", true, true)] + [TestCase("String", "String", true, true)] + [TestCase("[String]", "[String]", true, true)] + [TestCase("[String!]", "[String!]", true, true)] + [TestCase("[String]!", "[String]!", true, true)] + [TestCase("[String!]!", "[String!]!", true, true)] + [TestCase("String", "Int", true, false)] + [TestCase("String", "string", true, false)] + [TestCase("String", "String!", true, true)] + [TestCase("String", "[String]", true, false)] + [TestCase("[String]", "String", true, false)] + [TestCase("[Int]", "[Int]!", true, true)] + [TestCase("[Int!]", "[Int]", true, false)] + [TestCase("[Int]", "[Int!]", true, true)] + [TestCase("[Int]", "[[Int]]", true, false)] + [TestCase("[[[Int]!]]", "[[[Int!]!]!]!", true, true)] + [TestCase("[[[Int]!]]!", "[[[Int!]!]!]!", true, true)] + [TestCase("[[[Int!]]!]", "[[[Int!]!]!]!", true, true)] + [TestCase("[[[String!]]!]", "[[[Float!]!]!]!", true, false)] + [TestCase("[Int!]!", "[String!]!", false, true)] + [TestCase("[Int!]!", "[String!]!", true, false)] + public void AreCompatiable(string targetExpression, string suppliedExpression, bool matchTypeName, bool shouldBeCompatiable) { var target = targetExpression == null ? null : GraphTypeExpression.FromDeclaration(targetExpression); var supplied = suppliedExpression == null ? null : GraphTypeExpression.FromDeclaration(suppliedExpression); - var result = GraphTypeExpression.AreTypesCompatiable(target, supplied); + var result = GraphTypeExpression.AreTypesCompatiable(target, supplied, matchTypeName); Assert.AreEqual(shouldBeCompatiable, result); } diff --git a/src/unit-tests/graphql-aspnet-tests/Security/SecurityPipelineTests.cs b/src/unit-tests/graphql-aspnet-tests/Security/SecurityPipelineTests.cs index ee1c84100..0ce7cc461 100644 --- a/src/unit-tests/graphql-aspnet-tests/Security/SecurityPipelineTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Security/SecurityPipelineTests.cs @@ -58,7 +58,7 @@ public async Task RolePolicy_UserNotInRole_Fails() builder.UserContext.AddUserRole("role4"); var server = builder.Build(); - var fieldBuilder = server.CreateGraphTypeFieldContextBuilder( + var fieldBuilder = server.CreateActionMethodFieldContextBuilder( nameof(Controller_NoPolicies.RequireRolePolicy_RequiresRole1)); var authContext = fieldBuilder.CreateSecurityContext(); @@ -79,7 +79,7 @@ public async Task RolePolicy_UserInRole_Success() builder.UserContext.AddUserRole("role1"); var server = builder.Build(); - var fieldBuilder = server.CreateGraphTypeFieldContextBuilder( + var fieldBuilder = server.CreateActionMethodFieldContextBuilder( nameof(Controller_NoPolicies.RequireRolePolicy_RequiresRole1)); var authContext = fieldBuilder.CreateSecurityContext(); @@ -103,7 +103,7 @@ public async Task MultiPolicyCheck_UserPassesAll_Success() var server = builder.Build(); - var fieldBuilder = server.CreateGraphTypeFieldContextBuilder( + var fieldBuilder = server.CreateActionMethodFieldContextBuilder( nameof(Controller_NoPolicies.MultiPolicyMethod_RequireRole6_RequireClaim7)); var authContext = fieldBuilder.CreateSecurityContext(); @@ -130,7 +130,7 @@ public async Task MultiPolicyCheck_UserPassesOnly1_Fail() var server = builder.Build(); - var fieldBuilder = server.CreateGraphTypeFieldContextBuilder( + var fieldBuilder = server.CreateActionMethodFieldContextBuilder( nameof(Controller_NoPolicies.MultiPolicyMethod_RequireRole6_RequireClaim7)); var authContext = fieldBuilder.CreateSecurityContext(); @@ -150,7 +150,7 @@ public async Task DirectRoleCheck_UserDoesNotHaveRole_Fails() var server = builder.Build(); // policy name isnt declared on the controller method - var fieldBuilder = server.CreateGraphTypeFieldContextBuilder( + var fieldBuilder = server.CreateActionMethodFieldContextBuilder( nameof(Controller_NoPolicies.MethodHasRoles_Role5)); var authContext = fieldBuilder.CreateSecurityContext(); @@ -170,7 +170,7 @@ public async Task DirectRoleCheck_UserHasRole_Succeeds() var server = builder.Build(); // policy name isnt declared on the controller method - var fieldBuilder = server.CreateGraphTypeFieldContextBuilder( + var fieldBuilder = server.CreateActionMethodFieldContextBuilder( nameof(Controller_NoPolicies.MethodHasRoles_Role5)); var authContext = fieldBuilder.CreateSecurityContext(); @@ -191,7 +191,7 @@ public async Task ClaimsPolicy_UserDoesntHaveClaim_Fails() builder.UserContext.AddUserClaim("testClaim5", "testClaim5Value"); var server = builder.Build(); - var fieldBuilder = server.CreateGraphTypeFieldContextBuilder( + var fieldBuilder = server.CreateActionMethodFieldContextBuilder( nameof(Controller_NoPolicies.RequireClaimPolicy_RequiresTestClaim6)); var authContext = fieldBuilder.CreateSecurityContext(); @@ -212,7 +212,7 @@ public async Task ClaimsPolicy_UserDoesHaveClaim_Success() builder.UserContext.AddUserClaim("testClaim6", "testClaim6Value"); var server = builder.Build(); - var fieldBuilder = server.CreateGraphTypeFieldContextBuilder( + var fieldBuilder = server.CreateActionMethodFieldContextBuilder( nameof(Controller_NoPolicies.RequireClaimPolicy_RequiresTestClaim6)); var authContext = fieldBuilder.CreateSecurityContext(); @@ -233,7 +233,7 @@ public async Task ClaimsPolicy_UserDoesHaveClaim_ButWrongValue_Fail() builder.UserContext.AddUserClaim("testClaim6", "differentValueThanRequired"); var server = builder.Build(); - var fieldBuilder = server.CreateGraphTypeFieldContextBuilder( + var fieldBuilder = server.CreateActionMethodFieldContextBuilder( nameof(Controller_NoPolicies.RequireClaimPolicy_RequiresTestClaim6)); var authContext = fieldBuilder.CreateSecurityContext(); @@ -252,7 +252,7 @@ public async Task NoUserContext_Fails() var server = builder.Build(); // policy name isnt declared on the controller method - var fieldBuilder = server.CreateGraphTypeFieldContextBuilder( + var fieldBuilder = server.CreateActionMethodFieldContextBuilder( nameof(Controller_NoPolicies.GeneralSecureMethod)); fieldBuilder.AddSecurityContext(null); @@ -276,7 +276,7 @@ public async Task NoAuthService_Fails() var server = builder.Build(); // policy name isnt declared on the controller method - var fieldBuilder = server.CreateGraphTypeFieldContextBuilder( + var fieldBuilder = server.CreateActionMethodFieldContextBuilder( nameof(Controller_NoPolicies.GeneralSecureMethod)); var authContext = fieldBuilder.CreateSecurityContext(); @@ -301,7 +301,7 @@ public async Task NoAuthSerivce_ButNoDefinedRules_Skipped() var server = builder.Build(); // policy name isnt declared on the controller method - var fieldBuilder = server.CreateGraphTypeFieldContextBuilder( + var fieldBuilder = server.CreateActionMethodFieldContextBuilder( nameof(Controller_NoPolicies.NoDefinedPolicies)); var authContext = fieldBuilder.CreateSecurityContext(); @@ -320,7 +320,7 @@ public async Task NoUserContext_ButNoDefinedRules_Skipped() var server = builder.Build(); // policy name isnt declared on the controller method - var fieldBuilder = server.CreateGraphTypeFieldContextBuilder( + var fieldBuilder = server.CreateActionMethodFieldContextBuilder( nameof(Controller_NoPolicies.NoDefinedPolicies)); fieldBuilder.AddSecurityContext(null); @@ -343,7 +343,7 @@ public async Task AllowAnon_WhenUserDoesntPassChecks_Success() builder.UserContext.AddUserClaim("testClaim6", "testClaim6Value"); var server = builder.Build(); - var fieldBuilder = server.CreateGraphTypeFieldContextBuilder( + var fieldBuilder = server.CreateActionMethodFieldContextBuilder( nameof(Controller_NoPolicies.RequireClaimPolicy_RequiresTestClaim7_ButAlsoAllowAnon)); var authContext = fieldBuilder.CreateSecurityContext(); @@ -373,7 +373,7 @@ public async Task MultiSecurityGroup_PassesOuter_FailsInner_Fails() var server = builder.Build(); - var fieldBuilder = server.CreateGraphTypeFieldContextBuilder( + var fieldBuilder = server.CreateActionMethodFieldContextBuilder( nameof(Controller_Policy_RequiresPolicy5.Policy_RequiresRole1)); var authContext = fieldBuilder.CreateSecurityContext(); @@ -403,7 +403,7 @@ public async Task MultiSecurityGroup_PassesOuter_PassesInner_Success() var server = builder.Build(); - var fieldBuilder = server.CreateGraphTypeFieldContextBuilder( + var fieldBuilder = server.CreateActionMethodFieldContextBuilder( nameof(Controller_Policy_RequiresPolicy5.Policy_RequiresRole1)); var authContext = fieldBuilder.CreateSecurityContext(); From 0f32f4a6b0e1f94120ab8ade9e894102fb927eef Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Mon, 17 Jul 2023 17:33:36 -0700 Subject: [PATCH 41/63] WIP, clean up of TestServer method names --- .../Controllers/ControllerExtensionTests.cs | 10 +- .../GraphQLTemplateHelper.cs | 17 +- .../TestServer.cs | 202 +++++++++--------- .../ActionResults/ActionResultTests.cs | 2 +- .../Controllers/GraphControllerTests.cs | 12 +- .../Execution/ExecutionArgumentTests.cs | 13 +- .../Execution/GeneralQueryExecutionTests.cs | 2 +- .../Resolvers/ObjectMethodResolverTests.cs | 40 ++-- .../Resolvers/ObjectPropertyResolverTests.cs | 35 ++- .../TypeSystemDirectiveCommonTests.cs | 8 +- ...nMethodModelStateValidatedLogEntryTests.cs | 4 +- .../GeneralEventLogEntryPropertyChecks.cs | 20 +- .../Middleware/MiddlewarePipelineTests.cs | 10 +- .../Security/SecurityPipelineTests.cs | 32 +-- 14 files changed, 202 insertions(+), 205 deletions(-) diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Controllers/ControllerExtensionTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Controllers/ControllerExtensionTests.cs index f3e1e8656..4b4d3a42c 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Controllers/ControllerExtensionTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Controllers/ControllerExtensionTests.cs @@ -31,7 +31,7 @@ public async Task PublishSubEvent_PublishesEventWithCorrectData() .AddGraphController() .Build(); - var fieldContextBuilder = server.CreateActionMethodFieldContextBuilder( + var fieldContextBuilder = server.CreateFieldContextBuilder( nameof(InvokableController.MutationRaisesSubEvent)); var arg1Value = "random string"; @@ -69,7 +69,7 @@ public void PublishSubEvent_NoDataThrowsException() .AddController() .Build(); - var fieldContextBuilder = server.CreateActionMethodFieldContextBuilder( + var fieldContextBuilder = server.CreateFieldContextBuilder( nameof(InvokableController.MutationRaisesSubEventNoData)); var arg1Value = "random string"; @@ -92,7 +92,7 @@ public async Task PublishSubEvent_ExistingEventCollectionisAppendedTo() .AddController() .Build(); - var fieldContextBuilder = server.CreateActionMethodFieldContextBuilder( + var fieldContextBuilder = server.CreateFieldContextBuilder( nameof(InvokableController.MutationRaisesSubEvent)); var arg1Value = "random string"; @@ -119,7 +119,7 @@ public void PublishSubEvent_UnusableListForSubscriptionEvents_ThrowsException() .AddController() .Build(); - var fieldContextBuilder = server.CreateActionMethodFieldContextBuilder( + var fieldContextBuilder = server.CreateFieldContextBuilder( nameof(InvokableController.MutationRaisesSubEvent)); var arg1Value = "random string"; @@ -147,7 +147,7 @@ public void PublishSubEvent_NoEventNameFailsTheResolver_BubblesExceptionUp() .AddController() .Build(); - var fieldContextBuilder = server.CreateActionMethodFieldContextBuilder( + var fieldContextBuilder = server.CreateFieldContextBuilder( nameof(InvokableController.MutationRaiseSubEventWithNoEventName)); var arg1Value = "random string"; diff --git a/src/unit-tests/graphql-aspnet-testframework/GraphQLTemplateHelper.cs b/src/unit-tests/graphql-aspnet-testframework/GraphQLTemplateHelper.cs index 9c8adc83e..59b798c3f 100644 --- a/src/unit-tests/graphql-aspnet-testframework/GraphQLTemplateHelper.cs +++ b/src/unit-tests/graphql-aspnet-testframework/GraphQLTemplateHelper.cs @@ -71,7 +71,20 @@ public static IGraphFieldTemplate CreateActionMethodTemplate(string /// IGraphTypeFieldTemplate. public static IGraphFieldTemplate CreateFieldTemplate(string fieldOrMethodName) { - var template = CreateGraphTypeTemplate(TypeKind.OBJECT) as IGraphTypeFieldTemplateContainer; + return CreateFieldTemplate(typeof(TType), fieldOrMethodName); + } + + /// + /// Helper method to create a field template for a controller or object method/property. This method will search both the + /// names of the fields as they would exist in an object graph as well as the declared names of methods/properties. THe first + /// found match is returned. + /// + /// Type entity that owns the field or method. + /// Name of the field as defined in the object graph or the name of the method/property. + /// IGraphTypeFieldTemplate. + public static IGraphFieldTemplate CreateFieldTemplate(Type ownerEntityType, string fieldOrMethodName) + { + var template = CreateGraphTypeTemplate(ownerEntityType, TypeKind.OBJECT) as IGraphTypeFieldTemplateContainer; // bit of a hack but it solves a lot of schema configuration differences that // can occur when setting up a test do to references occuring out of process @@ -84,7 +97,7 @@ public static IGraphFieldTemplate CreateFieldTemplate(string fieldOrMetho return kvp.Value; } - throw new ArgumentOutOfRangeException(nameof(fieldOrMethodName), $"Test Setup Error. No field,method or property named '{fieldOrMethodName}' was found on the template of type '{typeof(TType).FriendlyName()}'."); + throw new ArgumentOutOfRangeException(nameof(fieldOrMethodName), $"Test Setup Error. No field,method or property named '{fieldOrMethodName}' was found on the template of type '{ownerEntityType.FriendlyName()}'."); } /// diff --git a/src/unit-tests/graphql-aspnet-testframework/TestServer.cs b/src/unit-tests/graphql-aspnet-testframework/TestServer.cs index ba5bf8b2c..8f6a29ec6 100644 --- a/src/unit-tests/graphql-aspnet-testframework/TestServer.cs +++ b/src/unit-tests/graphql-aspnet-testframework/TestServer.cs @@ -189,102 +189,113 @@ public virtual GraphTypeCreationResult CreateGraphType(Type concreteType, TypeKi } /// - /// Creates a builder that will generate a field execution context for an action on a target controller. This + /// (DEPRECATED, DO NOT USE) Creates a mocked context for the execution of a single field of data against the given concrete type and field name. This /// context can be submitted against the field execution pipeline to generate a result. /// - /// The type of the entity that owns . - /// Name of the field as it exists on the schema. + /// The concrete type representing the graph type in the schema. + /// Name of the field, on the type, as it exists in the schema. + /// The source data to use as the input to the field. This can be changed, but must be supplied. A + /// generic will be used if not supplied. + /// The type kind to resolve the field as (only necessary for input object types). /// FieldContextBuilder. - public virtual FieldContextBuilder CreateGraphTypeFieldContextBuilder(string fieldName) + [Obsolete("Use " + nameof(CreateFieldContextBuilder) + " Instead")] + public virtual FieldContextBuilder CreateGraphTypeFieldContextBuilder(string fieldName, object sourceData, TypeKind typeKind) { - var graphType = this.Schema.KnownTypes.FindGraphType(typeof(TEntity), TypeKind.OBJECT) as IObjectGraphType; - if (graphType == null) - { - throw new InvalidOperationException($"Unknown or unregistered OBJECT graph for type {typeof(TEntity).FriendlyName()}. This method " + - $"can only create a context builder for OBJECT graph types."); - } - - var field = graphType.Fields.FindField(fieldName); - if (field == null) - { - throw new InvalidOperationException($"The graph type '{graphType.Name}' does not contain a field named '{fieldName}'. " + - $"Field names are case sensitive."); - } - - var builder = new FieldContextBuilder( - this.ServiceProvider, - _userSecurityContext, - field, - this.Schema, - field.Resolver.MetaData); - - builder.AddSourceData(new object()); - return builder; + return CreateFieldContextBuilder(fieldName, sourceData); } /// - /// Creates a builder that will generate the various field processing contexts for an action method on a target controller.. + /// (DEPRECATED, DO NOT USE) Creates a builder that will generate the various field processing contexts for an action method on a target controller.. /// /// The type of the controller that owns the /// action. /// Name of the action/field in the controller, as it exists in the schema. /// FieldContextBuilder. + [Obsolete("Use " + nameof(CreateFieldContextBuilder) + " Instead")] public virtual FieldContextBuilder CreateActionMethodFieldContextBuilder(string actionName) { - var fieldTemplate = GraphQLTemplateHelper.CreateFieldTemplate(actionName); - var fieldMaker = new GraphFieldMaker(this.Schema, new GraphArgumentMaker(this.Schema)); - var fieldResult = fieldMaker.CreateField(fieldTemplate); - - var builder = new FieldContextBuilder( - this.ServiceProvider, - _userSecurityContext, - fieldResult.Field, - this.Schema, - fieldTemplate.CreateResolverMetaData()); - - builder.AddSourceData(new object()); - return builder; + return CreateFieldContextBuilder(actionName); } /// - /// Creates a mocked context for the execution of a single field of data against the given concrete type and field name. This + /// Creates a builder that will generate a field execution context for an action on a target controller. This /// context can be submitted against the field execution pipeline to generate a result. /// - /// The concrete type representing the graph type in the schema. - /// Name of the field, on the type, as it exists in the schema. - /// The source data to use as the input to the field. This can be changed, but must be supplied. A - /// generic will be used if not supplied. - /// The type kind to resolve the field as (only necessary for input object types). + /// The type of the entity that owns . + /// Name of the field as it appears in the graph or the name of the action, method or property + /// as it appears on the . This parameter is case sensitive. + /// (optional) A source data object to supply to the builder. /// FieldContextBuilder. - public virtual FieldContextBuilder CreateGraphTypeFieldContextBuilder(string fieldName, object sourceData, TypeKind typeKind) + public virtual FieldContextBuilder CreateFieldContextBuilder(string fieldOrActionName, object sourceData = null) { - IGraphType graphType = this.Schema.KnownTypes.FindGraphType(typeof(TType)); + return this.CreateFieldContextBuilder(typeof(TEntity), fieldOrActionName, sourceData); + } - if (graphType == null) - { - throw new InvalidOperationException($"Unable to locate a registered graph type that matched the supplied source data (Type: {typeof(TType).FriendlyName()})"); - } + /// + /// Creates a builder targeting the field owned the the combination entity and field, method or property name. + /// + /// Type of the entity to inspect. + /// Name of the field as it appears in the graph or the name of the action, method or property + /// as it appears on the . This parameter is case sensitive. + /// (optional) A source data object to supply to the builder. + /// FieldContextBuilder. + public virtual FieldContextBuilder CreateFieldContextBuilder(Type entityType, string fieldOrActionName, object sourceData = null) + { + Validation.ThrowIfNull(entityType, nameof(entityType)); + + IGraphField field = null; + fieldOrActionName = Validation.ThrowIfNullWhiteSpaceOrReturn(fieldOrActionName, nameof(fieldOrActionName)); - var typedGraphType = graphType as ITypedSchemaItem; - if (typedGraphType == null) + if (Validation.IsCastable(entityType)) { - throw new InvalidOperationException($"The target graph type '{graphType.Name}' is not a strongly typed graph type and cannot be invoked via this builder."); + var fieldTemplate = GraphQLTemplateHelper.CreateFieldTemplate(entityType, fieldOrActionName); + var fieldMaker = new GraphFieldMaker(this.Schema, new GraphArgumentMaker(this.Schema)); + field = fieldMaker.CreateField(fieldTemplate)?.Field; } - - var container = graphType as IGraphFieldContainer; - if (container == null) + else { - throw new InvalidOperationException($"The target graph type '{graphType.Name}' is not a field container. No field context builder can be created."); + var graphType = this.Schema.KnownTypes.FindGraphType(entityType, TypeKind.OBJECT) as IObjectGraphType; + if (graphType == null) + { + throw new InvalidOperationException($"Unknown or unregistered OBJECT graph for type {entityType.FriendlyName()}. This method " + + $"can only create a context builder for OBJECT graph types."); + } + + var typedGraphType = graphType as ITypedSchemaItem; + if (typedGraphType == null) + { + throw new InvalidOperationException($"The target graph type '{graphType.Name}' is not a strongly typed graph type and cannot be invoked via this builder."); + } + + var container = graphType as IGraphFieldContainer; + if (container == null) + { + throw new InvalidOperationException($"The target graph type '{graphType.Name}' is not a field container. No field context builder can be created."); + } + + // find the field on the graph type + field = graphType.Fields.FindField(fieldOrActionName); + if (field == null) + { + // fallback, try and find by method/property name + foreach (var item in graphType.Fields) + { + if (item.Resolver.MetaData.InternalName == fieldOrActionName) + { + field = item; + break; + } + } + } } - var field = container.Fields.FindField(fieldName); if (field == null) { - throw new InvalidOperationException($"The target graph type '{graphType.Name}' does not contain a field named '{fieldName}'."); + throw new InvalidOperationException($"The entity '{entityType.FriendlyName()}' does not contain a field, action, method or property named '{fieldOrActionName}'. " + + $"Field names are case sensitive."); } - var metaData = this.CreateResolverMetadata(fieldName, typeKind); - + var metaData = field.Resolver.MetaData; var builder = new FieldContextBuilder( this.ServiceProvider, _userSecurityContext, @@ -293,7 +304,6 @@ public virtual FieldContextBuilder CreateGraphTypeFieldContextBuilder(str metaData); builder.AddSourceData(sourceData); - return builder; } @@ -304,34 +314,22 @@ public virtual FieldContextBuilder CreateGraphTypeFieldContextBuilder(str /// /// The type of the object to create a reference from. /// Name of the field. - /// The type kind to resolve the field as (only necessary for input object types). /// IGraphMethod. - public virtual IGraphFieldResolverMetaData CreateResolverMetadata(string fieldName, TypeKind typeKind) + public virtual IGraphFieldResolverMetaData CreateResolverMetadata(string fieldName) { - var template = GraphQLTemplateHelper.CreateGraphTypeTemplate(typeKind); - var fieldContainer = template as IGraphTypeFieldTemplateContainer; - if (fieldContainer == null) - { - throw new InvalidOperationException($"The provided type '{typeof(TObjectType).FriendlyName()}' is not " + - $"a field container, no invokable method references can be created from it."); - } - - var fieldTemplate = fieldContainer.FieldTemplates - .SingleOrDefault(x => string.Compare(x.Value.Name, fieldName, StringComparison.OrdinalIgnoreCase) == 0) - .Value; - - if (fieldTemplate == null) - { - throw new InvalidOperationException($"The provided type '{typeof(TObjectType).FriendlyName()}' does not " + $"contain a field named '{fieldName}'."); - } - - var metaData = fieldTemplate.CreateResolverMetaData(); - if (metaData == null) - { - throw new InvalidOperationException($"The field named '{fieldName}' on the provided type '{typeof(TObjectType).FriendlyName()}' " + $"does not represent an invokable {typeof(IGraphFieldResolverMetaData)}. Operation cannot proceed."); - } + return CreateResolverMetadata(typeof(TObjectType), fieldName); + } - return metaData; + /// + /// Creates a reference to the invokable method or property that acts as a resolver for the given . + /// + /// Type of the entity that owns the field. + /// Name of the field or method/property name to search for. + /// IGraphMethod. + public virtual IGraphFieldResolverMetaData CreateResolverMetadata(Type entityType, string fieldOrActionName) + { + var builder = CreateFieldContextBuilder(entityType, fieldOrActionName); + return builder?.ResolverMetaData.Object; } /// @@ -455,6 +453,18 @@ public virtual async Task ExecuteField(GraphFieldExecutionContext context, Cance await pipeline.InvokeAsync(context, cancelToken).ConfigureAwait(false); } + /// + /// Executes the field authorization pipeline against the provided context. + /// + /// The context. + /// The cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// Task. + public virtual async Task ExecuteFieldAuthorization(SchemaItemSecurityChallengeContext context, CancellationToken cancelToken = default) + { + var pipeline = this.ServiceProvider.GetService>(); + await pipeline.InvokeAsync(context, cancelToken).ConfigureAwait(false); + } + /// /// Renders the provided operation request through the engine and generates a JSON string output. /// @@ -504,18 +514,6 @@ protected virtual async Task RenderResult(IQueryExecutionResult result) } } - /// - /// Executes the field authorization pipeline against the provided context. - /// - /// The context. - /// The cancellation token that can be used by other objects or threads to receive notice of cancellation. - /// Task. - public virtual async Task ExecuteFieldAuthorization(SchemaItemSecurityChallengeContext context, CancellationToken cancelToken = default) - { - var pipeline = this.ServiceProvider.GetService>(); - await pipeline.InvokeAsync(context, cancelToken).ConfigureAwait(false); - } - /// /// Gets a reference to the schema this test server is hosting. /// diff --git a/src/unit-tests/graphql-aspnet-tests/Controllers/ActionResults/ActionResultTests.cs b/src/unit-tests/graphql-aspnet-tests/Controllers/ActionResults/ActionResultTests.cs index 87795e9f8..478d9fb39 100644 --- a/src/unit-tests/graphql-aspnet-tests/Controllers/ActionResults/ActionResultTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Controllers/ActionResults/ActionResultTests.cs @@ -34,7 +34,7 @@ private FieldResolutionContext CreateResolutionContext() .AddType() .Build(); - var builder = server.CreateActionMethodFieldContextBuilder( + var builder = server.CreateFieldContextBuilder( nameof(ActionableController.DoStuff)); return builder.CreateResolutionContext(); } diff --git a/src/unit-tests/graphql-aspnet-tests/Controllers/GraphControllerTests.cs b/src/unit-tests/graphql-aspnet-tests/Controllers/GraphControllerTests.cs index 10263c66f..23021cc2d 100644 --- a/src/unit-tests/graphql-aspnet-tests/Controllers/GraphControllerTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Controllers/GraphControllerTests.cs @@ -29,7 +29,7 @@ public async Task MethodInvocation_EnsureInternalPropertiesAreSet() .AddGraphController() .Build(); - var fieldContextBuilder = server.CreateActionMethodFieldContextBuilder( + var fieldContextBuilder = server.CreateFieldContextBuilder( nameof(InvokableController.AsyncActionMethod)); fieldContextBuilder.AddInputArgument("arg1", "random string"); @@ -58,7 +58,7 @@ public async Task MethodInvocation_SyncMethodReturnsObjectNotTask() .AddGraphController() .Build(); - var fieldContextBuilder = tester.CreateActionMethodFieldContextBuilder( + var fieldContextBuilder = tester.CreateFieldContextBuilder( nameof(InvokableController.SyncronousActionMethod)); fieldContextBuilder.AddInputArgument("arg1", "random string"); @@ -76,7 +76,7 @@ public async Task MethodInvocation_UnawaitableAsyncMethodFlag_ResultsInInternalE var tester = new TestServerBuilder(TestOptions.UseCodeDeclaredNames) .AddGraphController() .Build(); - var fieldContextBuilder = tester.CreateActionMethodFieldContextBuilder( + var fieldContextBuilder = tester.CreateFieldContextBuilder( nameof(InvokableController.SyncronousActionMethod)); fieldContextBuilder.AddInputArgument("arg1", "random string"); @@ -97,7 +97,7 @@ public async Task MethodInvocation_MissingMethodInfo_ReturnsInternalServerError( var tester = new TestServerBuilder(TestOptions.UseCodeDeclaredNames) .AddGraphController() .Build(); - var fieldContextBuilder = tester.CreateActionMethodFieldContextBuilder( + var fieldContextBuilder = tester.CreateFieldContextBuilder( nameof(InvokableController.SyncronousActionMethod)); fieldContextBuilder.AddInputArgument("arg1", "random string"); fieldContextBuilder.ResolverMetaData.Setup(x => x.Method).Returns(null); @@ -117,7 +117,7 @@ public void MethodInvocation_UserCodeExceptionIsAllowedToThrow() var tester = new TestServerBuilder(TestOptions.UseCodeDeclaredNames) .AddGraphController() .Build(); - var fieldContextBuilder = tester.CreateActionMethodFieldContextBuilder( + var fieldContextBuilder = tester.CreateFieldContextBuilder( nameof(InvokableController.AsyncActionMethodToCauseException)); fieldContextBuilder.AddInputArgument("arg1", "random string"); @@ -134,7 +134,7 @@ public async Task ErrorResult() .AddType() .Build(); - var fieldContextBuilder = server.CreateActionMethodFieldContextBuilder( + var fieldContextBuilder = server.CreateFieldContextBuilder( nameof(InvokableController.ErrorResult)); var controller = new InvokableController(); diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/ExecutionArgumentTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/ExecutionArgumentTests.cs index 64223ce59..181299535 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/ExecutionArgumentTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/ExecutionArgumentTests.cs @@ -83,7 +83,7 @@ public void PrepareArguments_WhenArgumentShouldComeFromDI_AndExistsInDI_IsPrepar var testServer = builder.Build(); var contextBuilder = testServer - .CreateGraphTypeFieldContextBuilder(nameof(ObjectWithFields.FieldWithInjectedArgument)); + .CreateFieldContextBuilder(nameof(ObjectWithFields.FieldWithInjectedArgument)); var context = contextBuilder.CreateResolutionContext(); @@ -113,7 +113,7 @@ public void PrepareArguments_WhenArgumentShouldComeFromDI_AndDoesNotExistInDI_An var testServer = builder.Build(); var contextBuilder = testServer - .CreateGraphTypeFieldContextBuilder(nameof(ObjectWithFields.FieldWithInjectedArgument)); + .CreateFieldContextBuilder(nameof(ObjectWithFields.FieldWithInjectedArgument)); var context = contextBuilder.CreateResolutionContext(); @@ -143,7 +143,7 @@ public void PrepareArguments_WhenArgumentShouldComeFromDI_AndDoesNotExistInDI_An var testServer = builder.Build(); var contextBuilder = testServer - .CreateGraphTypeFieldContextBuilder(nameof(ObjectWithFields.FieldWithInjectedArgumentWithDefaultValue)); + .CreateFieldContextBuilder(nameof(ObjectWithFields.FieldWithInjectedArgumentWithDefaultValue)); // mimic a situation where no values are parsed from a query (no execution args) // and nothing is available from DI @@ -176,7 +176,7 @@ public void PrepareArguments_WhenArgumentShouldComeFromSchema_HasNoSuppliedValue template.ValidateOrThrow(); var fieldBuilder = testServer - .CreateGraphTypeFieldContextBuilder(nameof(ObjectWithFields.FieldWithNullableSchemaArgument)); + .CreateFieldContextBuilder(nameof(ObjectWithFields.FieldWithNullableSchemaArgument)); // mimic a situation where no values are parsed from a query (no execution args) // and nothing is available from DI @@ -205,7 +205,8 @@ public void PrepareArguments_WhenArgumentShouldComeFromSchema_HasNoSuppliedValue var testServer = builder.Build(); var fieldBuilder = testServer - .CreateGraphTypeFieldContextBuilder(nameof(ObjectWithFields.FieldWithNonNullableSchemaArgumentThatHasDefaultValue)); + .CreateFieldContextBuilder( + nameof(ObjectWithFields.FieldWithNonNullableSchemaArgumentThatHasDefaultValue)); // mimic a situation where no values are parsed from a query (no execution args) // and nothing is available from DI @@ -234,7 +235,7 @@ public void PrepareArguments_WhenArgumentShouldComeFromQuery_AndIsNotSupplied_An var testServer = builder.Build(); var fieldBuilder = testServer - .CreateGraphTypeFieldContextBuilder(nameof(ObjectWithFields.FieldWithNotNullableQueryArgument)); + .CreateFieldContextBuilder(nameof(ObjectWithFields.FieldWithNotNullableQueryArgument)); // mimic a situation where no values are parsed from a query (no execution args) // but the argument expected there to be diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionTests.cs index 627210f02..a8aa916d4 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/GeneralQueryExecutionTests.cs @@ -27,7 +27,7 @@ public async Task SingleFieldResolution_ViaPipeline_YieldsCorrectResult() .AddType() .Build(); - var builder = server.CreateActionMethodFieldContextBuilder( + var builder = server.CreateFieldContextBuilder( nameof(SimpleExecutionController.SimpleQueryMethod)); builder.AddInputArgument("arg1", "my value"); builder.AddInputArgument("arg2", 15L); diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ObjectMethodResolverTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ObjectMethodResolverTests.cs index 39b4b4a12..b16f38b23 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ObjectMethodResolverTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ObjectMethodResolverTests.cs @@ -28,10 +28,9 @@ public async Task NullSourceData_FailsRequest() .AddType() .Build(); - var builder = server.CreateGraphTypeFieldContextBuilder( + var builder = server.CreateFieldContextBuilder( nameof(ResolverObject.MethodRetrieveData), - null, - TypeKind.OBJECT); + null); var resolver = new ObjectMethodGraphFieldResolver(builder.ResolverMetaData.Object); @@ -50,10 +49,9 @@ public async Task SourceDataIsNotOfTheTemplate_FailsRequest() .AddType() .Build(); - var builder = server.CreateGraphTypeFieldContextBuilder( + var builder = server.CreateFieldContextBuilder( nameof(ResolverObject.MethodRetrieveData), - new object(), - TypeKind.OBJECT); + new object()); // source data is not of the type the resolver is for builder.AddSourceData(new TwoPropertyObject()); @@ -73,10 +71,9 @@ public async Task MethodThrowsException_FailsRequest() .AddType() .Build(); - var builder = server.CreateGraphTypeFieldContextBuilder( + var builder = server.CreateFieldContextBuilder( nameof(ResolverObject.MethodThrowException), - new object(), - TypeKind.OBJECT); + new object()); // source data is not of the type the resolver is for builder.AddSourceData(new ResolverObject()); @@ -98,10 +95,9 @@ public async Task KnownExecutionError_FailsRequest() .AddType() .Build(); - var builder = server.CreateGraphTypeFieldContextBuilder( + var builder = server.CreateFieldContextBuilder( nameof(ResolverObject.MethodWithArgument), - new object(), - TypeKind.OBJECT); + new object()); // the method declares one input argument which is not provided on this request // resulting in a GraphExecutionException which @@ -126,10 +122,9 @@ public async Task AsyncMethod_NullSourceData_FailsRequest() .AddType() .Build(); - var builder = server.CreateGraphTypeFieldContextBuilder( + var builder = server.CreateFieldContextBuilder( nameof(ResolverObject.MethodRetrieveDataAsync), - null, - TypeKind.OBJECT); + null); var resolver = new ObjectMethodGraphFieldResolver(builder.ResolverMetaData.Object); @@ -148,10 +143,9 @@ public async Task AsyncMethod_SourceDataIsNotOfTheTemplate_FailsRequest() .AddType() .Build(); - var builder = server.CreateGraphTypeFieldContextBuilder( + var builder = server.CreateFieldContextBuilder( nameof(ResolverObject.MethodRetrieveDataAsync), - new object(), - TypeKind.OBJECT); + new object()); // source data is not of the type the resolver is for builder.AddSourceData(new TwoPropertyObject()); @@ -171,10 +165,9 @@ public async Task AsyncMethod_MethodThrowsException_FailsRequest() .AddType() .Build(); - var builder = server.CreateGraphTypeFieldContextBuilder( + var builder = server.CreateFieldContextBuilder( nameof(ResolverObject.MethodThrowExceptionAsync), - new object(), - TypeKind.OBJECT); + new object()); // source data is not of the type the resolver is for builder.AddSourceData(new ResolverObject()); @@ -196,10 +189,9 @@ public async Task AsyncMethod_KnownExecutionError_FailsRequest() .AddType() .Build(); - var builder = server.CreateGraphTypeFieldContextBuilder( + var builder = server.CreateFieldContextBuilder( nameof(ResolverObject.MethodWithArgumentAsync), - new object(), - TypeKind.OBJECT); + new object()); // the method declares one input argument which is not provided on this request // resulting in a GraphExecutionException which diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ObjectPropertyResolverTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ObjectPropertyResolverTests.cs index 0361965cb..0a003139b 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ObjectPropertyResolverTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/Resolvers/ObjectPropertyResolverTests.cs @@ -31,10 +31,9 @@ public async Task NullSourceData_FailsRequest() .AddType() .Build(); - var fieldContextBuilder = server.CreateGraphTypeFieldContextBuilder( + var fieldContextBuilder = server.CreateFieldContextBuilder( nameof(ResolverObject.Address1), - null, - TypeKind.OBJECT); + null); fieldContextBuilder.AddSourceData(null); var resolutionContext = fieldContextBuilder.CreateResolutionContext(); @@ -55,10 +54,9 @@ public async Task TemplateIsInterface_SourceDataDoesImplementInterface_RendersCo .AddType() .Build(); - var fieldContextBuilder = server.CreateGraphTypeFieldContextBuilder( + var fieldContextBuilder = server.CreateFieldContextBuilder( nameof(ResolverObject.Address1), - null, - TypeKind.OBJECT); + null); var item = new ResolverObject(); item.Address1 = "15th Street"; @@ -86,10 +84,9 @@ public async Task TemplateIsInterface_SourceDataDoesNotImplementInterface_FailsR .AddType() .Build(); - var fieldContextBuilder = server.CreateGraphTypeFieldContextBuilder( + var fieldContextBuilder = server.CreateFieldContextBuilder( nameof(ResolverObject.Address1), - null, - TypeKind.OBJECT); + null); fieldContextBuilder.AddSourceData(new TwoPropertyObject()); @@ -117,10 +114,9 @@ public async Task SourceDataIsNotOfTheTemplate_FailsRequest() .Build(); // resolving structA, but supplying structB as source - var fieldContextBuilder = server.CreateGraphTypeFieldContextBuilder( + var fieldContextBuilder = server.CreateFieldContextBuilder( nameof(ResolverStructA.Prop1), - new ResolverStructB("struct"), - TypeKind.OBJECT); + new ResolverStructB("struct")); // source data is not of the type the resolver is for var resolver = new ObjectPropertyGraphFieldResolver(fieldContextBuilder.ResolverMetaData.Object); @@ -139,10 +135,9 @@ public async Task PropertyThrowsException_FailsRequest() .AddType() .Build(); - var fieldContextBuilder = server.CreateGraphTypeFieldContextBuilder( + var fieldContextBuilder = server.CreateFieldContextBuilder( nameof(ResolverObject.PropertyThrowException), - new ResolverObject(), - TypeKind.OBJECT); + new ResolverObject()); // source data is not of the type the resolver is for fieldContextBuilder.AddSourceData(new ResolverObject()); @@ -164,10 +159,9 @@ public async Task AsyncProperty_ValidSourceData_ReturnsData() .AddType() .Build(); - var fieldContextBuilder = server.CreateGraphTypeFieldContextBuilder( + var fieldContextBuilder = server.CreateFieldContextBuilder( nameof(ResolverObject.Address1Async), - new ResolverObject(), - TypeKind.OBJECT); + new ResolverObject()); var resolutionContext = fieldContextBuilder.CreateResolutionContext(); @@ -186,10 +180,9 @@ public async Task AsyncProperty_ThrowsException_FailsRequest() .AddType() .Build(); - var fieldContextBuilder = server.CreateGraphTypeFieldContextBuilder( + var fieldContextBuilder = server.CreateFieldContextBuilder( nameof(ResolverObject.AsyncPropException), - new ResolverObject(), - TypeKind.OBJECT); + new ResolverObject()); // source data is not of the type the resolver is for fieldContextBuilder.AddSourceData(new ResolverObject()); diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TypeSystemDirectiveCommonTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TypeSystemDirectiveCommonTests.cs index 94fa2f39f..f499c7937 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TypeSystemDirectiveCommonTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TypeSystemDirectiveCommonTests.cs @@ -30,7 +30,7 @@ public async Task ExtendAResolver_DirectiveDeclaredByType() LastName = "Smith", }; - var contextBuilder = server.CreateGraphTypeFieldContextBuilder( + var contextBuilder = server.CreateFieldContextBuilder( nameof(TestPersonWithResolverExtensionDirectiveByType.Name)); contextBuilder.AddSourceData(person); @@ -56,7 +56,7 @@ public async Task ExtendAResolver_DirectiveDeclaredByName() LastName = "Smith", }; - var contextBuilder = server.CreateGraphTypeFieldContextBuilder( + var contextBuilder = server.CreateFieldContextBuilder( nameof(TestPersonWithResolverExtensionDirectiveByName.Name)); contextBuilder.AddSourceData(person); @@ -84,7 +84,7 @@ public async Task DirectiveDeclaredByName_AndDirectiveHasCustomName_IsFoundAndEx LastName = "Smith", }; - var contextBuilder = server.CreateGraphTypeFieldContextBuilder( + var contextBuilder = server.CreateFieldContextBuilder( nameof(TestPersonWithResolverExtensionDirectiveByName.Name)); contextBuilder.AddSourceData(person); @@ -110,7 +110,7 @@ public async Task ExtendAnObjectType_AddField_DirectiveDeclaredByType() Property2 = "prop 2", }; - var contextBuilder = server.CreateGraphTypeFieldContextBuilder("property3") + var contextBuilder = server.CreateFieldContextBuilder("property3") .AddSourceData(obj); var context = contextBuilder.CreateExecutionContext(); diff --git a/src/unit-tests/graphql-aspnet-tests/Logging/ActionMethodModelStateValidatedLogEntryTests.cs b/src/unit-tests/graphql-aspnet-tests/Logging/ActionMethodModelStateValidatedLogEntryTests.cs index 7df8d572c..91ab9a68b 100644 --- a/src/unit-tests/graphql-aspnet-tests/Logging/ActionMethodModelStateValidatedLogEntryTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Logging/ActionMethodModelStateValidatedLogEntryTests.cs @@ -110,7 +110,7 @@ public void InvalidModelItem_BuildsLogEntry() .AddType() .Build(); - var builder = server.CreateActionMethodFieldContextBuilder( + var builder = server.CreateFieldContextBuilder( nameof(LogTestController.ValidatableInputObject)); var context = builder.CreateExecutionContext(); @@ -140,7 +140,7 @@ public void ValidModelItem_BuildsLogEntry() .AddType() .Build(); - var builder = server.CreateActionMethodFieldContextBuilder( + var builder = server.CreateFieldContextBuilder( nameof(LogTestController.ValidatableInputObject)); var context = builder.CreateExecutionContext(); diff --git a/src/unit-tests/graphql-aspnet-tests/Logging/GeneralEventLogEntryPropertyChecks.cs b/src/unit-tests/graphql-aspnet-tests/Logging/GeneralEventLogEntryPropertyChecks.cs index 875f93b8c..32f173b5a 100644 --- a/src/unit-tests/graphql-aspnet-tests/Logging/GeneralEventLogEntryPropertyChecks.cs +++ b/src/unit-tests/graphql-aspnet-tests/Logging/GeneralEventLogEntryPropertyChecks.cs @@ -241,7 +241,7 @@ public void FieldResolutionStartedLogEntry() .AddType() .Build(); - var package = server.CreateActionMethodFieldContextBuilder( + var package = server.CreateFieldContextBuilder( nameof(LogTestController.ExecuteField2)); var resolutionContext = package.CreateResolutionContext(); @@ -261,7 +261,7 @@ public void FieldResolutionCompletedLogEntry() .AddType() .Build(); - var package = server.CreateActionMethodFieldContextBuilder( + var package = server.CreateFieldContextBuilder( nameof(LogTestController.ExecuteField2)); var resolutionContext = package.CreateResolutionContext(); var fieldRequest = package.FieldRequest; @@ -287,7 +287,7 @@ public void FieldAuthorizationStartedLogEntry() builder.UserContext.Authenticate("bobSmith"); var server = builder.Build(); - var package = server.CreateActionMethodFieldContextBuilder( + var package = server.CreateFieldContextBuilder( nameof(LogTestController.ExecuteField2)); var fieldRequest = package.FieldRequest; @@ -312,7 +312,7 @@ public void FieldAuthorizationCompletedLogEntry() builder.UserContext.Authenticate("bobSmith"); var server = builder.Build(); - var package = server.CreateActionMethodFieldContextBuilder( + var package = server.CreateFieldContextBuilder( nameof(LogTestController.ExecuteField2)); var fieldRequest = package.FieldRequest; var authContext = package.CreateSecurityContext(); @@ -339,7 +339,7 @@ public void FieldAuthenticationStartedLogEntry() builder.UserContext.Authenticate("bobSmith"); var server = builder.Build(); - var package = server.CreateActionMethodFieldContextBuilder( + var package = server.CreateFieldContextBuilder( nameof(LogTestController.ExecuteField2)); var fieldRequest = package.FieldRequest; @@ -372,7 +372,7 @@ public void FieldAuthenticationCompletedLogEntry() authResult.Setup(x => x.AuthenticationScheme).Returns("testScheme"); authResult.Setup(x => x.Suceeded).Returns(true); - var package = server.CreateActionMethodFieldContextBuilder( + var package = server.CreateFieldContextBuilder( nameof(LogTestController.ExecuteField2)); var fieldRequest = package.FieldRequest; @@ -400,7 +400,7 @@ public void ActionMethodInvocationStartedLogEntry() .AddType() .Build(); var graphMethod = GraphQLTemplateHelper.CreateActionMethodTemplate(nameof(LogTestController.ExecuteField2)).CreateResolverMetaData(); - var package = server.CreateActionMethodFieldContextBuilder( + var package = server.CreateFieldContextBuilder( nameof(LogTestController.ExecuteField2)); var fieldRequest = package.FieldRequest; @@ -422,7 +422,7 @@ public void ActionMethodInvocationCompletedLogEntry() .Build(); var metaData = GraphQLTemplateHelper.CreateActionMethodTemplate(nameof(LogTestController.ExecuteField2)).CreateResolverMetaData(); - var package = server.CreateActionMethodFieldContextBuilder( + var package = server.CreateFieldContextBuilder( nameof(LogTestController.ExecuteField2)); var resolutionContext = package.CreateResolutionContext(); var fieldRequest = package.FieldRequest; @@ -447,7 +447,7 @@ public void ActionMethodInvocationExceptionLogEntry() .Build(); var metaData = GraphQLTemplateHelper.CreateActionMethodTemplate(nameof(LogTestController.ExecuteField2)).CreateResolverMetaData(); - var package = server.CreateActionMethodFieldContextBuilder( + var package = server.CreateFieldContextBuilder( nameof(LogTestController.ExecuteField2)); var fieldRequest = package.FieldRequest; @@ -477,7 +477,7 @@ public void ActionMethodUnhandledExceptionLogEntry() .AddType() .Build(); - var package = server.CreateActionMethodFieldContextBuilder( + var package = server.CreateFieldContextBuilder( nameof(LogTestController.ExecuteField2)); var template = GraphQLTemplateHelper.CreateActionMethodTemplate(nameof(LogTestController.ExecuteField2)); var metaData = template.CreateResolverMetaData(); diff --git a/src/unit-tests/graphql-aspnet-tests/Middleware/MiddlewarePipelineTests.cs b/src/unit-tests/graphql-aspnet-tests/Middleware/MiddlewarePipelineTests.cs index 798be0150..48bc56fa8 100644 --- a/src/unit-tests/graphql-aspnet-tests/Middleware/MiddlewarePipelineTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Middleware/MiddlewarePipelineTests.cs @@ -60,7 +60,7 @@ public async Task SingularPipelineInvokesComponentsInOrder() // fake a graph ql request context var server = serverBuilder.Build(); - var fieldBuilder = server.CreateActionMethodFieldContextBuilder( + var fieldBuilder = server.CreateFieldContextBuilder( nameof(MiddlewareController.FieldOfData)); var executionContext = fieldBuilder.CreateExecutionContext(); @@ -111,7 +111,7 @@ public void NoFoundMiddlewareComponent_ThrowsException() // fake a graph ql request context var server = serverBuilder.Build(); - var fieldBuilder = server.CreateActionMethodFieldContextBuilder( + var fieldBuilder = server.CreateFieldContextBuilder( nameof(MiddlewareController.FieldOfData)); var executionContext = fieldBuilder.CreateExecutionContext(); @@ -143,7 +143,7 @@ public async Task MiddlewareComponentThrowsExceptions_MiddlewareInvokerShouldUnw // fake a graph ql request context var server = serverBuilder.Build(); - var builder = server.CreateActionMethodFieldContextBuilder( + var builder = server.CreateFieldContextBuilder( nameof(MiddlewareController.FieldOfData)); var context = builder.CreateExecutionContext(); @@ -188,7 +188,7 @@ public async Task SingletonMiddlewareComponent_IsNeverInstantiatedMoreThanOnce() // fake a graph ql request context var server = serverBuilder.Build(); - var builder = server.CreateActionMethodFieldContextBuilder( + var builder = server.CreateFieldContextBuilder( nameof(MiddlewareController.FieldOfData)); // execute the pipeline multiple times @@ -238,7 +238,7 @@ public async Task SingletonMiddlewareWithUserProvidedInstance_NeverAttemptsToCre Assert.IsNotNull(pipeline); var server = serverBuilder.Build(); - var builder = server.CreateActionMethodFieldContextBuilder( + var builder = server.CreateFieldContextBuilder( nameof(MiddlewareController.FieldOfData)); // make an empty service collection (preventing creation if the middleware isnt found) diff --git a/src/unit-tests/graphql-aspnet-tests/Security/SecurityPipelineTests.cs b/src/unit-tests/graphql-aspnet-tests/Security/SecurityPipelineTests.cs index 0ce7cc461..044c47da4 100644 --- a/src/unit-tests/graphql-aspnet-tests/Security/SecurityPipelineTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Security/SecurityPipelineTests.cs @@ -58,7 +58,7 @@ public async Task RolePolicy_UserNotInRole_Fails() builder.UserContext.AddUserRole("role4"); var server = builder.Build(); - var fieldBuilder = server.CreateActionMethodFieldContextBuilder( + var fieldBuilder = server.CreateFieldContextBuilder( nameof(Controller_NoPolicies.RequireRolePolicy_RequiresRole1)); var authContext = fieldBuilder.CreateSecurityContext(); @@ -79,7 +79,7 @@ public async Task RolePolicy_UserInRole_Success() builder.UserContext.AddUserRole("role1"); var server = builder.Build(); - var fieldBuilder = server.CreateActionMethodFieldContextBuilder( + var fieldBuilder = server.CreateFieldContextBuilder( nameof(Controller_NoPolicies.RequireRolePolicy_RequiresRole1)); var authContext = fieldBuilder.CreateSecurityContext(); @@ -103,7 +103,7 @@ public async Task MultiPolicyCheck_UserPassesAll_Success() var server = builder.Build(); - var fieldBuilder = server.CreateActionMethodFieldContextBuilder( + var fieldBuilder = server.CreateFieldContextBuilder( nameof(Controller_NoPolicies.MultiPolicyMethod_RequireRole6_RequireClaim7)); var authContext = fieldBuilder.CreateSecurityContext(); @@ -130,7 +130,7 @@ public async Task MultiPolicyCheck_UserPassesOnly1_Fail() var server = builder.Build(); - var fieldBuilder = server.CreateActionMethodFieldContextBuilder( + var fieldBuilder = server.CreateFieldContextBuilder( nameof(Controller_NoPolicies.MultiPolicyMethod_RequireRole6_RequireClaim7)); var authContext = fieldBuilder.CreateSecurityContext(); @@ -150,7 +150,7 @@ public async Task DirectRoleCheck_UserDoesNotHaveRole_Fails() var server = builder.Build(); // policy name isnt declared on the controller method - var fieldBuilder = server.CreateActionMethodFieldContextBuilder( + var fieldBuilder = server.CreateFieldContextBuilder( nameof(Controller_NoPolicies.MethodHasRoles_Role5)); var authContext = fieldBuilder.CreateSecurityContext(); @@ -170,7 +170,7 @@ public async Task DirectRoleCheck_UserHasRole_Succeeds() var server = builder.Build(); // policy name isnt declared on the controller method - var fieldBuilder = server.CreateActionMethodFieldContextBuilder( + var fieldBuilder = server.CreateFieldContextBuilder( nameof(Controller_NoPolicies.MethodHasRoles_Role5)); var authContext = fieldBuilder.CreateSecurityContext(); @@ -191,7 +191,7 @@ public async Task ClaimsPolicy_UserDoesntHaveClaim_Fails() builder.UserContext.AddUserClaim("testClaim5", "testClaim5Value"); var server = builder.Build(); - var fieldBuilder = server.CreateActionMethodFieldContextBuilder( + var fieldBuilder = server.CreateFieldContextBuilder( nameof(Controller_NoPolicies.RequireClaimPolicy_RequiresTestClaim6)); var authContext = fieldBuilder.CreateSecurityContext(); @@ -212,7 +212,7 @@ public async Task ClaimsPolicy_UserDoesHaveClaim_Success() builder.UserContext.AddUserClaim("testClaim6", "testClaim6Value"); var server = builder.Build(); - var fieldBuilder = server.CreateActionMethodFieldContextBuilder( + var fieldBuilder = server.CreateFieldContextBuilder( nameof(Controller_NoPolicies.RequireClaimPolicy_RequiresTestClaim6)); var authContext = fieldBuilder.CreateSecurityContext(); @@ -233,7 +233,7 @@ public async Task ClaimsPolicy_UserDoesHaveClaim_ButWrongValue_Fail() builder.UserContext.AddUserClaim("testClaim6", "differentValueThanRequired"); var server = builder.Build(); - var fieldBuilder = server.CreateActionMethodFieldContextBuilder( + var fieldBuilder = server.CreateFieldContextBuilder( nameof(Controller_NoPolicies.RequireClaimPolicy_RequiresTestClaim6)); var authContext = fieldBuilder.CreateSecurityContext(); @@ -252,7 +252,7 @@ public async Task NoUserContext_Fails() var server = builder.Build(); // policy name isnt declared on the controller method - var fieldBuilder = server.CreateActionMethodFieldContextBuilder( + var fieldBuilder = server.CreateFieldContextBuilder( nameof(Controller_NoPolicies.GeneralSecureMethod)); fieldBuilder.AddSecurityContext(null); @@ -276,7 +276,7 @@ public async Task NoAuthService_Fails() var server = builder.Build(); // policy name isnt declared on the controller method - var fieldBuilder = server.CreateActionMethodFieldContextBuilder( + var fieldBuilder = server.CreateFieldContextBuilder( nameof(Controller_NoPolicies.GeneralSecureMethod)); var authContext = fieldBuilder.CreateSecurityContext(); @@ -301,7 +301,7 @@ public async Task NoAuthSerivce_ButNoDefinedRules_Skipped() var server = builder.Build(); // policy name isnt declared on the controller method - var fieldBuilder = server.CreateActionMethodFieldContextBuilder( + var fieldBuilder = server.CreateFieldContextBuilder( nameof(Controller_NoPolicies.NoDefinedPolicies)); var authContext = fieldBuilder.CreateSecurityContext(); @@ -320,7 +320,7 @@ public async Task NoUserContext_ButNoDefinedRules_Skipped() var server = builder.Build(); // policy name isnt declared on the controller method - var fieldBuilder = server.CreateActionMethodFieldContextBuilder( + var fieldBuilder = server.CreateFieldContextBuilder( nameof(Controller_NoPolicies.NoDefinedPolicies)); fieldBuilder.AddSecurityContext(null); @@ -343,7 +343,7 @@ public async Task AllowAnon_WhenUserDoesntPassChecks_Success() builder.UserContext.AddUserClaim("testClaim6", "testClaim6Value"); var server = builder.Build(); - var fieldBuilder = server.CreateActionMethodFieldContextBuilder( + var fieldBuilder = server.CreateFieldContextBuilder( nameof(Controller_NoPolicies.RequireClaimPolicy_RequiresTestClaim7_ButAlsoAllowAnon)); var authContext = fieldBuilder.CreateSecurityContext(); @@ -373,7 +373,7 @@ public async Task MultiSecurityGroup_PassesOuter_FailsInner_Fails() var server = builder.Build(); - var fieldBuilder = server.CreateActionMethodFieldContextBuilder( + var fieldBuilder = server.CreateFieldContextBuilder( nameof(Controller_Policy_RequiresPolicy5.Policy_RequiresRole1)); var authContext = fieldBuilder.CreateSecurityContext(); @@ -403,7 +403,7 @@ public async Task MultiSecurityGroup_PassesOuter_PassesInner_Success() var server = builder.Build(); - var fieldBuilder = server.CreateActionMethodFieldContextBuilder( + var fieldBuilder = server.CreateFieldContextBuilder( nameof(Controller_Policy_RequiresPolicy5.Policy_RequiresRole1)); var authContext = fieldBuilder.CreateSecurityContext(); From 173c6e4186c4144afbe1a2c44b5e8766257a5131 Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Tue, 18 Jul 2023 18:52:11 -0700 Subject: [PATCH 42/63] WIP, created DirectiveContextBuilder in test server --- ...CompleteBatchOperationGraphActionResult.cs | 1 - .../SchemaItemResolutionContext{TRequest}.cs | 9 - .../DirectiveContextBuilder.cs | 261 ++++++++++++++++++ .../FieldContextBuilder.cs | 53 ++-- .../TestServer.cs | 190 ++++++++----- .../DirectiveValidationRuleCheckTests.cs | 36 ++- .../GeneralEventLogEntryPropertyChecks.cs | 18 +- .../DirectivePipelineMiddlewareTests.cs | 10 +- 8 files changed, 448 insertions(+), 130 deletions(-) create mode 100644 src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/DirectiveContextBuilder.cs diff --git a/src/graphql-aspnet/Controllers/ActionResults/CompleteBatchOperationGraphActionResult.cs b/src/graphql-aspnet/Controllers/ActionResults/CompleteBatchOperationGraphActionResult.cs index e81097d72..98d59d051 100644 --- a/src/graphql-aspnet/Controllers/ActionResults/CompleteBatchOperationGraphActionResult.cs +++ b/src/graphql-aspnet/Controllers/ActionResults/CompleteBatchOperationGraphActionResult.cs @@ -41,7 +41,6 @@ public CompleteBatchOperationGraphActionResult(BatchBuilder public Task CompleteAsync(SchemaItemResolutionContext context) { - if (!(context is FieldResolutionContext frc)) { context.Messages.Critical( diff --git a/src/graphql-aspnet/Execution/Contexts/SchemaItemResolutionContext{TRequest}.cs b/src/graphql-aspnet/Execution/Contexts/SchemaItemResolutionContext{TRequest}.cs index cbdd045cb..830c2d1d0 100644 --- a/src/graphql-aspnet/Execution/Contexts/SchemaItemResolutionContext{TRequest}.cs +++ b/src/graphql-aspnet/Execution/Contexts/SchemaItemResolutionContext{TRequest}.cs @@ -7,15 +7,6 @@ // License: MIT // ************************************************************* -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - namespace GraphQL.AspNet.Execution.Contexts { using System; diff --git a/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/DirectiveContextBuilder.cs b/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/DirectiveContextBuilder.cs new file mode 100644 index 000000000..4a94d92f5 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/DirectiveContextBuilder.cs @@ -0,0 +1,261 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Framework.PipelineContextBuilders +{ + using System; + using System.Threading; + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Directives; + using GraphQL.AspNet.Execution; + using GraphQL.AspNet.Execution.Contexts; + using GraphQL.AspNet.Execution.QueryPlans.InputArguments; + using GraphQL.AspNet.Execution.Source; + using GraphQL.AspNet.Execution.Variables; + using GraphQL.AspNet.Interfaces.Execution; + using GraphQL.AspNet.Interfaces.Execution.QueryPlans.DocumentParts; + using GraphQL.AspNet.Interfaces.Execution.QueryPlans.InputArguments; + using GraphQL.AspNet.Interfaces.Logging; + using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Interfaces.Security; + using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Security; + using Moq; + + /// + /// A builder used to create inlined mocked replacements + /// of various data to setup a test scenario targeting a single directive resolution. + /// + public class DirectiveContextBuilder + { + private readonly IDirective _directive; + private readonly ISchema _schema; + private readonly Mock _mockRequest; + private readonly Mock _mockInvocationContext; + private readonly IGraphMessageCollection _messageCollection; + private readonly IInputArgumentCollection _arguments; + private readonly Mock _mockResolverMetadata; + private DirectiveLocation _location; + private IUserSecurityContext _securityContext; + private object _directiveTarget; + + /// + /// Initializes a new instance of the class. + /// + /// The service provider. + /// The user security context. + /// The schema where the directive is declared. + /// The directive to invoke. + /// The location where this directive is targeting. This information is presented to the directive + /// when it is invoked. + /// The phase of execution where the directive is being processed. + /// The metadata describing the method/functon to be invoked by a resolver. + public DirectiveContextBuilder( + IServiceProvider serviceProvider, + IUserSecurityContext userSecurityContext, + ISchema schema, + IDirective directive, + DirectiveLocation directiveLocation, + DirectiveInvocationPhase phase, + IGraphFieldResolverMetaData resolverMetadata) + { + _schema = Validation.ThrowIfNullOrReturn(schema, nameof(schema)); + _securityContext = Validation.ThrowIfNullOrReturn(userSecurityContext, nameof(userSecurityContext)); + _messageCollection = new GraphMessageCollection(); + _arguments = InputArgumentCollectionFactory.Create(); + _location = directiveLocation; + _directive = directive; + + this.ServiceProvider = Validation.ThrowIfNullOrReturn(serviceProvider, nameof(serviceProvider)); + + _mockInvocationContext = new Mock(); + _mockInvocationContext.Setup(x => x.Directive).Returns(_directive); + _mockInvocationContext.Setup(x => x.Arguments).Returns(_arguments); + _mockInvocationContext.Setup(x => x.Origin).Returns(SourceOrigin.None); + _mockInvocationContext.Setup(x => x.Location).Returns(() => _location); + + // fake the request for the directive + // (normally generated by the primary query execution pipeline) + var id = Guid.NewGuid(); + _mockRequest = new Mock(); + _mockRequest.Setup(x => x.Id).Returns(id); + _mockRequest.Setup(x => x.Origin).Returns(SourceOrigin.None); + _mockRequest.Setup(x => x.Directive).Returns(_directive); + _mockRequest.Setup(x => x.DirectiveTarget).Returns(() => _directiveTarget); + _mockRequest.Setup(x => x.InvocationContext).Returns(_mockInvocationContext.Object); + _mockRequest.Setup(x => x.DirectivePhase).Returns(phase); + + // copy in the resolver to a controlled mock (vs. whatever implementation was passed) + if (resolverMetadata != null) + { + _mockResolverMetadata = new Mock(); + _mockResolverMetadata.Setup(x => x.ParentInternalFullName).Returns(resolverMetadata.ParentInternalFullName); + _mockResolverMetadata.Setup(x => x.ParentInternalName).Returns(resolverMetadata.ParentInternalName); + _mockResolverMetadata.Setup(x => x.ParentObjectType).Returns(resolverMetadata.ParentObjectType); + _mockResolverMetadata.Setup(x => x.ExpectedReturnType).Returns(resolverMetadata.ExpectedReturnType); + _mockResolverMetadata.Setup(x => x.Method).Returns(resolverMetadata.Method); + _mockResolverMetadata.Setup(x => x.IsAsyncField).Returns(resolverMetadata.IsAsyncField); + _mockResolverMetadata.Setup(x => x.InternalName).Returns(resolverMetadata.InternalName); + _mockResolverMetadata.Setup(x => x.InternalFullName).Returns(resolverMetadata.InternalFullName); + _mockResolverMetadata.Setup(x => x.InternalName).Returns(resolverMetadata.InternalName); + _mockResolverMetadata.Setup(x => x.Parameters).Returns(resolverMetadata.Parameters); + } + } + + /// + /// Mimics a specific location in a document text. This value is passed to the request instead of + /// using . This information is handed to any context created by this builder. + /// + /// An origin within a query document text. + /// MockFieldExecutionContext. + public DirectiveContextBuilder AddOrigin(SourceOrigin origin) + { + _mockRequest.Setup(x => x.Origin).Returns(origin); + _mockInvocationContext.Setup(x => x.Origin).Returns(origin); + return this; + } + + /// + /// Simulate an argument being passed to the directive from a query document. It is assumed the value will cast correctly + /// and will not cause an error. + /// + /// Name of the argument on the directive, as declared in the schema. + /// A fully resolved value to use. + /// DirectiveContextBuilder. + public DirectiveContextBuilder AddInputArgument(string argumentName, object value) + { + var resolvedInputValue = new ResolvedInputArgumentValue(argumentName, value); + var arg = _directive.Arguments[argumentName]; + var inputArgument = new InputArgument(arg, resolvedInputValue, SourceOrigin.None); + _arguments.Add(inputArgument); + return this; + } + + /// + /// Alters the current security context to be different than that provided by the server that created this builder. + /// + /// The new security context to use. + /// MockFieldRequest. + public DirectiveContextBuilder AddSecurityContext(IUserSecurityContext securityContext) + { + _securityContext = securityContext; + return this; + } + + /// + /// + /// Adds a specific target that is passed to a directive resolver during resolution. + /// + /// For execution directives this is an object that implements . + /// + /// + /// For type system directives this is an object that implements . + /// + /// + /// The object being targeted by the directive invocation. + /// DirectiveContextBuilder. + public DirectiveContextBuilder AddTarget(object target) + { + _directiveTarget = target; + return this; + } + + private IGraphQLMiddlewareExecutionContext CreateFakeParentMiddlewareContext() + { + var queryRequest = new Mock(); + var parentContext = new Mock(); + + parentContext.Setup(x => x.QueryRequest).Returns(queryRequest.Object); + parentContext.Setup(x => x.ServiceProvider).Returns(this.ServiceProvider); + parentContext.Setup(x => x.SecurityContext).Returns(_securityContext); + parentContext.Setup(x => x.Metrics).Returns(null as IQueryExecutionMetrics); + parentContext.Setup(x => x.Logger).Returns(null as IGraphEventLogger); + parentContext.Setup(x => x.Messages).Returns(_messageCollection); + parentContext.Setup(x => x.IsValid).Returns(_messageCollection.IsSucessful); + parentContext.Setup(x => x.Session).Returns(new QuerySession()); + return parentContext.Object; + } + + /// + /// Creates an authorization context that can be used to test authorization middleware components. + /// + /// SchemaItemSecurityChallengeContext. + public SchemaItemSecurityChallengeContext CreateSecurityContext() + { + var parent = this.CreateFakeParentMiddlewareContext(); + + var request = new SchemaItemSecurityRequest(this.DirectiveRequest.Object); + return new SchemaItemSecurityChallengeContext( + parent, + request); + } + + /// + /// Creates a qualified execution context that can be passed to the directive execution pipeline + /// to test middleware components. + /// + /// GraphDirectiveExecutionContext. + public GraphDirectiveExecutionContext CreateExecutionContext() + { + return new GraphDirectiveExecutionContext( + _schema, + this.CreateFakeParentMiddlewareContext(), + this.DirectiveRequest.Object, + ResolvedVariableCollectionFactory.Create(), + _securityContext.DefaultUser); + } + + /// + /// Creates the resolution context that can be passed to a resolver for resolution. + /// + /// FieldResolutionContext. + public DirectiveResolutionContext CreateResolutionContext() + { + var context = this.CreateExecutionContext(); + + ExecutionArgumentGenerator.TryConvert( + _arguments, + context.VariableData, + context.Messages, + out var executionArguments); + + return new DirectiveResolutionContext( + this.ServiceProvider, + context.Session, + _schema, + context.QueryRequest, + this.DirectiveRequest.Object, + executionArguments, + context.Messages, + context.Logger, + context.User, + CancellationToken.None); + } + + /// + /// Gets a reference to the directive request to be contained in the context. + /// + /// The field request. + public Mock DirectiveRequest => _mockRequest; + + /// + /// Gets or sets the service provider used in all created contexts. + /// + /// The service provider. + public IServiceProvider ServiceProvider { get; set; } + + /// + /// Gets a mock reference to the root method that will be resonsible for resolving the context in case any direct + /// invocation tests are needed. Otherwise, this property is not used in resolving a context put directly + /// against the testserver. + /// + /// The metadata describing the resolver method to be invoked. + public Mock ResolverMetaData => _mockResolverMetadata; + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/FieldContextBuilder.cs b/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/FieldContextBuilder.cs index cb80ce1fc..88a9d5914 100644 --- a/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/FieldContextBuilder.cs +++ b/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/FieldContextBuilder.cs @@ -10,24 +10,24 @@ namespace GraphQL.AspNet.Tests.Framework.PipelineContextBuilders { using System; + using System.Threading; using GraphQL.AspNet.Common; - using GraphQL.AspNet.Execution.Source; using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Directives; using GraphQL.AspNet.Execution; using GraphQL.AspNet.Execution.Contexts; using GraphQL.AspNet.Execution.FieldResolution; using GraphQL.AspNet.Execution.QueryPlans.InputArguments; + using GraphQL.AspNet.Execution.Source; using GraphQL.AspNet.Execution.Variables; using GraphQL.AspNet.Interfaces.Execution; + using GraphQL.AspNet.Interfaces.Execution.QueryPlans.DocumentParts; + using GraphQL.AspNet.Interfaces.Execution.QueryPlans.InputArguments; using GraphQL.AspNet.Interfaces.Logging; using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Interfaces.Security; using GraphQL.AspNet.Security; using Moq; - using GraphQL.AspNet.Interfaces.Execution.QueryPlans.DocumentParts; - using GraphQL.AspNet.Interfaces.Execution.QueryPlans.InputArguments; - using System.Threading; /// /// A builder used to create inlined mocked replacements @@ -42,7 +42,7 @@ public class FieldContextBuilder private readonly Mock _mockFieldDocumentPart; private readonly IGraphMessageCollection _messageCollection; private readonly IInputArgumentCollection _arguments; - + private readonly Mock _mockResolverMetaData; private IUserSecurityContext _securityContext; /// @@ -103,17 +103,17 @@ public FieldContextBuilder( _mockRequest.Setup(x => x.Field).Returns(_graphField); _mockRequest.Setup(x => x.InvocationContext).Returns(_mockInvocationContext.Object); - this.ResolverMetaData = new Mock(); - this.ResolverMetaData.Setup(x => x.ParentInternalFullName).Returns(resolverMetadata.ParentInternalFullName); - this.ResolverMetaData.Setup(x => x.ParentInternalName).Returns(resolverMetadata.ParentInternalName); - this.ResolverMetaData.Setup(x => x.ParentObjectType).Returns(resolverMetadata.ParentObjectType); - this.ResolverMetaData.Setup(x => x.ExpectedReturnType).Returns(resolverMetadata.ExpectedReturnType); - this.ResolverMetaData.Setup(x => x.Method).Returns(resolverMetadata.Method); - this.ResolverMetaData.Setup(x => x.IsAsyncField).Returns(resolverMetadata.IsAsyncField); - this.ResolverMetaData.Setup(x => x.InternalName).Returns(resolverMetadata.InternalName); - this.ResolverMetaData.Setup(x => x.InternalFullName).Returns(resolverMetadata.InternalFullName); - this.ResolverMetaData.Setup(x => x.InternalName).Returns(resolverMetadata.InternalName); - this.ResolverMetaData.Setup(x => x.Parameters).Returns(resolverMetadata.Parameters); + _mockResolverMetaData = new Mock(); + _mockResolverMetaData.Setup(x => x.ParentInternalFullName).Returns(resolverMetadata.ParentInternalFullName); + _mockResolverMetaData.Setup(x => x.ParentInternalName).Returns(resolverMetadata.ParentInternalName); + _mockResolverMetaData.Setup(x => x.ParentObjectType).Returns(resolverMetadata.ParentObjectType); + _mockResolverMetaData.Setup(x => x.ExpectedReturnType).Returns(resolverMetadata.ExpectedReturnType); + _mockResolverMetaData.Setup(x => x.Method).Returns(resolverMetadata.Method); + _mockResolverMetaData.Setup(x => x.IsAsyncField).Returns(resolverMetadata.IsAsyncField); + _mockResolverMetaData.Setup(x => x.InternalName).Returns(resolverMetadata.InternalName); + _mockResolverMetaData.Setup(x => x.InternalFullName).Returns(resolverMetadata.InternalFullName); + _mockResolverMetaData.Setup(x => x.InternalName).Returns(resolverMetadata.InternalName); + _mockResolverMetaData.Setup(x => x.Parameters).Returns(resolverMetadata.Parameters); } /// @@ -159,7 +159,7 @@ public FieldContextBuilder AddInputArgument(string argumentName, object value) } /// - /// alters the security context to be different than that provided by the server that created this builder. + /// Alters the security context to be different than that provided by the server that created this builder. /// /// The security context. /// MockFieldRequest. @@ -186,34 +186,33 @@ private IGraphQLMiddlewareExecutionContext CreateFakeParentMiddlewareContext() } /// - /// Creates an authorization context to validate the field request this builder is creating. + /// Creates an authorization context that can be used to test authorization middleware components. /// - /// GraphFieldAuthorizationContext. + /// SchemaItemSecurityChallengeContext. public SchemaItemSecurityChallengeContext CreateSecurityContext() { var parent = this.CreateFakeParentMiddlewareContext(); - var request = new SchemaItemSecurityRequest(this.FieldRequest); + var request = new SchemaItemSecurityRequest(this.FieldRequest.Object); return new SchemaItemSecurityChallengeContext( parent, request); } /// - /// Creates this instance. + /// Creates an execution context that can be used to test field middleware pipeline contents. /// /// GraphFieldExecutionContext. public GraphFieldExecutionContext CreateExecutionContext() { return new GraphFieldExecutionContext( this.CreateFakeParentMiddlewareContext(), - this.FieldRequest, + this.FieldRequest.Object, ResolvedVariableCollectionFactory.Create()); } /// - /// Creates the resolution context capable of being acted on directly by a resolver, as opposed to being - /// processed through a pipeline. + /// Creates the resolution context that can be passed to a resolver to test field resolution. /// /// FieldResolutionContext. public FieldResolutionContext CreateResolutionContext() @@ -231,7 +230,7 @@ public FieldResolutionContext CreateResolutionContext() context.Session, _schema, context.QueryRequest, - this.FieldRequest, + this.FieldRequest.Object, executionArguments, context.Messages, context.Logger, @@ -243,7 +242,7 @@ public FieldResolutionContext CreateResolutionContext() /// Gets a reference to the field request to be contained in the context. /// /// The field request. - public IGraphFieldRequest FieldRequest => _mockRequest.Object; + public Mock FieldRequest => _mockRequest; /// /// Gets or sets the service provider used in all created contexts. @@ -257,6 +256,6 @@ public FieldResolutionContext CreateResolutionContext() /// against the testserver. /// /// The graph method. - public Mock ResolverMetaData { get; } + public Mock ResolverMetaData => _mockResolverMetaData; } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-testframework/TestServer.cs b/src/unit-tests/graphql-aspnet-testframework/TestServer.cs index 8f6a29ec6..681cd35c2 100644 --- a/src/unit-tests/graphql-aspnet-testframework/TestServer.cs +++ b/src/unit-tests/graphql-aspnet-testframework/TestServer.cs @@ -189,8 +189,7 @@ public virtual GraphTypeCreationResult CreateGraphType(Type concreteType, TypeKi } /// - /// (DEPRECATED, DO NOT USE) Creates a mocked context for the execution of a single field of data against the given concrete type and field name. This - /// context can be submitted against the field execution pipeline to generate a result. + /// (DEPRECATED, DO NOT USE). /// /// The concrete type representing the graph type in the schema. /// Name of the field, on the type, as it exists in the schema. @@ -205,7 +204,7 @@ public virtual FieldContextBuilder CreateGraphTypeFieldContextBuilder(str } /// - /// (DEPRECATED, DO NOT USE) Creates a builder that will generate the various field processing contexts for an action method on a target controller.. + /// (DEPRECATED, DO NOT USE). /// /// The type of the controller that owns the /// action. @@ -221,7 +220,8 @@ public virtual FieldContextBuilder CreateActionMethodFieldContextBuilder - /// The type of the entity that owns . + /// The type of the entity that owns . This entity must be a + /// controller or an entity representing an OBJECT graph type that is registered to the schema. /// Name of the field as it appears in the graph or the name of the action, method or property /// as it appears on the . This parameter is case sensitive. /// (optional) A source data object to supply to the builder. @@ -234,7 +234,8 @@ public virtual FieldContextBuilder CreateFieldContextBuilder(string fie /// /// Creates a builder targeting the field owned the the combination entity and field, method or property name. /// - /// Type of the entity to inspect. + /// Type of the entity that owns the . This entity must be a + /// controller or an entity representing an OBJECT graph type that is registered to the schema /// Name of the field as it appears in the graph or the name of the action, method or property /// as it appears on the . This parameter is case sensitive. /// (optional) A source data object to supply to the builder. @@ -308,32 +309,7 @@ public virtual FieldContextBuilder CreateFieldContextBuilder(Type entityType, st } /// - /// Creates a reference to the invokable method or property that represents the - /// root resolver for the given . (i.e. the method - /// or property of the object that can produce the core data value). - /// - /// The type of the object to create a reference from. - /// Name of the field. - /// IGraphMethod. - public virtual IGraphFieldResolverMetaData CreateResolverMetadata(string fieldName) - { - return CreateResolverMetadata(typeof(TObjectType), fieldName); - } - - /// - /// Creates a reference to the invokable method or property that acts as a resolver for the given . - /// - /// Type of the entity that owns the field. - /// Name of the field or method/property name to search for. - /// IGraphMethod. - public virtual IGraphFieldResolverMetaData CreateResolverMetadata(Type entityType, string fieldOrActionName) - { - var builder = CreateFieldContextBuilder(entityType, fieldOrActionName); - return builder?.ResolverMetaData.Object; - } - - /// - /// Creates an execution context to invoke a directive execution pipeleine. + /// /// (DEPRECATED, DO NOT USE). /// /// The type of the directive to invoke. /// The target location from where the directive is being called. @@ -342,6 +318,7 @@ public virtual IGraphFieldResolverMetaData CreateResolverMetadata(Type entityTyp /// The origin in a source document, if any. /// The arguments to pass to the directive, if any. /// GraphDirectiveExecutionContext. + [Obsolete("Use " + nameof(CreateDirectiveContextBuilder) + " Instead")] public virtual GraphDirectiveExecutionContext CreateDirectiveExecutionContext( DirectiveLocation location, object directiveTarget, @@ -350,52 +327,133 @@ public virtual GraphDirectiveExecutionContext CreateDirectiveExecutionContext() - .Build(); + var builder = this.CreateDirectiveContextBuilder( + typeof(TDirective), + location, + directiveTarget, + phase, + origin, + arguments); + + return builder.CreateExecutionContext(); + } + + /// + /// Creates a builder targeting a specific directive. This builder can be used to create execution contexts (targeting middleware components) + /// and resolution contexts (targeting specific directive resolvers) in order to perform different types of tests. + /// + /// The type of the to build for. + /// The directive location, of those accepted by the directive. + /// The directive target. Typically an for execution directives + /// or an for type system directives. + /// The phase of execution. This value will be passed to the middleware item or resolver. + /// The origin location within a query document. This value will be passed to the middleware item + /// or resolver. + /// The set of input argument values accepted by the directive. These arguments are expected + /// to be supplied in order of definition within the schema and castable to the appropriate data types. This builder + /// will NOT attempt any validation or mangling on these values. + /// DirectiveContextBuilder. + public virtual DirectiveContextBuilder CreateDirectiveContextBuilder( + DirectiveLocation directiveLocation, + object directiveTarget = null, + DirectiveInvocationPhase phase = DirectiveInvocationPhase.QueryDocumentExecution, + SourceOrigin origin = default, + object[] arguments = null) + { + var builder = this.CreateDirectiveContextBuilder( + typeof(TDirectiveType), + directiveLocation, + directiveTarget, + phase, + origin, + arguments); + + return builder; + } - var targetDirective = server.Schema.KnownTypes.FindDirective(typeof(TDirective)); + /// + /// Creates a builder targeting a specific directive. This builder can be used to create execution contexts (targeting middleware components) + /// and resolution contexts (targeting specific directive resolvers) in order to perform different types of tests. + /// + /// + /// If the target is not a valid directive or not registered to the schema a context builder + /// will still be created with null values to test various scenarios. + /// + /// The type of the directive that is registered to teh schema. + /// The directive location, of those accepted by the directive. + /// The directive target. Typically an for execution directives + /// or an for type system directives. + /// The phase of execution. This value will be passed to the middleware item or resolver. + /// The origin location within a query document. This value will be passed to the middleware item + /// or resolver. + /// The set of input argument values accepted by the directive. These arguments are expected + /// to be supplied in order of definition within the schema and castable to the appropriate data types. This builder + /// will NOT attempt any validation or mangling on these values. + /// DirectiveContextBuilder. + public virtual DirectiveContextBuilder CreateDirectiveContextBuilder( + Type directiveType, + DirectiveLocation directiveLocation, + object directiveTarget = null, + DirectiveInvocationPhase phase = DirectiveInvocationPhase.QueryDocumentExecution, + SourceOrigin origin = default, + object[] arguments = null) + { + var directiveInstance = this.Schema.KnownTypes.FindGraphType(directiveType, TypeKind.DIRECTIVE) as IDirective; - var queryRequest = new Mock(); - var directiveRequest = new Mock(); - var invocationContext = new Mock(); - var argCollection = InputArgumentCollectionFactory.Create(); + IGraphFieldResolverMetaData metadata = null; + directiveInstance?.Resolver.MetaData.TryGetValue(directiveLocation, out metadata); - directiveRequest.Setup(x => x.DirectivePhase).Returns(phase); - directiveRequest.Setup(x => x.InvocationContext).Returns(invocationContext.Object); - directiveRequest.Setup(x => x.DirectiveTarget).Returns(directiveTarget); - directiveRequest.Setup(x => x.Directive).Returns(targetDirective); + var builder = new DirectiveContextBuilder( + this.ServiceProvider, + this.SecurityContext, + this.Schema, + directiveInstance, + directiveLocation, + phase, + metadata); - invocationContext.Setup(x => x.Location).Returns(location); - invocationContext.Setup(x => x.Arguments).Returns(argCollection); - invocationContext.Setup(x => x.Origin).Returns(origin); - invocationContext.Setup(x => x.Directive).Returns(targetDirective); + if (directiveTarget != null) + builder.AddTarget(directiveTarget); - if (targetDirective != null && targetDirective.Kind == TypeKind.DIRECTIVE - && arguments != null) + if (arguments != null && directiveInstance != null) { - for (var i = 0; i < targetDirective.Arguments.Count; i++) + for (var i = 0; i < arguments.Length; i++) { - if (arguments.Length <= i) - break; - - var directiveArg = targetDirective.Arguments[i]; - var resolvedValue = arguments[i]; - - var argValue = new ResolvedInputArgumentValue(directiveArg.Name, resolvedValue); - var inputArg = new InputArgument(directiveArg, argValue); - argCollection.Add(inputArg); + if (directiveInstance.Arguments.Count > i) + { + var argByPosition = directiveInstance.Arguments[i]; + builder.AddInputArgument(argByPosition.Name, arguments[i]); + } } } - var context = new GraphDirectiveExecutionContext( - server.Schema, - directiveRequest.Object, - queryRequest.Object, - server.ServiceProvider, - new QuerySession()); + return builder; + } + + /// + /// Creates a reference to the invokable method or property that represents the + /// root resolver for the given . (i.e. the method + /// or property of the object that can produce the core data value). + /// + /// The type of the object to create a reference from. + /// Name of the field. + /// IGraphMethod. + public virtual IGraphFieldResolverMetaData CreateResolverMetadata(string fieldName) + { + return CreateResolverMetadata(typeof(TObjectType), fieldName); + } - return context; + /// + /// Creates a reference to the invokable method or property that acts as a resolver for the given . + /// The must represent a controller or OBJECT graph type. + /// + /// Type of the entity that owns the field. + /// Name of the field or method/property name to search for. + /// IGraphMethod. + public virtual IGraphFieldResolverMetaData CreateResolverMetadata(Type entityType, string fieldOrActionName) + { + var builder = CreateFieldContextBuilder(entityType, fieldOrActionName); + return builder?.ResolverMetaData.Object; } /// diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/RulesEngine/DirectiveValidationRuleCheckTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/RulesEngine/DirectiveValidationRuleCheckTests.cs index 4e19a64a7..545cb52aa 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/RulesEngine/DirectiveValidationRuleCheckTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/RulesEngine/DirectiveValidationRuleCheckTests.cs @@ -33,9 +33,11 @@ public void UnknownLocation_FailsValidation() var obj = new Mock(); - var context = server.CreateDirectiveExecutionContext( + var context = server.CreateDirectiveContextBuilder( DirectiveLocation.NONE, - obj.Object); + obj.Object) + + .CreateExecutionContext(); var ruleSet = new DirectiveValidationRuleProcessor(); var complete = ruleSet.Execute(context.AsEnumerable()); @@ -53,10 +55,11 @@ public void UnknownPhase_FailsValidation() .Build(); var obj = new Mock(); - var context = server.CreateDirectiveExecutionContext( + var context = server.CreateDirectiveContextBuilder( DirectiveLocation.OBJECT, obj.Object, - DirectiveInvocationPhase.Unknown); + DirectiveInvocationPhase.Unknown) + .CreateExecutionContext(); var ruleSet = new DirectiveValidationRuleProcessor(); var complete = ruleSet.Execute(context.AsEnumerable()); @@ -74,10 +77,11 @@ public void LocationMisMatch_FailsValidation() .Build(); var obj = new Mock(); - var context = server.CreateDirectiveExecutionContext( + var context = server.CreateDirectiveContextBuilder( DirectiveLocation.FIELD, obj.Object, - DirectiveInvocationPhase.SchemaGeneration); + DirectiveInvocationPhase.SchemaGeneration) + .CreateExecutionContext(); var ruleSet = new DirectiveValidationRuleProcessor(); var complete = ruleSet.Execute(context.AsEnumerable()); @@ -96,10 +100,11 @@ public void NotADirective_FailsValidation() .Build(); var obj = new Mock(); - var context = server.CreateDirectiveExecutionContext( + var context = server.CreateDirectiveContextBuilder( DirectiveLocation.OBJECT, obj.Object, - DirectiveInvocationPhase.SchemaGeneration); + DirectiveInvocationPhase.SchemaGeneration) + .CreateExecutionContext(); var ruleSet = new DirectiveValidationRuleProcessor(); var complete = ruleSet.Execute(context.AsEnumerable()); @@ -118,12 +123,13 @@ public void ValidateRequest_PassedValidation() .Build(); var obj = new Mock(); - var context = server.CreateDirectiveExecutionContext( + var context = server.CreateDirectiveContextBuilder( DirectiveLocation.OBJECT, obj.Object, DirectiveInvocationPhase.SchemaGeneration, SourceOrigin.None, - new object[] { 5, "someValue" }); + new object[] { 5, "someValue" }) + .CreateExecutionContext(); var ruleSet = new DirectiveValidationRuleProcessor(); var complete = ruleSet.Execute(context.AsEnumerable()); @@ -142,12 +148,13 @@ public void IncorrectNumberOfArguments_FailsValidation() var obj = new Mock(); - var context = server.CreateDirectiveExecutionContext( + var context = server.CreateDirectiveContextBuilder( DirectiveLocation.OBJECT, obj.Object, DirectiveInvocationPhase.SchemaGeneration, SourceOrigin.None, - new object[] { 5 }); // directive requires 2 argument, only 1 supplied + new object[] { 5 }) // directive requires 2 argument, only 1 supplied + .CreateExecutionContext(); var ruleSet = new DirectiveValidationRuleProcessor(); var complete = ruleSet.Execute(context.AsEnumerable()); @@ -167,12 +174,13 @@ public void InvalidArgument_FailsValidation() var obj = new Mock(); - var context = server.CreateDirectiveExecutionContext( + var context = server.CreateDirectiveContextBuilder( DirectiveLocation.OBJECT, obj.Object, DirectiveInvocationPhase.SchemaGeneration, SourceOrigin.None, - new object[] { "notAInt", "validString" }); // arg 1 should be an int + new object[] { "notAInt", "validString" }) // arg 1 should be an int + .CreateExecutionContext(); var ruleSet = new DirectiveValidationRuleProcessor(); var complete = ruleSet.Execute(context.AsEnumerable()); diff --git a/src/unit-tests/graphql-aspnet-tests/Logging/GeneralEventLogEntryPropertyChecks.cs b/src/unit-tests/graphql-aspnet-tests/Logging/GeneralEventLogEntryPropertyChecks.cs index 32f173b5a..ce4488f7c 100644 --- a/src/unit-tests/graphql-aspnet-tests/Logging/GeneralEventLogEntryPropertyChecks.cs +++ b/src/unit-tests/graphql-aspnet-tests/Logging/GeneralEventLogEntryPropertyChecks.cs @@ -264,7 +264,7 @@ public void FieldResolutionCompletedLogEntry() var package = server.CreateFieldContextBuilder( nameof(LogTestController.ExecuteField2)); var resolutionContext = package.CreateResolutionContext(); - var fieldRequest = package.FieldRequest; + var fieldRequest = package.FieldRequest.Object; resolutionContext.Result = "15"; @@ -289,7 +289,7 @@ public void FieldAuthorizationStartedLogEntry() var package = server.CreateFieldContextBuilder( nameof(LogTestController.ExecuteField2)); - var fieldRequest = package.FieldRequest; + var fieldRequest = package.FieldRequest.Object; var authContext = package.CreateSecurityContext(); authContext.AuthenticatedUser = server.SecurityContext.DefaultUser; @@ -314,7 +314,7 @@ public void FieldAuthorizationCompletedLogEntry() var package = server.CreateFieldContextBuilder( nameof(LogTestController.ExecuteField2)); - var fieldRequest = package.FieldRequest; + var fieldRequest = package.FieldRequest.Object; var authContext = package.CreateSecurityContext(); authContext.AuthenticatedUser = server.SecurityContext.DefaultUser; @@ -341,7 +341,7 @@ public void FieldAuthenticationStartedLogEntry() var package = server.CreateFieldContextBuilder( nameof(LogTestController.ExecuteField2)); - var fieldRequest = package.FieldRequest; + var fieldRequest = package.FieldRequest.Object; var authContext = package.CreateSecurityContext(); authContext.AuthenticatedUser = server.SecurityContext.DefaultUser; @@ -375,7 +375,7 @@ public void FieldAuthenticationCompletedLogEntry() var package = server.CreateFieldContextBuilder( nameof(LogTestController.ExecuteField2)); - var fieldRequest = package.FieldRequest; + var fieldRequest = package.FieldRequest.Object; var authContext = package.CreateSecurityContext(); authContext.AuthenticatedUser = server.SecurityContext.DefaultUser; authContext.Result = SchemaItemSecurityChallengeResult.Fail("test message 1"); @@ -402,7 +402,7 @@ public void ActionMethodInvocationStartedLogEntry() var graphMethod = GraphQLTemplateHelper.CreateActionMethodTemplate(nameof(LogTestController.ExecuteField2)).CreateResolverMetaData(); var package = server.CreateFieldContextBuilder( nameof(LogTestController.ExecuteField2)); - var fieldRequest = package.FieldRequest; + var fieldRequest = package.FieldRequest.Object; var entry = new ActionMethodInvocationStartedLogEntry(graphMethod, fieldRequest); @@ -425,7 +425,7 @@ public void ActionMethodInvocationCompletedLogEntry() var package = server.CreateFieldContextBuilder( nameof(LogTestController.ExecuteField2)); var resolutionContext = package.CreateResolutionContext(); - var fieldRequest = package.FieldRequest; + var fieldRequest = package.FieldRequest.Object; var result = new object(); @@ -449,7 +449,7 @@ public void ActionMethodInvocationExceptionLogEntry() var metaData = GraphQLTemplateHelper.CreateActionMethodTemplate(nameof(LogTestController.ExecuteField2)).CreateResolverMetaData(); var package = server.CreateFieldContextBuilder( nameof(LogTestController.ExecuteField2)); - var fieldRequest = package.FieldRequest; + var fieldRequest = package.FieldRequest.Object; var result = new object(); @@ -481,7 +481,7 @@ public void ActionMethodUnhandledExceptionLogEntry() nameof(LogTestController.ExecuteField2)); var template = GraphQLTemplateHelper.CreateActionMethodTemplate(nameof(LogTestController.ExecuteField2)); var metaData = template.CreateResolverMetaData(); - var fieldRequest = package.FieldRequest; + var fieldRequest = package.FieldRequest.Object; var result = new object(); diff --git a/src/unit-tests/graphql-aspnet-tests/Middleware/DirectivePipelineMiddlewareTests.cs b/src/unit-tests/graphql-aspnet-tests/Middleware/DirectivePipelineMiddlewareTests.cs index 1659f8dac..2467bb67a 100644 --- a/src/unit-tests/graphql-aspnet-tests/Middleware/DirectivePipelineMiddlewareTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Middleware/DirectivePipelineMiddlewareTests.cs @@ -37,12 +37,13 @@ public async Task ValidationMiddlewareForwardsRequestToRuleSet() .AddType() .Build(); - var context = server.CreateDirectiveExecutionContext( + var context = server.CreateDirectiveContextBuilder( DirectiveLocation.OBJECT, new TwoPropertyObject(), DirectiveInvocationPhase.SchemaGeneration, SourceOrigin.None, - new object[] { 5 }); // directive requires 2 argument, only 1 supplied + new object[] { 5 }) // directive requires 2 argument, only 1 supplied + .CreateExecutionContext(); Assert.IsTrue(context.IsValid); @@ -62,12 +63,13 @@ public async Task InvocationMiddlewareCallsResolver() var testObject = new TwoPropertyObject(); - var context = server.CreateDirectiveExecutionContext( + var context = server.CreateDirectiveContextBuilder( DirectiveLocation.OBJECT, testObject, DirectiveInvocationPhase.SchemaGeneration, SourceOrigin.None, - new object[] { "testValue", 5 }); + new object[] { "testValue", 5 }) + .CreateExecutionContext(); Assert.IsTrue(context.IsValid); From f23782bb589763865af265343b4fd73aada5a947 Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Fri, 21 Jul 2023 21:51:38 -0700 Subject: [PATCH 43/63] WIP, resolver context injection tests done --- .../GraphControllers/StarshipsController.cs | 3 +- .../Attributes/GraphSkipAttribute.cs | 3 +- .../ResolverParameterResolutionRules.cs | 21 ++++ .../SchemaExecutionConfiguration.cs | 20 +++- ...CompleteBatchOperationGraphActionResult.cs | 4 +- .../Execution/ExecutionArgumentCollection.cs | 58 ++++++++- .../ISchemaExecutionConfiguration.cs | 10 ++ .../TypeTemplates/GraphArgumentTemplate.cs | 50 ++++++-- .../MethodGraphFieldTemplateBase.cs | 2 +- .../TypeSystem/GraphArgumentModifiers.cs | 7 +- .../GraphArgumentModifiersExtensions.cs | 10 ++ .../MultipartRequests/Model/FileUpload.cs | 2 - .../QueryContextBuilder.cs | 14 ++- .../DefaultGraphResponseWriterTests.cs | 2 +- .../Execution/RuntimeDirectiveTests.cs | 111 ++++++++++++++++++ .../Execution/RuntimeFieldTests.cs | 97 ++++++++++++++- .../GeneralEventLogEntryPropertyChecks.cs | 4 +- .../TypeTemplates/ArgumentTemplateTests.cs | 18 +++ .../ParameterTestData/ObjectWithGraphSkip.cs | 19 +++ .../ParameterTestData/ParameterTestClass.cs | 2 + .../Web/HttpContextInjectionTests.cs | 88 ++++++++++++++ 21 files changed, 509 insertions(+), 36 deletions(-) create mode 100644 src/graphql-aspnet/Configuration/ResolverParameterResolutionRules.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ParameterTestData/ObjectWithGraphSkip.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Web/HttpContextInjectionTests.cs diff --git a/src/ancillary-projects/starwars/starwars-common/GraphControllers/StarshipsController.cs b/src/ancillary-projects/starwars/starwars-common/GraphControllers/StarshipsController.cs index 18d4b6600..e0a68d05f 100644 --- a/src/ancillary-projects/starwars/starwars-common/GraphControllers/StarshipsController.cs +++ b/src/ancillary-projects/starwars/starwars-common/GraphControllers/StarshipsController.cs @@ -21,6 +21,8 @@ namespace GraphQL.AspNet.StarwarsAPI.Common.GraphControllers using GraphQL.AspNet.Interfaces.Controllers; using GraphQL.AspNet.StarwarsAPI.Common.Model; using GraphQL.AspNet.StarwarsAPI.Common.Services; + using Microsoft.AspNetCore.Http; + using Microsoft.Extensions.DependencyInjection; /// /// A graph controller responsible for managing starship related data. @@ -67,7 +69,6 @@ public async Task RetrieveStarship([FromGraphQL("id")] Graph return this.Ok(starship); } - /// /// Retrieves a droid in the system by their id. Note the use of a different name for the parameter /// between its exposure in the object graph vs. the formal parameter name used in the C# code. diff --git a/src/graphql-aspnet/Attributes/GraphSkipAttribute.cs b/src/graphql-aspnet/Attributes/GraphSkipAttribute.cs index e7101fc70..17c3bdd98 100644 --- a/src/graphql-aspnet/Attributes/GraphSkipAttribute.cs +++ b/src/graphql-aspnet/Attributes/GraphSkipAttribute.cs @@ -21,7 +21,8 @@ namespace GraphQL.AspNet.Attributes | AttributeTargets.Field | AttributeTargets.Enum | AttributeTargets.Class - | AttributeTargets.Struct)] + | AttributeTargets.Struct + | AttributeTargets.Parameter)] public class GraphSkipAttribute : Attribute { // Implementation note: This attribute purposefully does diff --git a/src/graphql-aspnet/Configuration/ResolverParameterResolutionRules.cs b/src/graphql-aspnet/Configuration/ResolverParameterResolutionRules.cs new file mode 100644 index 000000000..1ae3c2bbd --- /dev/null +++ b/src/graphql-aspnet/Configuration/ResolverParameterResolutionRules.cs @@ -0,0 +1,21 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Configuration +{ + /// + /// The available rules that dictate how the runtime will handle a missing or unresolved parameter + /// during the execution of a field or directive resolver. + /// + public enum ResolverParameterResolutionRules + { + ThrowException = 0, + UseNullorDefault = 1, + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/SchemaExecutionConfiguration.cs b/src/graphql-aspnet/Configuration/SchemaExecutionConfiguration.cs index 7bf5e61f1..f00fd9ad9 100644 --- a/src/graphql-aspnet/Configuration/SchemaExecutionConfiguration.cs +++ b/src/graphql-aspnet/Configuration/SchemaExecutionConfiguration.cs @@ -23,6 +23,14 @@ public class SchemaExecutionConfiguration : ISchemaExecutionConfiguration { private ResolverIsolationOptions _isolationOptions = ResolverIsolationOptions.None; + /// + /// Initializes a new instance of the class. + /// + public SchemaExecutionConfiguration() + { + this.ResolverParameterResolutionRule = ResolverParameterResolutionRules.ThrowException; + } + /// /// Merges the specified configuration setttings into this instance. /// @@ -38,6 +46,7 @@ public void Merge(ISchemaExecutionConfiguration config) this.MaxQueryDepth = config.MaxQueryDepth; this.MaxQueryComplexity = config.MaxQueryComplexity; this.DebugMode = config.DebugMode; + this.ResolverParameterResolutionRule = config.ResolverParameterResolutionRule; } /// @@ -52,6 +61,12 @@ public void Merge(ISchemaExecutionConfiguration config) /// public float? MaxQueryComplexity { get; set; } + /// + public bool DebugMode { get; set; } + + /// + public ResolverParameterResolutionRules ResolverParameterResolutionRule { get; set; } + /// public ResolverIsolationOptions ResolverIsolation { @@ -68,10 +83,5 @@ public ResolverIsolationOptions ResolverIsolation _isolationOptions = value; } } - - /// - public bool DebugMode { get; set; } } - -#pragma warning restore CS0618 // Type or member is obsolete } \ No newline at end of file diff --git a/src/graphql-aspnet/Controllers/ActionResults/CompleteBatchOperationGraphActionResult.cs b/src/graphql-aspnet/Controllers/ActionResults/CompleteBatchOperationGraphActionResult.cs index 98d59d051..695b1fee0 100644 --- a/src/graphql-aspnet/Controllers/ActionResults/CompleteBatchOperationGraphActionResult.cs +++ b/src/graphql-aspnet/Controllers/ActionResults/CompleteBatchOperationGraphActionResult.cs @@ -22,8 +22,8 @@ namespace GraphQL.AspNet.Controllers.ActionResults /// A graph action result that is built from a batch builder and can turn said builder into an /// appropriate dictionary of items to resolve a type extension. /// - /// The type of the source item identified in the type extension. - /// The type of the result item identified in the type extension. + /// The type of the source item supplied to the batch extension. + /// The type of the result item produced by the batch extension. /// The type of the key that links to . public class CompleteBatchOperationGraphActionResult : IGraphActionResult { diff --git a/src/graphql-aspnet/Execution/ExecutionArgumentCollection.cs b/src/graphql-aspnet/Execution/ExecutionArgumentCollection.cs index 1dcf40511..457195124 100644 --- a/src/graphql-aspnet/Execution/ExecutionArgumentCollection.cs +++ b/src/graphql-aspnet/Execution/ExecutionArgumentCollection.cs @@ -9,14 +9,19 @@ namespace GraphQL.AspNet.Execution { + using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; + using System.Reflection; using GraphQL.AspNet.Common; + using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Execution.Contexts; using GraphQL.AspNet.Execution.Exceptions; + using GraphQL.AspNet.Execution.RulesEngine.RuleSets.DocumentValidation.FieldSelectionSetSteps; using GraphQL.AspNet.Interfaces.Execution; using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Interfaces.Web; using GraphQL.AspNet.Schemas.TypeSystem; /// @@ -95,7 +100,7 @@ public object[] PrepareArguments(IGraphFieldResolverMetaData resolverMetadata) { var parameter = resolverMetadata.Parameters[i]; - object passedValue = this.ResolveParameterValue(parameter); + object passedValue = this.ResolveParameterValue(parameter, resolverMetadata.InternalFullName); // ensure compatible list types between the internally // tracked data and the target type of the method being invoked @@ -113,7 +118,7 @@ public object[] PrepareArguments(IGraphFieldResolverMetaData resolverMetadata) return preparedParams; } - private object ResolveParameterValue(IGraphFieldResolverParameterMetaData paramDef) + private object ResolveParameterValue(IGraphFieldResolverParameterMetaData paramDef, string parentFullName) { Validation.ThrowIfNull(paramDef, nameof(paramDef)); @@ -121,14 +126,40 @@ private object ResolveParameterValue(IGraphFieldResolverParameterMetaData paramD return _resolutionContext?.SourceData; if (paramDef.ArgumentModifiers.IsCancellationToken()) - return _resolutionContext?.CancellationToken; + return _resolutionContext?.CancellationToken ?? default; if (paramDef.ArgumentModifiers.IsResolverContext()) { if (_resolutionContext != null && Validation.IsCastable(_resolutionContext.GetType(), paramDef.ExpectedType)) return _resolutionContext; - return null; + if (paramDef.HasDefaultValue) + return paramDef.DefaultValue; + + // check fallback rules for missing, non-schema items + if (_resolutionContext != null && _resolutionContext.Schema.Configuration.ExecutionOptions.ResolverParameterResolutionRule == Configuration.ResolverParameterResolutionRules.UseNullorDefault) + return this.CreateNullOrDefault(paramDef.ExpectedType); + + throw new GraphExecutionException( + $"The resolution context parameter '{paramDef.InternalName}' of type {paramDef.ExpectedType.FriendlyName()} for resolver '{parentFullName}' could not be resolved and " + + $"does not declare a default value. Unable to complete the request."); + } + + if (paramDef.ArgumentModifiers.IsHttpContext()) + { + if (_resolutionContext?.QueryRequest is IQueryExecutionWebRequest req) + return req.HttpContext; + + if (paramDef.HasDefaultValue) + return paramDef.DefaultValue; + + // check fallback rules for missing, non-schema items + if (_resolutionContext != null && _resolutionContext.Schema.Configuration.ExecutionOptions.ResolverParameterResolutionRule == Configuration.ResolverParameterResolutionRules.UseNullorDefault) + return this.CreateNullOrDefault(paramDef.ExpectedType); + + throw new GraphExecutionException( + $"The http context parameter '{paramDef.InternalName}' of type {paramDef.ExpectedType.FriendlyName()} for resolver '{parentFullName}' could not be resolved and " + + $"does not declare a default value. Unable to complete the request."); } // if there an argument supplied on the query for this parameter, use that @@ -138,8 +169,8 @@ private object ResolveParameterValue(IGraphFieldResolverParameterMetaData paramD // if the parameter is part of the graph, use the related argument's default value if (paramDef.ArgumentModifiers.CouldBePartOfTheSchema()) { - // additional checks and coersion if this the value is - // being supplied from a query + // additional checks and coersion if this the value is (or should be) + // supplied from a query var graphArgument = _resolutionContext? .SchemaDefinedArguments? .FindArgumentByParameterName(paramDef.InternalName); @@ -162,6 +193,7 @@ private object ResolveParameterValue(IGraphFieldResolverParameterMetaData paramD // but captured here as a saftey net for users // doing custom extensions or implementations // this prevents resolver execution with indeterminate or unexpected data + // as well as cryptic error messages related to object invocation var path = _resolutionContext?.Route.Path; throw new GraphExecutionException( $"The parameter '{paramDef.InternalName}' for schema item '{path}' could not be resolved from the query document " + @@ -180,6 +212,10 @@ private object ResolveParameterValue(IGraphFieldResolverParameterMetaData paramD if (paramDef.HasDefaultValue) return paramDef.DefaultValue; + // check fallback rules for missing, non-schema items + if (_resolutionContext != null && _resolutionContext.Schema.Configuration.ExecutionOptions.ResolverParameterResolutionRule == Configuration.ResolverParameterResolutionRules.UseNullorDefault) + return this.CreateNullOrDefault(paramDef.ExpectedType); + var schemaItem = _resolutionContext?.Route.Path ?? paramDef.InternalFullName; @@ -190,6 +226,16 @@ private object ResolveParameterValue(IGraphFieldResolverParameterMetaData paramD $"and no default value was declared."); } + private object CreateNullOrDefault(Type typeToCreateFor) + { + if (typeToCreateFor.IsValueType) + { + return Activator.CreateInstance(typeToCreateFor); + } + + return null; + } + /// public bool ContainsKey(string key) => _suppliedArgumentDataValues.ContainsKey(key); diff --git a/src/graphql-aspnet/Interfaces/Configuration/ISchemaExecutionConfiguration.cs b/src/graphql-aspnet/Interfaces/Configuration/ISchemaExecutionConfiguration.cs index 35d864c52..1ac2689c4 100644 --- a/src/graphql-aspnet/Interfaces/Configuration/ISchemaExecutionConfiguration.cs +++ b/src/graphql-aspnet/Interfaces/Configuration/ISchemaExecutionConfiguration.cs @@ -82,5 +82,15 @@ public interface ISchemaExecutionConfiguration /// /// An integer representing the maximum calculated query complexity of a single query plan before its rejected. float? MaxQueryComplexity { get; } + + /// + /// Gets a value that determines the behaviort of the runtime when a required parameter + /// to a field or directive resolver cannot be found. + /// + /// + /// Required refers to a method parameter that does not supply a default value. + /// + /// The resolver parameter resolution rule. + ResolverParameterResolutionRules ResolverParameterResolutionRule { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphArgumentTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphArgumentTemplate.cs index 861e29fa3..e76d20ff2 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphArgumentTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphArgumentTemplate.cs @@ -27,6 +27,7 @@ namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; + using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; /// @@ -38,6 +39,8 @@ public class GraphArgumentTemplate : IGraphArgumentTemplate private FromGraphQLAttribute _argDeclaration; private bool _invalidTypeExpression; private HashSet _foundModifiers; + private GraphSkipAttribute _argSkipDeclaration; + private GraphSkipAttribute _argTypeSkipDeclaration; /// /// Initializes a new instance of the class. @@ -64,7 +67,7 @@ public virtual void Parse() this.AppliedDirectives = this.ExtractAppliedDirectiveTemplates(); // set the name - _argDeclaration = this.Parameter.SingleAttributeOrDefault(); + _argDeclaration = this.AttributeProvider.SingleAttributeOrDefault(); string name = null; if (_argDeclaration != null) { @@ -84,7 +87,7 @@ public virtual void Parse() name = name.Replace(Constants.Routing.PARAMETER_META_NAME, this.Parameter.Name); this.Route = new GraphArgumentFieldPath(this.Parent.Route, name); - this.Description = this.Parameter.SingleAttributeOrDefault()?.Description?.Trim(); + this.Description = this.AttributeProvider.SingleAttributeOrDefault()?.Description?.Trim(); if (_argDeclaration?.TypeExpression == null) { @@ -136,8 +139,14 @@ public virtual void Parse() if (this.IsResolutionContext()) _foundModifiers.Add(GraphArgumentModifiers.ResolutionContext); + if (this.IsHttpContext()) + _foundModifiers.Add(GraphArgumentModifiers.HttpContext); + if (_foundModifiers.Count == 1) this.ArgumentModifier = _foundModifiers.First(); + + _argSkipDeclaration = this.AttributeProvider.FirstAttributeOfTypeOrDefault(); + _argTypeSkipDeclaration = this.Parameter.ParameterType.FirstAttributeOfTypeOrDefault(); } /// @@ -147,13 +156,20 @@ public virtual void Parse() /// true if the ; otherwise, false. public virtual bool IsResolutionContext() { - if (this.Parent.Arguments.Any(x => x.ArgumentModifier.IsResolverContext())) - return false; - - if (Validation.IsCastable(this.ObjectType, typeof(FieldResolutionContext)) && this.Parent is IGraphFieldTemplate) + if (Validation.IsCastable(this.ObjectType, typeof(SchemaItemResolutionContext))) return true; - if (Validation.IsCastable(this.ObjectType, typeof(DirectiveResolutionContext)) && this.Parent is IGraphDirectiveTemplate) + return false; + } + + /// + /// Determines whether this instance represents a parameter that should be marked as a "resolution context" + /// and filled with the active context when possible. + /// + /// true if the ; otherwise, false. + public virtual bool IsHttpContext() + { + if (Validation.IsCastable(this.ObjectType, typeof(HttpContext))) return true; return false; @@ -166,6 +182,7 @@ public virtual bool IsResolutionContext() /// System.Boolean. protected virtual bool IsSourceDataArgument() { + // there can only ever be one source argument if (this.Parent.Arguments.Any(x => x.ArgumentModifier.IsSourceParameter())) return false; @@ -281,10 +298,27 @@ public void ValidateOrThrow() var flags = string.Join(", ", _foundModifiers); throw new GraphTypeDeclarationException( $"The item '{this.Parent.InternalFullName}' declares a parameter '{this.Name}' that " + - $"is declares more than one behavior modification flag. Each parameter must declare only one" + + $"declares more than one behavior modification flag. Each parameter must declare only one " + $"behavioral role within a given resolver method. Flags Declared: {flags}"); } + if (_argSkipDeclaration != null && this.ArgumentModifier.CouldBePartOfTheSchema()) + { + throw new GraphTypeDeclarationException( + $"The item '{this.Parent.InternalFullName}' contains a parameter '{this.Name}' that " + + $"declares the {nameof(GraphSkipAttribute)}. However, this argument may be included in the schema in some scenarios. " + + $"If this argument is intended to be served from a service provider try adding {typeof(FromServicesAttribute)} to its declaration."); + } + + if (_argTypeSkipDeclaration != null && this.ArgumentModifier.CouldBePartOfTheSchema()) + { + throw new GraphTypeDeclarationException( + $"The item '{this.Parent.InternalFullName}' contains a parameter '{this.Name}' that " + + $"is of type {this.Parameter.ParameterType.FriendlyName()} . This type declares the {nameof(GraphSkipAttribute)} and is " + + $"not allowed to appear in any schema but is currently being interpreted as an INPUT_OBJECT. If the parameter value is intended to be served " + + $"from a service provider try adding {typeof(FromServicesAttribute)} to its declaration."); + } + foreach (var directive in this.AppliedDirectives) directive.ValidateOrThrow(); } diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplateBase.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplateBase.cs index a52b4ea25..cff78d02f 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplateBase.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplateBase.cs @@ -63,7 +63,7 @@ protected override void ParseTemplateDefinition() base.ParseTemplateDefinition(); // parse all input parameters from the method signature - foreach (var parameter in this.Method.GetParameters()) + foreach (var parameter in this.Parameters) { var argTemplate = this.CreateArgument(parameter); argTemplate.Parse(); diff --git a/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiers.cs b/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiers.cs index f250ea2f0..818bd12ca 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiers.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiers.cs @@ -53,8 +53,13 @@ public enum GraphArgumentModifiers ExplicitSchemaItem, /// - /// This paraemter is declared to be resolved as the active resolution context being processed by a controller action. + /// This parameter is declared to be resolved as the active resolution context being processed by a controller action. /// ResolutionContext, + + /// + /// This parameter is declared to be resolved as the active http context responsible for the original query. + /// + HttpContext, } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiersExtensions.cs b/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiersExtensions.cs index af7b87597..a2e0f3993 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiersExtensions.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/GraphArgumentModifiersExtensions.cs @@ -79,5 +79,15 @@ public static bool IsInjected(this GraphArgumentModifiers modifier) { return modifier == GraphArgumentModifiers.ExplicitInjected; } + + /// + /// Determines whether the modifier indicate that the argument is to be populated with the http context for the request. + /// + /// The modifier to check. + /// true if the parameters represent the global http context for the request; otherwise, false. + public static bool IsHttpContext(this GraphArgumentModifiers modifier) + { + return modifier == GraphArgumentModifiers.HttpContext; + } } } \ No newline at end of file diff --git a/src/graphql-aspnet/ServerExtensions/MultipartRequests/Model/FileUpload.cs b/src/graphql-aspnet/ServerExtensions/MultipartRequests/Model/FileUpload.cs index caafd83f4..d24e20987 100644 --- a/src/graphql-aspnet/ServerExtensions/MultipartRequests/Model/FileUpload.cs +++ b/src/graphql-aspnet/ServerExtensions/MultipartRequests/Model/FileUpload.cs @@ -15,7 +15,6 @@ namespace GraphQL.AspNet.ServerExtensions.MultipartRequests.Model using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Common; using GraphQL.AspNet.ServerExtensions.MultipartRequests.Interfaces; - using GraphQL.AspNet.ServerExtensions.MultipartRequests.Schema; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Primitives; @@ -27,7 +26,6 @@ namespace GraphQL.AspNet.ServerExtensions.MultipartRequests.Model /// will result in a schema failure. This class cannot be used as a regular INPUT_OBJECT. See documentation /// for details. /// - [GraphSkip] [GraphType(PreventAutoInclusion = true)] public class FileUpload { diff --git a/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/QueryContextBuilder.cs b/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/QueryContextBuilder.cs index 386ed7354..3941b9498 100644 --- a/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/QueryContextBuilder.cs +++ b/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/QueryContextBuilder.cs @@ -32,9 +32,9 @@ namespace GraphQL.AspNet.Tests.Framework.PipelineContextBuilders public class QueryContextBuilder { private readonly IServiceProvider _serviceProvider; - private readonly Mock _mockRequest; private readonly List> _sourceData; + private Mock _mockRequest; private IUserSecurityContext _userSecurityContext; private IQueryExecutionMetrics _metrics; private IGraphEventLogger _eventLogger; @@ -149,11 +149,11 @@ public virtual QueryExecutionContext Build() // updateable items about the request var context = new QueryExecutionContext( - this.QueryRequest, + this.QueryRequest.Object, _serviceProvider, new QuerySession(), securityContext: _userSecurityContext, - items: this.QueryRequest.Items, + items: this.QueryRequest.Object.Items, metrics: _metrics, logger: _eventLogger); @@ -169,9 +169,13 @@ public virtual QueryExecutionContext Build() } /// - /// Gets the mocked request as its currently defined by this builder. + /// Gets or sets the mocked request as its currently defined by this builder. /// /// The request. - public IQueryExecutionRequest QueryRequest => _mockRequest.Object; + public Mock QueryRequest + { + get { return _mockRequest; } + set { _mockRequest = value; } + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/DefaultGraphResponseWriterTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/DefaultGraphResponseWriterTests.cs index 2713810cf..41c7812d3 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/DefaultGraphResponseWriterTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/DefaultGraphResponseWriterTests.cs @@ -266,7 +266,7 @@ public async Task EnsureProperStringEscapement(string testValue, string expected var mockResult = new Mock(); mockResult.Setup(x => x.Data).Returns(dic); mockResult.Setup(x => x.Messages).Returns(new GraphMessageCollection()); - mockResult.Setup(x => x.QueryRequest).Returns(queryBuilder.QueryRequest); + mockResult.Setup(x => x.QueryRequest).Returns(queryBuilder.QueryRequest.Object); var writer = new DefaultQueryResponseWriter(server.Schema); var result = await this.WriteResponse(writer, mockResult.Object); diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeDirectiveTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeDirectiveTests.cs index 5be47781f..b4807b935 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeDirectiveTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeDirectiveTests.cs @@ -16,6 +16,7 @@ namespace GraphQL.AspNet.Tests.Execution using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Controllers.ActionResults; using GraphQL.AspNet.Execution; + using GraphQL.AspNet.Execution.Contexts; using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Tests.Common.CommonHelpers; @@ -291,5 +292,115 @@ public async Task Runtime_ExecutionDirective_WithSecurityParams_AndUnAuthorizedU Assert.AreEqual(GraphMessageSeverity.Critical, result.Messages[0].Severity); Assert.AreEqual(Constants.ErrorCodes.ACCESS_DENIED, result.Messages[0].Code); } + + [Test] + public async Task Runtime_ExecutionDirective_WithDirectiveContext_SuppliesContextToDirectiveCorrect() + { + var serverBuilder = new TestServerBuilder(); + + serverBuilder.AddGraphQL(o => + { + o.MapQuery("field", () => 3); + + o.MapDirective("@injectedContext") + .RestrictLocations(DirectiveLocation.FIELD) + .AddResolver((DirectiveResolutionContext context) => + { + if (context != null) + _values["directiveResolutionContext0"] = 1; + + return GraphActionResult.Ok(); + }); + }); + + var server = serverBuilder.Build(); + + var builder = server.CreateQueryContextBuilder(); + builder.AddQueryText(@"query { field @injectedContext }"); + + var result = await server.RenderResult(builder); + + Assert.IsTrue(_values.ContainsKey("directiveResolutionContext0")); + CommonAssertions.AreEqualJsonStrings( + @"{ + ""data"": { + ""field"": 3 + } + }", + result); + } + + [Test] + public async Task Runtime_ExecutionDirective_WithFieldResolutionContext_ThrowsException() + { + var serverBuilder = new TestServerBuilder(); + + serverBuilder.AddGraphQL(o => + { + o.MapQuery("field", () => 3); + + o.MapDirective("@injectedContext") + .RestrictLocations(DirectiveLocation.FIELD) + .AddResolver((FieldResolutionContext context) => + { + if (context != null) + _values["directiveResolutionContext1"] = 1; + + return GraphActionResult.Ok(); + }); + }); + + var server = serverBuilder.Build(); + + var builder = server.CreateQueryContextBuilder(); + builder.AddQueryText(@"query { field @injectedContext }"); + + var result = await server.ExecuteQuery(builder); + + Assert.IsFalse(_values.ContainsKey("directiveResolutionContext1")); + + Assert.AreEqual(1, result.Messages.Count); + Assert.AreEqual(Constants.ErrorCodes.INTERNAL_SERVER_ERROR, result.Messages[0].Code); + Assert.AreEqual(typeof(GraphExecutionException), result.Messages[0].Exception.GetType()); + + Assert.IsTrue(result.Messages[0].Exception.Message.Contains(nameof(FieldResolutionContext))); + } + + [Test] + public async Task Runtime_ExecutionDirective_WithMultipleDirectiveContext_SuppliesContextToDirectiveCorrect() + { + var serverBuilder = new TestServerBuilder(); + + serverBuilder.AddGraphQL(o => + { + o.MapQuery("field", () => 3); + + o.MapDirective("@injectedContext") + .RestrictLocations(DirectiveLocation.FIELD) + .AddResolver((DirectiveResolutionContext context, DirectiveResolutionContext context1) => + { + if (context != null && context == context1) + _values["directiveResolutionContext2"] = 1; + + return GraphActionResult.Ok(); + }); + }); + + var server = serverBuilder.Build(); + + var builder = server.CreateQueryContextBuilder(); + builder.AddQueryText(@"query { field @injectedContext }"); + + var result = await server.RenderResult(builder); + + Assert.IsTrue(_values.ContainsKey("directiveResolutionContext2")); + CommonAssertions.AreEqualJsonStrings( + @"{ + ""data"": { + ""field"": 3 + } + }", + result); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeFieldTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeFieldTests.cs index 05cfd4f2a..0af778e90 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeFieldTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeFieldTests.cs @@ -16,13 +16,17 @@ namespace GraphQL.AspNet.Tests.Execution using GraphQL.AspNet.Controllers.ActionResults; using GraphQL.AspNet.Execution; using GraphQL.AspNet.Execution.Contexts; + using GraphQL.AspNet.Execution.Exceptions; + using GraphQL.AspNet.Interfaces.Web; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Execution.TestData.RuntimeFieldTest; using GraphQL.AspNet.Tests.Execution.TestData.RuntimeFieldTestData; using GraphQL.AspNet.Tests.Framework; + using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.DependencyInjection; + using Moq; using NUnit.Framework; [TestFixture] @@ -594,7 +598,7 @@ public async Task Runtime_StandardField_FieldResolutionContext_IsInjected_WhenRe { o.MapQuery("field", (FieldResolutionContext context) => { - if (context != null && context.Request.Field != null) + if (context?.Request?.Field != null && context.Request.Field.Name == "field") return 1; return 0; @@ -615,5 +619,96 @@ public async Task Runtime_StandardField_FieldResolutionContext_IsInjected_WhenRe }", result); } + + [Test] + public async Task Runtime_StandardField_FieldResolutionContext_WhenSuppliedMultipleTimes_IsInjected_WhenRequested() + { + var serverBuilder = new TestServerBuilder(); + + serverBuilder.AddGraphQL(o => + { + o.MapQuery("field", (FieldResolutionContext context, FieldResolutionContext context1) => + { + if (context != null && context == context1) + return 1; + + return 0; + }); + }); + + var server = serverBuilder.Build(); + + var builder = server.CreateQueryContextBuilder(); + builder.AddQueryText(@"query { field }"); + + var result = await server.RenderResult(builder); + CommonAssertions.AreEqualJsonStrings( + @"{ + ""data"": { + ""field"": 1 + } + }", + result); + } + + [Test] + public async Task Runtime_StandardField_SupplyingADirectiveResolutionContext_WithoutDefaultValue_ThrowsException() + { + var serverBuilder = new TestServerBuilder(TestOptions.IncludeExceptions); + + // TODO: Read https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/lambda-method-group-defaults + serverBuilder.AddGraphQL(o => + { + o.MapQuery("field", (DirectiveResolutionContext context) => + { + return 0; + }); + }); + + var server = serverBuilder.Build(); + + var builder = server.CreateQueryContextBuilder(); + builder.AddQueryText(@"query { field }"); + + var result = await server.ExecuteQuery(builder); + Assert.AreEqual(1, result.Messages.Count); + Assert.AreEqual(Constants.ErrorCodes.INTERNAL_SERVER_ERROR, result.Messages[0].Code); + Assert.AreEqual(typeof(GraphExecutionException), result.Messages[0].Exception.GetType()); + + Assert.IsTrue(result.Messages[0].Exception.Message.Contains(nameof(DirectiveResolutionContext))); + } + + [Test] + public async Task Runtime_StandardField_HttpContext_WhenNotSupplied_ReturnsNull_WhenRulesSetToNullableItems() + { + var serverBuilder = new TestServerBuilder(); + + serverBuilder.AddGraphQL(o => + { + o.ExecutionOptions.ResolverParameterResolutionRule = ResolverParameterResolutionRules.UseNullorDefault; + + o.MapQuery("field", (HttpContext context) => + { + if (context != null) + return 1; + + return 0; + }); + }); + + var server = serverBuilder.Build(); + + var builder = server.CreateQueryContextBuilder(); + builder.AddQueryText(@"query { field }"); + + var result = await server.RenderResult(builder); + CommonAssertions.AreEqualJsonStrings( + @"{ + ""data"": { + ""field"": 0 + } + }", + result); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Logging/GeneralEventLogEntryPropertyChecks.cs b/src/unit-tests/graphql-aspnet-tests/Logging/GeneralEventLogEntryPropertyChecks.cs index ce4488f7c..b476b2830 100644 --- a/src/unit-tests/graphql-aspnet-tests/Logging/GeneralEventLogEntryPropertyChecks.cs +++ b/src/unit-tests/graphql-aspnet-tests/Logging/GeneralEventLogEntryPropertyChecks.cs @@ -131,7 +131,7 @@ public void RequestReceivedLogEntry() var builder = server.CreateQueryContextBuilder(); builder.AddQueryText("{ testField }"); - var request = builder.QueryRequest; + var request = builder.QueryRequest.Object; var context = builder.Build(); var entry = new RequestReceivedLogEntry(context); @@ -153,7 +153,7 @@ public void RequestCompletedLogEntry() var builder = server.CreateQueryContextBuilder(); builder.AddQueryText("{ testField }"); - var request = builder.QueryRequest; + var request = builder.QueryRequest.Object; var context = builder.Build(); var mock = new Mock(); diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ArgumentTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ArgumentTemplateTests.cs index 3c364133c..84d6f73b8 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ArgumentTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ArgumentTemplateTests.cs @@ -316,5 +316,23 @@ public void ArgumentAttributedasFromGraphQLAndFromServices_ThrowsException() var template = this.ExtractParameterTemplate("doubleDeclaredObject", out var paramInfo); }); } + + [Test] + public void ArgumentAttributedasGraphSkip_ThrowsException() + { + Assert.Throws(() => + { + var template = this.ExtractParameterTemplate("graphSkipArgument", out var paramInfo); + }); + } + + [Test] + public void ArgumentTypeAttributedasGraphSkip_ThrowsException() + { + Assert.Throws(() => + { + var template = this.ExtractParameterTemplate("typeHasGraphSkip", out var paramInfo); + }); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ParameterTestData/ObjectWithGraphSkip.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ParameterTestData/ObjectWithGraphSkip.cs new file mode 100644 index 000000000..38411ec83 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ParameterTestData/ObjectWithGraphSkip.cs @@ -0,0 +1,19 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ParameterTestData +{ + using GraphQL.AspNet.Attributes; + + [GraphSkip] + public class ObjectWithGraphSkip + { + public int Property1 { get; set; } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ParameterTestData/ParameterTestClass.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ParameterTestData/ParameterTestClass.cs index 8cb2b362e..d1b2c52a5 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ParameterTestData/ParameterTestClass.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ParameterTestData/ParameterTestClass.cs @@ -43,6 +43,8 @@ public int TestMethod( IEnumerable[] arrayOfEnumerableOfArrayOfObjects, Person[][][][][][][][][][][][][][][][][][][] deepArray, [FromGraphQL(TypeExpression = "[Type!")] int invalidTypeExpression, + [GraphSkip] Person graphSkipArgument, + ObjectWithGraphSkip typeHasGraphSkip, [FromGraphQL(TypeExpression = "Type!")] int? compatiableTypeExpressionSingle, // add more specificity [FromGraphQL(TypeExpression = "[Type!]!")] int?[] compatiableTypeExpressionList, // add more specificity [FromGraphQL(TypeExpression = "[Type]")] int incompatiableTypeExpressionListToSingle, diff --git a/src/unit-tests/graphql-aspnet-tests/Web/HttpContextInjectionTests.cs b/src/unit-tests/graphql-aspnet-tests/Web/HttpContextInjectionTests.cs new file mode 100644 index 000000000..83dff0e1d --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Web/HttpContextInjectionTests.cs @@ -0,0 +1,88 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Web +{ + using System.IO; + using System.Threading.Tasks; + using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Engine; + using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + using GraphQL.AspNet.Tests.Framework; + using GraphQL.AspNet.Tests.Web.CancelTokenTestData; + using Microsoft.AspNetCore.Http; + using Microsoft.Extensions.DependencyInjection; + using NUnit.Framework; + + [TestFixture] + public class HttpContextInjectionTests + { + [Test] + public async Task WhenHttpContextIsFound_ItsInjectedAsExpected() + { + DefaultHttpContext httpContext = null; + var serverBuilder = new TestServerBuilder(); + serverBuilder.AddGraphController(); + serverBuilder.AddTransient>(); + serverBuilder.AddGraphQL((o) => + { + o.ExecutionOptions.QueryTimeout = null; + o.MapQuery("field", (HttpContext context) => + { + if (context != null + && context.Items.ContainsKey("Test1") + && context.Items["Test1"].ToString() == "Value1") + { + return 1; + } + + return 0; + }); + }); + + var server = serverBuilder.Build(); + + using var scope = server.ServiceProvider.CreateScope(); + var processor = scope.ServiceProvider.GetRequiredService>(); + + httpContext = new DefaultHttpContext() + { + Response = + { + Body = new MemoryStream(), + }, + RequestServices = scope.ServiceProvider, + }; + + var request = httpContext.Request; + request.Method = "GET"; + request.QueryString = new QueryString("?query=query { field }"); + + httpContext.Items.Add("Test1", "Value1"); + + await processor.InvokeAsync(httpContext); + await httpContext.Response.Body.FlushAsync(); + + httpContext.Response.Body.Seek(0, SeekOrigin.Begin); + var reader = new StreamReader(httpContext.Response.Body); + var text = reader.ReadToEnd(); + + var expectedResult = @" + { + ""data"" : { + ""field"" : 1 + } + }"; + + CommonAssertions.AreEqualJsonStrings(expectedResult, text); + Assert.AreEqual(200, httpContext.Response.StatusCode); + } + } +} \ No newline at end of file From 2cbc445dcac70a924ea90b71e63fb9bb3f85a504 Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Sat, 22 Jul 2023 08:57:04 -0700 Subject: [PATCH 44/63] WIP, cleaned up InternalName properties and separated it from indexable values --- ...ptionControllerActionGraphFieldTemplate.cs | 8 +-- .../SubscriptionMethodGraphField.cs | 2 +- .../Attributes/FromGraphQLAttribute.cs | 10 ++++ .../Attributes/GraphEnumValueAttribute.cs | 9 ++++ .../Attributes/GraphFieldAttribute.cs | 23 ++++++--- .../Attributes/GraphTypeAttribute.cs | 10 ++++ .../SchemaItemFilterExtensions.cs | 2 +- .../InternalServerErrorGraphActionResult.cs | 2 +- .../RouteNotFoundGraphActionResult.cs | 43 +++++++++------- ...DefaultGraphQLSchemaFactory_Controllers.cs | 4 +- .../Execution/ExecutionArgumentCollection.cs | 18 +++---- .../Resolvers/FieldResolverMetaData.cs | 15 +----- .../FieldResolverParameterMetaData.cs | 14 ++--- .../Resolvers/GraphDirectiveActionResolver.cs | 2 +- .../Resolvers/InputObjectValueResolver.cs | 2 +- .../InternalFieldResolverMetaData.cs | 4 +- .../ObjectMethodGraphFieldResolver.cs | 2 +- .../ObjectPropertyGraphFieldResolver.cs | 4 +- .../Execution/IGraphFieldResolverMetaData.cs | 16 +----- .../IGraphFieldResolverParameterMetaData.cs | 18 +++---- .../Interfaces/Internal/IEnumValueTemplate.cs | 6 +++ .../Internal/ISchemaItemTemplate.cs | 9 +--- .../Interfaces/Schema/IEnumValue.cs | 14 +++-- .../Interfaces/Schema/ITypedSchemaItem.cs | 10 ++-- .../ActionMethodExceptionLogEntryBase.cs | 2 +- ...ActionMethodInvocationCompletedLogEntry.cs | 2 +- .../ActionMethodInvocationStartedLogEntry.cs | 2 +- ...ActionMethodModelStateValidatedLogEntry.cs | 2 +- .../ExecutionDirectiveAppliedLogEntry.cs | 2 +- .../TypeSystemDirectiveAppliedLogEntry.cs | 2 +- .../TypeMakers/EnumGraphTypeMaker.cs | 1 + .../TypeMakers/GraphArgumentMaker.cs | 2 +- .../Generation/TypeMakers/GraphFieldMaker.cs | 51 +++++++++++++++++-- .../ControllerActionGraphFieldTemplate.cs | 2 +- .../TypeTemplates/EnumGraphTypeTemplate.cs | 6 --- .../TypeTemplates/EnumValueTemplate.cs | 18 +++++-- .../TypeTemplates/GraphArgumentTemplate.cs | 32 +++++++----- .../GraphDirectiveMethodTemplate.cs | 25 +++++---- .../GraphDirectiveMethodTemplateContainer.cs | 4 +- .../TypeTemplates/GraphDirectiveTemplate.cs | 10 +--- .../TypeTemplates/GraphFieldTemplateBase.cs | 30 +++++------ .../GraphTypeExtensionFieldTemplate.cs | 6 +-- .../TypeTemplates/GraphTypeTemplateBase.cs | 10 ++-- .../TypeTemplates/InputGraphFieldTemplate.cs | 29 +++++------ .../InputObjectGraphTypeTemplate.cs | 10 +--- .../TypeTemplates/MethodGraphFieldTemplate.cs | 4 +- .../MethodGraphFieldTemplateBase.cs | 21 ++++---- .../NonLeafGraphTypeTemplateBase.cs | 10 +--- .../PropertyGraphFieldTemplate.cs | 25 +++++---- .../TypeTemplates/ScalarGraphTypeTemplate.cs | 11 ++-- .../TypeTemplates/SchemaItemTemplateBase.cs | 18 ++++--- .../TypeTemplates/UnionGraphTypeTemplate.cs | 15 +++--- .../Schemas/SchemaLanguageGenerator.cs | 4 +- .../Schemas/Structural/EnumValueCollection.cs | 16 +++--- .../Schemas/TypeSystem/Directive.cs | 4 +- .../Schemas/TypeSystem/EnumGraphType.cs | 4 +- .../Schemas/TypeSystem/EnumValue.cs | 19 ++++--- .../Schemas/TypeSystem/GraphFieldArgument.cs | 6 +-- .../Schemas/TypeSystem/GraphOperation.cs | 2 +- .../Schemas/TypeSystem/InputGraphField.cs | 4 +- .../TypeSystem/InputObjectGraphType.cs | 4 +- .../Schemas/TypeSystem/InterfaceGraphType.cs | 4 +- .../BaseIntrospectionObjectType.cs | 2 +- .../Introspection_DirectiveLocationType.cs | 1 + .../Introspection_TypeKindType.cs | 1 + .../Schemas/TypeSystem/MethodGraphField.cs | 6 +-- .../Schemas/TypeSystem/ObjectGraphType.cs | 4 +- .../Schemas/TypeSystem/PropertyGraphField.cs | 2 +- .../TypeSystem/Scalars/ScalarGraphTypeBase.cs | 4 +- .../Schemas/TypeSystem/VirtualGraphField.cs | 4 +- .../TypeSystem/VirtualGraphFieldArgument.cs | 4 +- .../TypeSystem/VirtualObjectGraphType.cs | 2 +- ...SubscriptionEnabledFieldFieldMakerTests.cs | 2 +- .../Templating/GraphActionTemplateTests.cs | 4 +- .../GraphQLTemplateHelper.cs | 2 +- .../DirectiveContextBuilder.cs | 2 - .../FieldContextBuilder.cs | 2 - .../ActionResults/ActionResultTests.cs | 12 +++-- .../ScalarTestBase.cs | 4 +- .../Execution/IntrospectionTests.cs | 2 +- ...nMethodModelStateValidatedLogEntryTests.cs | 6 +-- .../GeneralEventLogEntryPropertyChecks.cs | 27 +++++----- .../Schemas/EnumValueCollectionTests.cs | 36 ++++++------- .../TypeMakers/FieldMaker_InputFieldTests.cs | 16 +++--- .../FieldMaker_StandardFieldTests.cs | 12 ++--- .../ActionMethodTemplateTests.cs | 4 +- .../AppliedDirectiveTemplateTests.cs | 10 ++-- .../TypeTemplates/ArgumentTemplateTests.cs | 7 +-- .../DirectiveMethodTemplateTests.cs | 10 ++-- .../TypeTemplates/DirectiveTemplateTests.cs | 1 - .../InputGraphFieldTemplateTests.cs | 22 ++++---- .../TypeTemplates/InputObjectTemplateTests.cs | 1 - .../MethodGraphFieldTemplateTests.cs | 14 ++--- .../ObjectGraphTypeTemplateTests.cs | 8 +-- .../PropertyGraphFieldTemplateTests.cs | 28 +++++----- .../ScalarGraphTypeTemplateTests.cs | 3 +- .../ScalarTestData/MyTestScalar.cs | 4 +- .../TypeExtensionFieldTemplateTests.cs | 8 +-- .../UnionGraphTypeTemplateTests.cs | 3 +- .../InvalidParentAppliedDirectivesScalar.cs | 2 +- .../GlobalTypesTestData/NoObjectTypeScalar.cs | 2 +- .../NoSourceResolverScalar.cs | 2 +- .../GlobalTypesTestData/NoValueTypeScalar.cs | 2 +- .../NotScalarKindScalar.cs | 2 +- .../NullAppliedDirectivesScalar.cs | 2 +- .../ObjectTypeIsNullableScalar.cs | 2 +- .../Schemas/GraphFieldArgumentCloningTests.cs | 2 +- .../Schemas/GraphFieldCloningTests.cs | 4 +- ...CollectionInterefaceImplementationTests.cs | 9 ++-- 109 files changed, 532 insertions(+), 443 deletions(-) diff --git a/src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionControllerActionGraphFieldTemplate.cs b/src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionControllerActionGraphFieldTemplate.cs index 3d6efab44..b1776d01e 100644 --- a/src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionControllerActionGraphFieldTemplate.cs +++ b/src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionControllerActionGraphFieldTemplate.cs @@ -99,14 +99,14 @@ public override void ValidateOrThrow() if (string.IsNullOrWhiteSpace(this.EventName)) { throw new GraphTypeDeclarationException( - $"Invalid subscription action declaration. The method '{this.InternalFullName}' does not " + + $"Invalid subscription action declaration. The method '{this.InternalName}' does not " + $"have an event name."); } if (!Constants.RegExPatterns.NameRegex.IsMatch(this.EventName)) { throw new GraphTypeDeclarationException( - $"Invalid subscription action declaration. The method '{this.InternalFullName}' declares " + + $"Invalid subscription action declaration. The method '{this.InternalName}' declares " + $"a custom event name of '{this.EventName}'. However, the event name must conform to " + $"standard graphql naming rules. (Regex: {Constants.RegExPatterns.NameRegex} )"); } @@ -115,7 +115,7 @@ public override void ValidateOrThrow() if (this.Method.GetParameters().Where(x => x.HasAttribute()).Count() > 1) { throw new GraphTypeDeclarationException( - $"Invalid subscription action declaration. The method '{this.InternalFullName}' decorates more" + + $"Invalid subscription action declaration. The method '{this.InternalName}' decorates more" + $"than one parameter with {typeof(SubscriptionSourceAttribute).FriendlyName()}. At most one parameter " + $"can be attributed with {typeof(SubscriptionSourceAttribute).FriendlyName()}"); } @@ -125,7 +125,7 @@ public override void ValidateOrThrow() if (sourceArgument == null) { throw new GraphTypeDeclarationException( - $"Invalid subscription action declaration. The method '{this.InternalFullName}' must " + + $"Invalid subscription action declaration. The method '{this.InternalName}' must " + $"declare 1 (and only 1) parameter of type '{this.SourceObjectType.FriendlyName()}' which will be populated" + "with the source data raised by a subscription event at runtime. Alternately use " + $"{typeof(SubscriptionSourceAttribute).FriendlyName()} to explicitly assign a source data parameter."); diff --git a/src/graphql-aspnet-subscriptions/Schemas/TypeSystem/SubscriptionMethodGraphField.cs b/src/graphql-aspnet-subscriptions/Schemas/TypeSystem/SubscriptionMethodGraphField.cs index d4d10764c..bc7fa6903 100644 --- a/src/graphql-aspnet-subscriptions/Schemas/TypeSystem/SubscriptionMethodGraphField.cs +++ b/src/graphql-aspnet-subscriptions/Schemas/TypeSystem/SubscriptionMethodGraphField.cs @@ -60,7 +60,7 @@ protected override MethodGraphField CreateNewInstance(IGraphType parent) this.Name, this.TypeExpression.Clone(), parent.Route.CreateChild(this.Name), - this.InternalFullName, + this.InternalName, this.ObjectType, this.DeclaredReturnType, this.Mode, diff --git a/src/graphql-aspnet/Attributes/FromGraphQLAttribute.cs b/src/graphql-aspnet/Attributes/FromGraphQLAttribute.cs index 6299ce590..f2333608a 100644 --- a/src/graphql-aspnet/Attributes/FromGraphQLAttribute.cs +++ b/src/graphql-aspnet/Attributes/FromGraphQLAttribute.cs @@ -59,5 +59,15 @@ public FromGraphQLAttribute(string argumentName) /// /// The type expression to assign to this argument. public string TypeExpression { get; set; } + + /// + /// Gets or sets a customized name to refer to this parameter in all log entries and error messages. + /// + /// + /// When not supplied the name defaults to a combination of the class + method + parameter naem. (e.g. 'MyObject.Method1.Param1'). This + /// can be especially helpful when working with runtime defined fields (e.g. minimal api). + /// + /// The name to refer to this parameter on internal messaging. + public string InternalName { get; set; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Attributes/GraphEnumValueAttribute.cs b/src/graphql-aspnet/Attributes/GraphEnumValueAttribute.cs index 15aa30d22..47dd61edd 100644 --- a/src/graphql-aspnet/Attributes/GraphEnumValueAttribute.cs +++ b/src/graphql-aspnet/Attributes/GraphEnumValueAttribute.cs @@ -40,5 +40,14 @@ public GraphEnumValueAttribute(string name) /// /// The name given to this enum value. public string Name { get; } + + /// + /// Gets or sets a customized name to refer to this .NET enum value in all log entries and error messages. + /// + /// + /// When not supplied the name defaults to the qualified name of the enum value. (e.g. 'MyEnum.Value1'). + /// + /// The name to refer to this enum value on internal messaging. + public string InternalName { get; set; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Attributes/GraphFieldAttribute.cs b/src/graphql-aspnet/Attributes/GraphFieldAttribute.cs index 8cbdf7224..44490e736 100644 --- a/src/graphql-aspnet/Attributes/GraphFieldAttribute.cs +++ b/src/graphql-aspnet/Attributes/GraphFieldAttribute.cs @@ -33,9 +33,10 @@ public GraphFieldAttribute() /// /// Initializes a new instance of the class. /// - /// Name of the field. - public GraphFieldAttribute(string name) - : this(false, SchemaItemCollections.Types, name) + /// The template naming scheme to use to generate a graph field from this method or property. The exact name may be altered on a per schema + /// basis depending on field name formatting rules etc. + public GraphFieldAttribute(string template) + : this(false, SchemaItemCollections.Types, template) { } @@ -97,14 +98,14 @@ protected GraphFieldAttribute( /// /// Gets the name of the union this field defines, if any. /// - /// The name of the union. + /// The name of the union type to create when multiple return types are possible. public string UnionTypeName { get; } /// /// Gets a value indicating whether this instance represents a template /// pathed from its root operation or if it is intended to be nested with another fragment. /// - /// true if this instance is root fragment; otherwise, false. + /// true if this instance is rooted to a top level operation; otherwise, false. public bool IsRootFragment { get; } /// @@ -145,7 +146,17 @@ protected GraphFieldAttribute( /// Gets the mode indicating how the runtime should process /// the objects resolving this field. /// - /// The mode. + /// The execution mode of this field when it is resolved by the runtime. public virtual FieldResolutionMode ExecutionMode => FieldResolutionMode.PerSourceItem; + + /// + /// Gets or sets a customized name to refer to this field in all log entries and error messages. + /// + /// + /// When not supplied the name defaults to the fully qualified method or property name. (e.g. 'MyObject.MyMethod'). This + /// can be especially helpful when working with runtime defined fields (e.g. minimal api). + /// + /// The name to refer to this field on internal messaging. + public string InternalName { get; set; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Attributes/GraphTypeAttribute.cs b/src/graphql-aspnet/Attributes/GraphTypeAttribute.cs index 1cba50fcf..bb043290b 100644 --- a/src/graphql-aspnet/Attributes/GraphTypeAttribute.cs +++ b/src/graphql-aspnet/Attributes/GraphTypeAttribute.cs @@ -111,5 +111,15 @@ public TemplateDeclarationRequirements FieldDeclarationRequirements /// /// true if publish; otherwise, false. public bool Publish { get; set; } + + /// + /// Gets or sets a customized name to refer to this .NET type in all log entries and error messages. + /// + /// + /// When not supplied the name defaults to the fully qualified class, struct or primative name. (e.g. 'MyObject', 'Person'). This + /// can be especially helpful when working with runtime defined fields (e.g. minimal api). + /// + /// The name to refer to this field on internal messaging. + public string InternalName { get; set; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/SchemaItemFilterExtensions.cs b/src/graphql-aspnet/Configuration/SchemaItemFilterExtensions.cs index 6f9dca8d8..4cccdf188 100644 --- a/src/graphql-aspnet/Configuration/SchemaItemFilterExtensions.cs +++ b/src/graphql-aspnet/Configuration/SchemaItemFilterExtensions.cs @@ -209,7 +209,7 @@ public static bool IsEnumValue(this ISchemaItem schemaItem, TEnum enumVal return schemaItem != null && schemaItem is IEnumValue ev && ev.Parent.ObjectType == typeof(TEnum) - && Enum.Equals(ev.InternalValue, enumValue); + && Enum.Equals(ev.DeclaredValue, enumValue); } /// diff --git a/src/graphql-aspnet/Controllers/ActionResults/InternalServerErrorGraphActionResult.cs b/src/graphql-aspnet/Controllers/ActionResults/InternalServerErrorGraphActionResult.cs index a0631e70a..8352fcb30 100644 --- a/src/graphql-aspnet/Controllers/ActionResults/InternalServerErrorGraphActionResult.cs +++ b/src/graphql-aspnet/Controllers/ActionResults/InternalServerErrorGraphActionResult.cs @@ -59,7 +59,7 @@ public InternalServerErrorGraphActionResult(IGraphFieldResolverMetaData action, _exception = exception; if (_exception == null) - _exception = new Exception($"The action method '{action?.InternalFullName}' failed to complete successfully but did not record an exception."); + _exception = new Exception($"The action method '{action?.InternalName}' failed to complete successfully but did not record an exception."); } /// diff --git a/src/graphql-aspnet/Controllers/ActionResults/RouteNotFoundGraphActionResult.cs b/src/graphql-aspnet/Controllers/ActionResults/RouteNotFoundGraphActionResult.cs index 06d13ca8f..b5c404b5c 100644 --- a/src/graphql-aspnet/Controllers/ActionResults/RouteNotFoundGraphActionResult.cs +++ b/src/graphql-aspnet/Controllers/ActionResults/RouteNotFoundGraphActionResult.cs @@ -12,6 +12,7 @@ namespace GraphQL.AspNet.Controllers.ActionResults using System; using System.Threading.Tasks; using GraphQL.AspNet.Execution.Contexts; + using GraphQL.AspNet.Execution.RulesEngine.RuleSets.DocumentValidation.QueryFragmentSteps; using GraphQL.AspNet.Interfaces.Controllers; using GraphQL.AspNet.Interfaces.Execution; @@ -56,38 +57,44 @@ public RouteNotFoundGraphActionResult() /// public Task CompleteAsync(SchemaItemResolutionContext context) { - if (_invokeDef != null) - { - string fieldName; - if (context is FieldResolutionContext frc) - fieldName = frc.Request.Field.Route.Path; - else if (context is DirectiveResolutionContext drc) - fieldName = drc.Request.Directive.Route.Path; - else - fieldName = "-unknown-"; + context.Cancel(); + if (!string.IsNullOrWhiteSpace(_message)) + { context.Messages.Critical( - $"The field '{fieldName}' was not found or could not be invoked.", + _message, Constants.ErrorCodes.INVALID_ROUTE, - context.Request.Origin, - _thrownException); + context.Request.Origin); + + return Task.CompletedTask; } - else if (!string.IsNullOrWhiteSpace(_message)) + + string fieldName = context.Route?.Path; + if (string.IsNullOrWhiteSpace(fieldName)) + fieldName = "~Unknown~"; + + if (_invokeDef != null) { + var exception = new Exception( + $"The resolver '{_invokeDef.InternalName}' with {_invokeDef.Parameters.Count} was not invocable with the provided data on " + + $"the request.", + _thrownException); + context.Messages.Critical( - _message, + $"The field '{fieldName}' was not found or the resolver could not be invoked.", Constants.ErrorCodes.INVALID_ROUTE, - context.Request.Origin); + context.Request.Origin, + exception); } else { context.Messages.Critical( - "The item was not routable or otherwise not available.", + $"The field '{fieldName}' was not routable or otherwise not available.", Constants.ErrorCodes.INVALID_ROUTE, - context.Request.Origin); + context.Request.Origin, + _thrownException); } - context.Cancel(); return Task.CompletedTask; } diff --git a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Controllers.cs b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Controllers.cs index 137f006b1..2e58e1095 100644 --- a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Controllers.cs +++ b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_Controllers.cs @@ -76,7 +76,7 @@ protected virtual void AddAction(IGraphFieldTemplate action) { throw new ArgumentOutOfRangeException( nameof(action), - $"The '{action.InternalFullName}' action's operation root ({action.Route.RootCollection}) is not " + + $"The '{action.InternalName}' action's operation root ({action.Route.RootCollection}) is not " + $"allowed by the target schema (Name: {this.Schema.Name})."); } } @@ -228,7 +228,7 @@ protected virtual void AddActionAsField(IObjectGraphType parentType, IGraphField { throw new GraphTypeDeclarationException( $"The '{parentType.Kind}' graph type '{parentType.Name}' already contains a field named '{fieldResult.Field.Name}'. " + - $"The action method '{action.InternalFullName}' cannot be added to the graph type with the same name."); + $"The action method '{action.InternalName}' cannot be added to the graph type with the same name."); } parentType.Extend(fieldResult.Field); diff --git a/src/graphql-aspnet/Execution/ExecutionArgumentCollection.cs b/src/graphql-aspnet/Execution/ExecutionArgumentCollection.cs index 457195124..9ce93fb16 100644 --- a/src/graphql-aspnet/Execution/ExecutionArgumentCollection.cs +++ b/src/graphql-aspnet/Execution/ExecutionArgumentCollection.cs @@ -100,7 +100,7 @@ public object[] PrepareArguments(IGraphFieldResolverMetaData resolverMetadata) { var parameter = resolverMetadata.Parameters[i]; - object passedValue = this.ResolveParameterValue(parameter, resolverMetadata.InternalFullName); + object passedValue = this.ResolveParameterValue(parameter); // ensure compatible list types between the internally // tracked data and the target type of the method being invoked @@ -118,7 +118,7 @@ public object[] PrepareArguments(IGraphFieldResolverMetaData resolverMetadata) return preparedParams; } - private object ResolveParameterValue(IGraphFieldResolverParameterMetaData paramDef, string parentFullName) + private object ResolveParameterValue(IGraphFieldResolverParameterMetaData paramDef) { Validation.ThrowIfNull(paramDef, nameof(paramDef)); @@ -141,7 +141,7 @@ private object ResolveParameterValue(IGraphFieldResolverParameterMetaData paramD return this.CreateNullOrDefault(paramDef.ExpectedType); throw new GraphExecutionException( - $"The resolution context parameter '{paramDef.InternalName}' of type {paramDef.ExpectedType.FriendlyName()} for resolver '{parentFullName}' could not be resolved and " + + $"The resolution context parameter '{paramDef.InternalName}' of type {paramDef.ExpectedType.FriendlyName()} for resolver '{paramDef.ParentInternalName}' could not be resolved and " + $"does not declare a default value. Unable to complete the request."); } @@ -158,12 +158,12 @@ private object ResolveParameterValue(IGraphFieldResolverParameterMetaData paramD return this.CreateNullOrDefault(paramDef.ExpectedType); throw new GraphExecutionException( - $"The http context parameter '{paramDef.InternalName}' of type {paramDef.ExpectedType.FriendlyName()} for resolver '{parentFullName}' could not be resolved and " + + $"The http context parameter '{paramDef.InternalName}' of type {paramDef.ExpectedType.FriendlyName()} for resolver '{paramDef.ParentInternalName}' could not be resolved and " + $"does not declare a default value. Unable to complete the request."); } // if there an argument supplied on the query for this parameter, use that - if (this.TryGetValue(paramDef.InternalName, out var arg)) + if (this.TryGetValue(paramDef.ParameterInfo.Name, out var arg)) return arg.Value; // if the parameter is part of the graph, use the related argument's default value @@ -173,7 +173,7 @@ private object ResolveParameterValue(IGraphFieldResolverParameterMetaData paramD // supplied from a query var graphArgument = _resolutionContext? .SchemaDefinedArguments? - .FindArgumentByParameterName(paramDef.InternalName); + .FindArgumentByParameterName(paramDef.ParameterInfo.Name); if (graphArgument != null) { @@ -216,12 +216,12 @@ private object ResolveParameterValue(IGraphFieldResolverParameterMetaData paramD if (_resolutionContext != null && _resolutionContext.Schema.Configuration.ExecutionOptions.ResolverParameterResolutionRule == Configuration.ResolverParameterResolutionRules.UseNullorDefault) return this.CreateNullOrDefault(paramDef.ExpectedType); - var schemaItem = _resolutionContext?.Route.Path - ?? paramDef.InternalFullName; + var schemaItemName = _resolutionContext?.Route.Path + ?? paramDef.InternalName; // error unable to resolve correctly. *womp womp* throw new GraphExecutionException( - $"The parameter '{paramDef.InternalName}' targeting '{schemaItem}' was expected to be resolved from a " + + $"The parameter '{paramDef.InternalName}' targeting '{schemaItemName}' was expected to be resolved from a " + $"service provider but a suitable instance could not be obtained from the current invocation context " + $"and no default value was declared."); } diff --git a/src/graphql-aspnet/Execution/Resolvers/FieldResolverMetaData.cs b/src/graphql-aspnet/Execution/Resolvers/FieldResolverMetaData.cs index 61d620d49..ab77f110a 100644 --- a/src/graphql-aspnet/Execution/Resolvers/FieldResolverMetaData.cs +++ b/src/graphql-aspnet/Execution/Resolvers/FieldResolverMetaData.cs @@ -31,21 +31,16 @@ internal class FieldResolverMetaData : IGraphFieldResolverMetaData /// from concrete return types (e.g. expecting an interface but actually returning a concrete type that implements that interface). /// if set to true the invoked method is asyncronous. /// The name of the resolver method or property as it exists in source code. - /// the full name of the resolver method or propert, with namespace and parent owning class, - /// as it exists in source code. /// The type of the .NET class or struct where the resolver method is declared. /// The name of the .NET class or struct where the resolver method is declared. - /// The full name of the .NET class or struct, including namespace, where the resolver method is declared. public FieldResolverMetaData( MethodInfo method, IGraphFieldResolverParameterMetaDataCollection parameters, Type expectedReturnType, bool isAsyncField, string internalName, - string internalFullName, Type parentObjectType, - string parentInternalName, - string parentInternalFullName) + string parentInternalName) { this.Method = Validation.ThrowIfNullOrReturn(method, nameof(method)); @@ -55,11 +50,9 @@ public FieldResolverMetaData( this.Parameters = Validation.ThrowIfNullOrReturn(parameters, nameof(parameters)); this.InternalName = Validation.ThrowIfNullWhiteSpaceOrReturn(internalName, nameof(internalName)); - this.InternalFullName = Validation.ThrowIfNullWhiteSpaceOrReturn(internalFullName, nameof(internalFullName)); this.ParentObjectType = Validation.ThrowIfNullOrReturn(parentObjectType, nameof(parentObjectType)); this.ParentInternalName = Validation.ThrowIfNullWhiteSpaceOrReturn(parentInternalName, nameof(parentInternalName)); - this.ParentInternalFullName = Validation.ThrowIfNullWhiteSpaceOrReturn(parentInternalFullName, nameof(parentInternalFullName)); } /// @@ -71,9 +64,6 @@ public FieldResolverMetaData( /// public bool IsAsyncField { get; } - /// - public string InternalFullName { get; } - /// public string InternalName { get; } @@ -83,9 +73,6 @@ public FieldResolverMetaData( /// public string ParentInternalName { get; } - /// - public string ParentInternalFullName { get; } - /// public Type ParentObjectType { get; } } diff --git a/src/graphql-aspnet/Execution/Resolvers/FieldResolverParameterMetaData.cs b/src/graphql-aspnet/Execution/Resolvers/FieldResolverParameterMetaData.cs index 4e10ab26c..43dd49547 100644 --- a/src/graphql-aspnet/Execution/Resolvers/FieldResolverParameterMetaData.cs +++ b/src/graphql-aspnet/Execution/Resolvers/FieldResolverParameterMetaData.cs @@ -28,8 +28,8 @@ internal class FieldResolverParameterMetaData : IGraphFieldResolverParameterMeta /// Initializes a new instance of the class. /// /// The parameter info for a single parameter within a resolver method. - /// The name of the parameter as its declared in source code. - /// The full name of the parameter, including namespace, owning object and declared method, as it exists in source code. + /// The internal name of the parameter as its declared in source code. + /// The internal name of the parent method that owns this parameter. /// Any modifier attributes for this parameter discovered via templating or set /// at runtime by the target schema. /// if set to true this parameter is expecting a list @@ -40,7 +40,7 @@ internal class FieldResolverParameterMetaData : IGraphFieldResolverParameterMeta public FieldResolverParameterMetaData( ParameterInfo paramInfo, string internalName, - string internalFullName, + string parentInternalName, GraphArgumentModifiers modifiers, bool isListBasedParameter, bool hasDefaultValue, @@ -54,8 +54,8 @@ public FieldResolverParameterMetaData( eliminateTask: true, eliminateNullableT: false); + this.ParentInternalName = Validation.ThrowIfNullWhiteSpaceOrReturn(parentInternalName, nameof(parentInternalName)); this.InternalName = Validation.ThrowIfNullWhiteSpaceOrReturn(internalName, nameof(internalName)); - this.InternalFullName = Validation.ThrowIfNullWhiteSpaceOrReturn(internalFullName, nameof(internalFullName)); this.DefaultValue = defaultValue; this.ArgumentModifiers = modifiers; this.HasDefaultValue = hasDefaultValue; @@ -65,9 +65,6 @@ public FieldResolverParameterMetaData( /// public ParameterInfo ParameterInfo { get; } - /// - public string InternalFullName { get; } - /// public string InternalName { get; } @@ -88,5 +85,8 @@ public FieldResolverParameterMetaData( /// public bool HasDefaultValue { get; } + + /// + public string ParentInternalName { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Execution/Resolvers/GraphDirectiveActionResolver.cs b/src/graphql-aspnet/Execution/Resolvers/GraphDirectiveActionResolver.cs index 821b154bc..51777679d 100644 --- a/src/graphql-aspnet/Execution/Resolvers/GraphDirectiveActionResolver.cs +++ b/src/graphql-aspnet/Execution/Resolvers/GraphDirectiveActionResolver.cs @@ -73,7 +73,7 @@ public async Task ResolveAsync(DirectiveResolutionContext context, CancellationT if (directive == null) { result = new RouteNotFoundGraphActionResult( - $"The directive '{action.InternalFullName}' " + + $"The directive '{action.InternalName}' " + "was not found in the scoped service provider. Any directives that have constructor parameters " + $"must also be registered to the service provider; Try using '{nameof(SchemaOptions.AddGraphType)}' " + $"with the type of your directive at startup."); diff --git a/src/graphql-aspnet/Execution/Resolvers/InputObjectValueResolver.cs b/src/graphql-aspnet/Execution/Resolvers/InputObjectValueResolver.cs index d792da957..d06d04939 100644 --- a/src/graphql-aspnet/Execution/Resolvers/InputObjectValueResolver.cs +++ b/src/graphql-aspnet/Execution/Resolvers/InputObjectValueResolver.cs @@ -105,7 +105,7 @@ public object Resolve(IResolvableValueItem resolvableItem, IResolvedVariableColl var actualField = _graphType.Fields.FindField(inputField.Key); if (actualField != null) { - propSetter = _propSetters.ContainsKey(actualField.InternalFullName) ? _propSetters[actualField.InternalFullName] : null; + propSetter = _propSetters.ContainsKey(actualField.InternalName) ? _propSetters[actualField.InternalName] : null; } if (resolver == null || propSetter == null) diff --git a/src/graphql-aspnet/Execution/Resolvers/InternalFieldResolverMetaData.cs b/src/graphql-aspnet/Execution/Resolvers/InternalFieldResolverMetaData.cs index da55ee2a7..5297e5748 100644 --- a/src/graphql-aspnet/Execution/Resolvers/InternalFieldResolverMetaData.cs +++ b/src/graphql-aspnet/Execution/Resolvers/InternalFieldResolverMetaData.cs @@ -39,10 +39,8 @@ public static IGraphFieldResolverMetaData CreateMetadata(Type owningType) typeof(int), false, nameof(InternalValueResolver), - $"{owningType.FriendlyName(true)}.{nameof(InternalValueResolver)}", owningType, - owningType.FriendlyName(), - owningType.FriendlyName(true)); + owningType.FriendlyName()); } private static int InternalValueResolver() diff --git a/src/graphql-aspnet/Execution/Resolvers/ObjectMethodGraphFieldResolver.cs b/src/graphql-aspnet/Execution/Resolvers/ObjectMethodGraphFieldResolver.cs index cf5ddfc65..5187bf894 100644 --- a/src/graphql-aspnet/Execution/Resolvers/ObjectMethodGraphFieldResolver.cs +++ b/src/graphql-aspnet/Execution/Resolvers/ObjectMethodGraphFieldResolver.cs @@ -64,7 +64,7 @@ public virtual async Task ResolveAsync(FieldResolutionContext context, Cancellat Constants.ErrorCodes.INVALID_OBJECT, context.Request.Origin, new GraphExecutionException( - $"The method '{this.MetaData.InternalFullName}' expected source data of type " + + $"The method '{this.MetaData.InternalName}' expected source data of type " + $"'{this.MetaData.ParentObjectType.FriendlyName()}' but received '{sourceData.GetType().FriendlyName()}' " + "which is not compatible.")); diff --git a/src/graphql-aspnet/Execution/Resolvers/ObjectPropertyGraphFieldResolver.cs b/src/graphql-aspnet/Execution/Resolvers/ObjectPropertyGraphFieldResolver.cs index 8dce133c0..3ad7896f6 100644 --- a/src/graphql-aspnet/Execution/Resolvers/ObjectPropertyGraphFieldResolver.cs +++ b/src/graphql-aspnet/Execution/Resolvers/ObjectPropertyGraphFieldResolver.cs @@ -64,7 +64,7 @@ public async Task ResolveAsync(FieldResolutionContext context, CancellationToken Constants.ErrorCodes.INVALID_OBJECT, context.Request.Origin, new GraphExecutionException( - $"The property '{this.MetaData.InternalFullName}' expected source data that implements the interface " + + $"The property '{this.MetaData.InternalName}' expected source data that implements the interface " + $"'{this.MetaData.ParentObjectType.FriendlyName()}' but received '{sourceData.GetType().FriendlyName()}' which " + "is not compatible.")); @@ -79,7 +79,7 @@ public async Task ResolveAsync(FieldResolutionContext context, CancellationToken Constants.ErrorCodes.INVALID_OBJECT, context.Request.Origin, new GraphExecutionException( - $"The property '{this.MetaData.InternalFullName}' expected source data of type " + + $"The property '{this.MetaData.InternalName}' expected source data of type " + $"'{this.MetaData.ParentObjectType.FriendlyName()}' but received '{sourceData.GetType().FriendlyName()}' " + "which is not compatible.")); diff --git a/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverMetaData.cs b/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverMetaData.cs index 4eba0a0a6..d61b60efb 100644 --- a/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverMetaData.cs +++ b/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverMetaData.cs @@ -43,16 +43,9 @@ public interface IGraphFieldResolverMetaData /// true if the method is asynchronous; otherwise, false. bool IsAsyncField { get; } - /// - /// Gets the fully qualified name, including namespace, of this item as it exists in the - /// .NET code (e.g. Namespace.ObjectType.MethodName). - /// - /// The fully qualified name given to this item. - string InternalFullName { get; } - /// /// Gets the name that defines this item within the .NET code of the application; - /// typically a method name or property name. + /// typically a qualifed method name or property name. (e.g. MyObject.MyMethodName). /// /// The internal name given to this item. string InternalName { get; } @@ -71,13 +64,6 @@ public interface IGraphFieldResolverMetaData /// The name of the parent. string ParentInternalName { get; } - /// - /// Gets the full internal name of the parent item that ows the which generated - /// this metdata object. - /// - /// The name of the parent. - string ParentInternalFullName { get; } - /// /// Gets the templatized field arguments representing the field (if any). /// diff --git a/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverParameterMetaData.cs b/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverParameterMetaData.cs index fc1aeaa88..4684b06cd 100644 --- a/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverParameterMetaData.cs +++ b/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverParameterMetaData.cs @@ -49,15 +49,8 @@ public interface IGraphFieldResolverParameterMetaData Type UnwrappedExpectedParameterType { get; } /// - /// Gets the fully qualified name, including namespace, of this item as it exists in the - /// .NET code (e.g. Namespace.ObjectType.MethodName). - /// - /// The fully qualified name given to this item. - string InternalFullName { get; } - - /// - /// Gets the name that defines this item within the .NET code of the application; - /// typically a method name or property name. + /// Gets the name that identifies this item within the .NET code of the application. + /// This is typically a method name or property name. /// /// The internal name given to this item. string InternalName { get; } @@ -86,5 +79,12 @@ public interface IGraphFieldResolverParameterMetaData /// /// true if this instance is a list or collection; otherwise, false. bool IsList { get; } + + /// + /// Gets the internal name of the parent resolver that owns the which generated + /// this metdata object. + /// + /// The name of the parent method. + string ParentInternalName { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Internal/IEnumValueTemplate.cs b/src/graphql-aspnet/Interfaces/Internal/IEnumValueTemplate.cs index d8a7e56c5..8d59bda46 100644 --- a/src/graphql-aspnet/Interfaces/Internal/IEnumValueTemplate.cs +++ b/src/graphql-aspnet/Interfaces/Internal/IEnumValueTemplate.cs @@ -32,5 +32,11 @@ public interface IEnumValueTemplate : ISchemaItemTemplate /// /// The numeric value as string. string NumericValueAsString { get; } + + /// + /// Gets the label assigned to this enum value in the source code. (e.g. "Value1" in an enum value named MyEnum.Value1). + /// + /// The declared label. + string DeclaredLabel { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Internal/ISchemaItemTemplate.cs b/src/graphql-aspnet/Interfaces/Internal/ISchemaItemTemplate.cs index 6cb14bd2f..b4734c89b 100644 --- a/src/graphql-aspnet/Interfaces/Internal/ISchemaItemTemplate.cs +++ b/src/graphql-aspnet/Interfaces/Internal/ISchemaItemTemplate.cs @@ -62,13 +62,8 @@ public interface ISchemaItemTemplate : INamedItemTemplate Type ObjectType { get; } /// - /// Gets the fully qualified name, including namespace, of this item as it exists in the .NET code (e.g. 'Namespace.ObjectType.MethodName'). - /// - /// The internal name given to this item. - string InternalFullName { get; } - - /// - /// Gets the name that defines this item within the .NET code of the application; typically a method name or property name. + /// Gets the name that defines this item within the .NET code of the application; + /// typically a class, struct, method or property name. /// /// The internal name given to this item. string InternalName { get; } diff --git a/src/graphql-aspnet/Interfaces/Schema/IEnumValue.cs b/src/graphql-aspnet/Interfaces/Schema/IEnumValue.cs index f22abb683..535f7ec3b 100644 --- a/src/graphql-aspnet/Interfaces/Schema/IEnumValue.cs +++ b/src/graphql-aspnet/Interfaces/Schema/IEnumValue.cs @@ -24,13 +24,21 @@ public interface IEnumValue : ISchemaItem, IDeprecatable /// Gets the declared numerical value of the enum. /// /// The value of the neum. - object InternalValue { get; } + object DeclaredValue { get; } + + /// + /// Gets the internal name assigned to this enum value. Typically this is the same + /// as but can be customized by the developer to provider additional + /// context in error messages and log entries. + /// + /// The assigned internal name of this enum value. + string InternalName { get; } /// /// Gets the declared label applied to the enum value by .NET. /// (e.g. 'Value1' for the enum value MyEnum.Value1). /// - /// The internal label. - string InternalLabel { get; } + /// The declared label in source code. + string DeclaredLabel { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Schema/ITypedSchemaItem.cs b/src/graphql-aspnet/Interfaces/Schema/ITypedSchemaItem.cs index f399d2832..768f21349 100644 --- a/src/graphql-aspnet/Interfaces/Schema/ITypedSchemaItem.cs +++ b/src/graphql-aspnet/Interfaces/Schema/ITypedSchemaItem.cs @@ -23,7 +23,7 @@ public interface ITypedSchemaItem : ISchemaItem Type ObjectType { get; } /// - /// Gets a fully-qualified, internal name of schema item as it exists on the server. This name + /// Gets the assigned internal name of schema item as it exists on the server. This name /// is used in many exceptions and internal error messages. /// /// @@ -31,9 +31,11 @@ public interface ITypedSchemaItem : ISchemaItem /// Examples:
/// Scalar: System.Int
/// Controller Resolver Method: MyProject.MyController.RetrieveWidgets
- /// Object Property: MyProject.Widget.Name
. + /// Object Property: MyProject.Widget.Name
+ ///
+ /// This value is customizable by the developer to assign a more specific name if desired. /// - /// The fully qualiified, internal name of this schema item. - string InternalFullName { get; } + /// The assigned internal name of this schema item. + string InternalName { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodExceptionLogEntryBase.cs b/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodExceptionLogEntryBase.cs index 802e54edc..b943f1530 100644 --- a/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodExceptionLogEntryBase.cs +++ b/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodExceptionLogEntryBase.cs @@ -36,7 +36,7 @@ protected ActionMethodExceptionLogEntryBase( : base(eventId) { this.PipelineRequestId = request?.Id.ToString(); - this.ControllerTypeName = method?.ParentInternalFullName; + this.ControllerTypeName = method?.ParentInternalName; this.ActionName = method?.InternalName; this.Exception = new ExceptionLogItem(exception); } diff --git a/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodInvocationCompletedLogEntry.cs b/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodInvocationCompletedLogEntry.cs index d5bae4d27..b45f2d9b2 100644 --- a/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodInvocationCompletedLogEntry.cs +++ b/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodInvocationCompletedLogEntry.cs @@ -31,7 +31,7 @@ public ActionMethodInvocationCompletedLogEntry(IGraphFieldResolverMetaData metho : base(LogEventIds.ControllerInvocationCompleted) { this.PipelineRequestId = request?.Id.ToString(); - this.ControllerName = method?.ParentInternalFullName; + this.ControllerName = method?.ParentInternalName; this.ActionName = method?.InternalName; this.ResultTypeName = result?.GetType().FriendlyName(true); _shortControllerName = method?.ParentInternalName; diff --git a/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodInvocationStartedLogEntry.cs b/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodInvocationStartedLogEntry.cs index a466e7532..1535eb609 100644 --- a/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodInvocationStartedLogEntry.cs +++ b/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodInvocationStartedLogEntry.cs @@ -30,7 +30,7 @@ public ActionMethodInvocationStartedLogEntry(IGraphFieldResolverMetaData method, : base(LogEventIds.ControllerInvocationStarted) { this.PipelineRequestId = request?.Id.ToString(); - this.ControllerName = method?.ParentInternalFullName; + this.ControllerName = method?.ParentInternalName; this.ActionName = method?.InternalName; if (request is IGraphFieldRequest gfr) diff --git a/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodModelStateValidatedLogEntry.cs b/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodModelStateValidatedLogEntry.cs index eb1b6f2fe..6c6747cd2 100644 --- a/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodModelStateValidatedLogEntry.cs +++ b/src/graphql-aspnet/Logging/GeneralEvents/ActionMethodModelStateValidatedLogEntry.cs @@ -38,7 +38,7 @@ public ActionMethodModelStateValidatedLogEntry( : base(LogEventIds.ControllerModelValidated) { this.PipelineRequestId = request?.Id.ToString(); - this.ControllerName = method?.ParentInternalFullName; + this.ControllerName = method?.ParentInternalName; this.ActionName = method?.InternalName; this.ModelDataIsValid = modelState?.IsValid; diff --git a/src/graphql-aspnet/Logging/GeneralEvents/ExecutionDirectiveAppliedLogEntry.cs b/src/graphql-aspnet/Logging/GeneralEvents/ExecutionDirectiveAppliedLogEntry.cs index b83bbe7bd..15659b5ff 100644 --- a/src/graphql-aspnet/Logging/GeneralEvents/ExecutionDirectiveAppliedLogEntry.cs +++ b/src/graphql-aspnet/Logging/GeneralEvents/ExecutionDirectiveAppliedLogEntry.cs @@ -35,7 +35,7 @@ public ExecutionDirectiveAppliedLogEntry(IDirective directiveApplied, IDocumentP this.SourceLineIndex = appliedTo?.SourceLocation.LineIndex ?? 0; this.DirectiveLocation = appliedTo?.AsDirectiveLocation().ToString() ?? "-unknown-"; this.DirectiveName = directiveApplied?.Name; - this.DirectiveInternalName = directiveApplied?.InternalFullName; + this.DirectiveInternalName = directiveApplied?.InternalName; } /// diff --git a/src/graphql-aspnet/Logging/GeneralEvents/TypeSystemDirectiveAppliedLogEntry.cs b/src/graphql-aspnet/Logging/GeneralEvents/TypeSystemDirectiveAppliedLogEntry.cs index 63f85abbf..c05cda001 100644 --- a/src/graphql-aspnet/Logging/GeneralEvents/TypeSystemDirectiveAppliedLogEntry.cs +++ b/src/graphql-aspnet/Logging/GeneralEvents/TypeSystemDirectiveAppliedLogEntry.cs @@ -31,7 +31,7 @@ public TypeSystemDirectiveAppliedLogEntry(IDirective directiveApplied, ISchemaIt this.SchemaTypeName = typeof(TSchema).FriendlyName(true); this.SchemaItemPath = appliedTo?.Route?.Path; this.DirectiveName = directiveApplied?.Name; - this.DirectiveInternalName = directiveApplied?.InternalFullName; + this.DirectiveInternalName = directiveApplied?.InternalName; this.DirectiveLocation = appliedTo?.AsDirectiveLocation().ToString() ?? "-unknown-"; } diff --git a/src/graphql-aspnet/Schemas/Generation/TypeMakers/EnumGraphTypeMaker.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/EnumGraphTypeMaker.cs index eacce93ab..5af3071cb 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeMakers/EnumGraphTypeMaker.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/EnumGraphTypeMaker.cs @@ -80,6 +80,7 @@ public virtual GraphTypeCreationResult CreateGraphType(IGraphTypeTemplate typeTe value.Description, value.Route, value.Value, + value.DeclaredLabel, value.InternalName, valueDirectives); diff --git a/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphArgumentMaker.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphArgumentMaker.cs index 9af077396..60c9fecfd 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphArgumentMaker.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphArgumentMaker.cs @@ -75,7 +75,7 @@ public GraphArgumentCreationResult CreateArgument(ISchemaItem owner, IGraphArgum typeExpression, template.Route, template.ParameterName, - template.InternalFullName, + template.InternalName, template.ObjectType, template.HasDefaultValue, template.DefaultValue, diff --git a/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphFieldMaker.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphFieldMaker.cs index a1c4cc3b2..b2e2de95e 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphFieldMaker.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphFieldMaker.cs @@ -47,6 +47,8 @@ public GraphFieldMaker(ISchema schema, IGraphArgumentMaker argMaker) /// public virtual GraphFieldCreationResult CreateField(IGraphFieldTemplate template) { + Validation.ThrowIfNull(template, nameof(template)); + var formatter = _config.DeclarationOptions.GraphNamingFormatter; var result = new GraphFieldCreationResult(); @@ -94,6 +96,8 @@ public virtual GraphFieldCreationResult CreateField(IGraphFieldTemp /// public GraphFieldCreationResult CreateField(IInputGraphFieldTemplate template) { + Validation.ThrowIfNull(template, nameof(template)); + var formatter = _config.DeclarationOptions.GraphNamingFormatter; var defaultInputObject = InstanceFactory.CreateInstance(template.Parent.ObjectType); @@ -101,18 +105,19 @@ public GraphFieldCreationResult CreateField(IInputGraphFieldTe object defaultValue = null; - if (!template.IsRequired && propGetters.ContainsKey(template.InternalName)) + if (!template.IsRequired && propGetters.ContainsKey(template.DeclaredName)) { - defaultValue = propGetters[template.InternalName](ref defaultInputObject); + defaultValue = propGetters[template.DeclaredName](ref defaultInputObject); } var result = new GraphFieldCreationResult(); var directives = template.CreateAppliedDirectives(); + var schemaTypeName = this.PrepareTypeName(template); var field = new InputGraphField( formatter.FormatFieldName(template.Name), - template.TypeExpression.CloneTo(formatter.FormatGraphTypeName(template.TypeExpression.TypeName)), + template.TypeExpression.CloneTo(schemaTypeName), template.Route, template.DeclaredName, template.ObjectType, @@ -153,8 +158,8 @@ protected virtual string PrepareTypeName(IGraphFieldTemplate template) string schemaTypeName; // when the type already exists on the target schema - // and is usable as an input type then just use the name - if (existingGraphType != null && existingGraphType.Kind.IsValidInputKind()) + // and is usable as a type name then just use the name + if (existingGraphType != null) { schemaTypeName = existingGraphType.Name; } @@ -177,6 +182,42 @@ protected virtual string PrepareTypeName(IGraphFieldTemplate template) return schemaTypeName; } + /// + /// Finds and applies proper casing to the graph type name returned by this input field. + /// + /// The template to inspect. + /// System.String. + protected virtual string PrepareTypeName(IInputGraphFieldTemplate template) + { + + // all input fields return either an object, scalar or enum (never a union) + string schemaTypeName; + var existingGraphType = _schema.KnownTypes.FindGraphType(template.ObjectType, template.OwnerTypeKind); + + // when the type already exists on the target schema + // and is usable as a type for an input field then just use the name + // an OBJECT type may be registered for the target `template.ObjectType` which might get found + // but the coorisponding INPUT_OBJECT may not yet be discovered + if (existingGraphType != null && existingGraphType.Kind.IsValidInputKind()) + { + schemaTypeName = existingGraphType.Name; + } + else + { + // guess on what the unformatted name of the schema item will be + // this is guaranteed correct for all but scalars and scalars should be registered by the time + // input objects are registered + schemaTypeName = GraphTypeNames.ParseName(template.ObjectType, template.OwnerTypeKind); + } + + // enforce non-renaming standards in the maker since the + // directly controls the formatter + if (GlobalTypes.CanBeRenamed(schemaTypeName)) + schemaTypeName = _schema.Configuration.DeclarationOptions.GraphNamingFormatter.FormatGraphTypeName(schemaTypeName); + + return schemaTypeName; + } + /// /// Instantiates the graph field according to the data provided. /// diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/ControllerActionGraphFieldTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/ControllerActionGraphFieldTemplate.cs index fb5310ae2..50ea33f97 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/ControllerActionGraphFieldTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/ControllerActionGraphFieldTemplate.cs @@ -88,7 +88,7 @@ public override void ValidateOrThrow() if (declaration != null && declaration == typeof(GraphFieldAttribute)) { throw new GraphTypeDeclarationException( - $"Invalid action declaration. The controller action method '{this.InternalFullName}' declares " + + $"Invalid action declaration. The controller action method '{this.InternalName}' declares " + $"a '{nameof(GraphFieldAttribute)}'. This attribute is reserved for model classes. Controller " + $"actions must declare an operation specific attribute such as '{nameof(QueryAttribute)}', '{nameof(MutationAttribute)}' etc."); } diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/EnumGraphTypeTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/EnumGraphTypeTemplate.cs index ce4f75aa2..228fcec2f 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/EnumGraphTypeTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/EnumGraphTypeTemplate.cs @@ -152,12 +152,6 @@ public override void ValidateOrThrow() /// public IReadOnlyList Values => _values; - /// - public override string InternalFullName => this.ObjectType?.FriendlyName(true); - - /// - public override string InternalName => this.ObjectType?.FriendlyName(); - /// public override AppliedSecurityPolicyGroup SecurityPolicies => AppliedSecurityPolicyGroup.Empty; diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/EnumValueTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/EnumValueTemplate.cs index 24afca5fc..581a158a0 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/EnumValueTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/EnumValueTemplate.cs @@ -14,6 +14,7 @@ namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Common; using GraphQL.AspNet.Common.Extensions; + using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Schemas.Structural; @@ -51,18 +52,28 @@ protected override void ParseTemplateDefinition() this.Description = this.FieldInfo.SingleAttributeOrDefault()?.Description ?? null; var enumAttrib = this.FieldInfo.SingleAttributeOrDefault(); + this.InternalName = enumAttrib?.InternalName; var valueName = enumAttrib?.Name?.Trim() ?? Constants.Routing.ENUM_VALUE_META_NAME; if (valueName.Length == 0) valueName = Constants.Routing.ENUM_VALUE_META_NAME; valueName = valueName.Replace(Constants.Routing.ENUM_VALUE_META_NAME, this.FieldInfo.Name); this.Route = new SchemaItemPath(SchemaItemPath.Join(this.Parent.Route.Path, valueName)); + + if (string.IsNullOrWhiteSpace(this.InternalName)) + this.InternalName = $"{this.Parent.InternalName}.{this.FieldInfo.Name}"; } /// public override void ValidateOrThrow() { - GraphValidation.EnsureGraphNameOrThrow($"{this.InternalFullName}", this.Name); + if (string.IsNullOrWhiteSpace(this.InternalName)) + { + throw new GraphTypeDeclarationException( + $"The enum value template of `{this.Value}`, owned by enum {this.Parent.InternalName}, does not declare a valid internal name"); + } + + GraphValidation.EnsureGraphNameOrThrow($"{this.InternalName}", this.Name); } /// @@ -84,9 +95,6 @@ public override void ValidateOrThrow() public string NumericValueAsString { get; private set; } /// - public override string InternalFullName => $"{this.Parent.InternalFullName}.{this.InternalName}"; - - /// - public override string InternalName => this.FieldInfo.Name; + public string DeclaredLabel => this.FieldInfo.Name; } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphArgumentTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphArgumentTemplate.cs index e76d20ff2..f40ad9e1e 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphArgumentTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphArgumentTemplate.cs @@ -73,8 +73,12 @@ public virtual void Parse() { name = _argDeclaration?.ArgumentName?.Trim(); _foundModifiers.Add(GraphArgumentModifiers.ExplicitSchemaItem); + this.InternalName = _argDeclaration.InternalName; } + if (string.IsNullOrWhiteSpace(this.InternalName)) + this.InternalName = $"{this.Parent?.InternalName}.{this.Parameter.Name}"; + if (string.IsNullOrWhiteSpace(name)) name = Constants.Routing.PARAMETER_META_NAME; @@ -257,12 +261,19 @@ public IEnumerable RetrieveRequiredTypes() /// public void ValidateOrThrow() { - GraphValidation.EnsureGraphNameOrThrow(this.InternalFullName, this.Name); + if (string.IsNullOrWhiteSpace(this.InternalName)) + { + throw new GraphTypeDeclarationException( + $"The item '{this.Parent.InternalName}' declares a parameter '{this.Parameter.Name}' " + + "that did not not declare a valid internal name. Templating cannot continue."); + } + + GraphValidation.EnsureGraphNameOrThrow(this.InternalName, this.Name); if (_invalidTypeExpression) { throw new GraphTypeDeclarationException( - $"The item '{this.Parent.InternalFullName}' declares a parameter '{this.Name}' that " + + $"The item '{this.Parent.InternalName}' declares a parameter '{this.Name}' that " + $"defines an invalid {nameof(FromGraphQLAttribute.TypeExpression)} (Value = '{_argDeclaration.TypeExpression}'). " + $"The provided type expression must be a valid query language type expression or null."); } @@ -276,7 +287,7 @@ public void ValidateOrThrow() if (!GraphTypeExpression.AreTypesCompatiable(actualTypeExpression, this.TypeExpression, false)) { throw new GraphTypeDeclarationException( - $"The item '{this.Parent.InternalFullName}' declares a parameter '{this.Name}' that " + + $"The item '{this.Parent.InternalName}' declares a parameter '{this.Name}' that " + $"defines a {nameof(FromGraphQLAttribute.TypeExpression)} that is incompatiable with the " + $".NET parameter. (Declared '{this.TypeExpression}' is incompatiable with '{actualTypeExpression}') "); } @@ -287,7 +298,7 @@ public void ValidateOrThrow() && _foundModifiers.Contains(GraphArgumentModifiers.ExplicitSchemaItem)) { throw new GraphTypeDeclarationException( - $"The item '{this.Parent.InternalFullName}' declares a parameter '{this.Name}' that " + + $"The item '{this.Parent.InternalName}' declares a parameter '{this.Name}' that " + $"is defined to be supplied from a graphql query AND from a DI services container. " + $"An argument can not be supplied from a graphql query and from a DI container. If declaring argument attributes, supply " + $"{nameof(FromGraphQLAttribute)} or {nameof(FromServicesAttribute)}, but not both."); @@ -297,7 +308,7 @@ public void ValidateOrThrow() { var flags = string.Join(", ", _foundModifiers); throw new GraphTypeDeclarationException( - $"The item '{this.Parent.InternalFullName}' declares a parameter '{this.Name}' that " + + $"The item '{this.Parent.InternalName}' declares a parameter '{this.Name}' that " + $"declares more than one behavior modification flag. Each parameter must declare only one " + $"behavioral role within a given resolver method. Flags Declared: {flags}"); } @@ -305,7 +316,7 @@ public void ValidateOrThrow() if (_argSkipDeclaration != null && this.ArgumentModifier.CouldBePartOfTheSchema()) { throw new GraphTypeDeclarationException( - $"The item '{this.Parent.InternalFullName}' contains a parameter '{this.Name}' that " + + $"The item '{this.Parent.InternalName}' contains a parameter '{this.Name}' that " + $"declares the {nameof(GraphSkipAttribute)}. However, this argument may be included in the schema in some scenarios. " + $"If this argument is intended to be served from a service provider try adding {typeof(FromServicesAttribute)} to its declaration."); } @@ -313,7 +324,7 @@ public void ValidateOrThrow() if (_argTypeSkipDeclaration != null && this.ArgumentModifier.CouldBePartOfTheSchema()) { throw new GraphTypeDeclarationException( - $"The item '{this.Parent.InternalFullName}' contains a parameter '{this.Name}' that " + + $"The item '{this.Parent.InternalName}' contains a parameter '{this.Name}' that " + $"is of type {this.Parameter.ParameterType.FriendlyName()} . This type declares the {nameof(GraphSkipAttribute)} and is " + $"not allowed to appear in any schema but is currently being interpreted as an INPUT_OBJECT. If the parameter value is intended to be served " + $"from a service provider try adding {typeof(FromServicesAttribute)} to its declaration."); @@ -336,7 +347,7 @@ public IGraphFieldResolverParameterMetaData CreateResolverMetaData() return new FieldResolverParameterMetaData( this.Parameter, this.InternalName, - this.InternalFullName, + this.Parent.InternalName, this.ArgumentModifier, isValidList, this.HasDefaultValue, @@ -356,10 +367,7 @@ public IGraphFieldResolverParameterMetaData CreateResolverMetaData() public Type DeclaredArgumentType { get; private set; } /// - public string InternalFullName => $"{this.Parent?.InternalFullName}.{this.Parameter.Name}"; - - /// - public string InternalName => this.Parameter.Name; + public string InternalName { get; private set; } /// public bool IsExplicitDeclaration => true; diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveMethodTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveMethodTemplate.cs index 70d84e985..5f90edf23 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveMethodTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveMethodTemplate.cs @@ -22,6 +22,7 @@ namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Execution.Resolvers; + using GraphQL.AspNet.Execution.RulesEngine.RuleSets.DocumentValidation.QueryOperationSteps; using GraphQL.AspNet.Interfaces.Controllers; using GraphQL.AspNet.Interfaces.Execution; using GraphQL.AspNet.Interfaces.Internal; @@ -75,6 +76,7 @@ public virtual void Parse() this.Description = this.AttributeProvider.SingleAttributeOrDefault()?.Description; this.IsAsyncField = Validation.IsCastable(this.Method.ReturnType); this.AppliedDirectives = this.ExtractAppliedDirectiveTemplates(); + this.InternalName = $"{this.Parent?.InternalName ?? "UnknownDirective"}.{this.Method.Name}"; // deteremine all the directive locations where this method should be invoked var locations = DirectiveLocation.NONE; @@ -147,14 +149,14 @@ public virtual void ValidateOrThrow() if (this.Method.SingleAttributeOrDefault() != null) { throw new GraphTypeDeclarationException( - $"The directive method {this.InternalFullName} defines a {nameof(GraphSkipAttribute)}. It cannot be parsed or added " + + $"The directive method {this.InternalName} defines a {nameof(GraphSkipAttribute)}. It cannot be parsed or added " + "to the object graph."); } if (this.AppliedDirectives.Any()) { throw new GraphTypeDeclarationException( - $"The directive method {this.InternalFullName} defines an {nameof(ApplyDirectiveAttribute)}. " + + $"The directive method {this.InternalName} defines an {nameof(ApplyDirectiveAttribute)}. " + $"Directive methods cannot have applied directives."); } @@ -167,7 +169,7 @@ public virtual void ValidateOrThrow() if (genericArgs.Length != 1) { throw new GraphTypeDeclarationException( - $"The directive method '{this.InternalFullName}' defines a return type of'{typeof(Task).Name}' but " + + $"The directive method '{this.InternalName}' defines a return type of'{typeof(Task).Name}' but " + "defines no contained return type for the resultant model object yielding a void return after " + "completion of the task. All graph methods must return a single model object. Consider using " + $"'{typeof(Task<>).Name}' instead for asyncronous methods"); @@ -177,10 +179,16 @@ public virtual void ValidateOrThrow() if (this.ExpectedReturnType != typeof(IGraphActionResult)) { throw new GraphTypeDeclarationException( - $"The directive method '{this.InternalFullName}' does not return a {nameof(IGraphActionResult)}. " + + $"The directive method '{this.InternalName}' does not return a {nameof(IGraphActionResult)}. " + $"All directive methods must return a {nameof(IGraphActionResult)} or {typeof(Task).FriendlyName()}"); } + if (string.IsNullOrWhiteSpace(this.InternalName)) + { + throw new GraphTypeDeclarationException( + $"The directive method template identified by `{this.Method.Name}` does not declare a valid internal name."); + } + foreach (var argument in _arguments) argument.ValidateOrThrow(); @@ -218,10 +226,8 @@ public IGraphFieldResolverMetaData CreateResolverMetaData() this.ExpectedReturnType, this.IsAsyncField, this.InternalName, - this.InternalFullName, this.Parent.ObjectType, - this.Parent.InternalName, - this.Parent.InternalFullName); + this.Parent.InternalName); } /// @@ -292,10 +298,7 @@ public IGraphFieldResolverMetaData CreateResolverMetaData() public GraphFieldSource FieldSource => GraphFieldSource.Method; /// - public string InternalFullName => $"{this.Parent?.InternalFullName}.{this.Method.Name}"; - - /// - public string InternalName => this.Method.Name; + public string InternalName { get; protected set; } /// public ICustomAttributeProvider AttributeProvider { get; } diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveMethodTemplateContainer.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveMethodTemplateContainer.cs index 5b6f47786..46a326fa0 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveMethodTemplateContainer.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveMethodTemplateContainer.cs @@ -127,7 +127,7 @@ public void ValidateOrThrow() { var duplicatedDecs = string.Join(",", _duplicateDirectiveLocations.Select(x => $"'{x.ToString()}'")); throw new GraphTypeDeclarationException( - $"The directive '{_parent.InternalFullName}' attempted to register more than one method to handle " + + $"The directive '{_parent.InternalName}' attempted to register more than one method to handle " + $"a single {nameof(DirectiveLocation)}. Each directive can only define, at most, one method per {nameof(DirectiveLocation)}. " + $"Duplicated Locations: {duplicatedDecs}"); } @@ -155,7 +155,7 @@ public void ValidateOrThrow() if (!this.DoMethodSignaturesMatch(baseExecutionMethod, kvp.Value)) { throw new GraphTypeDeclarationException( - $"The method '{kvp.Value.InternalFullName}' (Target Location: {kvp.Value}) declares a signature of '{kvp.Value.MethodSignature}'. " + + $"The method '{kvp.Value.InternalName}' (Target Location: {kvp.Value}) declares a signature of '{kvp.Value.MethodSignature}'. " + $"However, which is different than the method '{baseExecutionMethod.InternalName}'. " + $"All location targeting methods on a directive must have the same method signature " + $"including parameter types, names and declaration order."); diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveTemplate.cs index 43423d5a7..d91335f8d 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveTemplate.cs @@ -135,14 +135,14 @@ public override void ValidateOrThrow() if (this.Locations == DirectiveLocation.NONE) { throw new GraphTypeDeclarationException( - $"The directive '{this.InternalFullName}' defines no locations to which it can be applied. You must specify at least " + + $"The directive '{this.InternalName}' defines no locations to which it can be applied. You must specify at least " + $"one '{typeof(DirectiveLocation)}' via the {typeof(DirectiveLocationsAttribute).FriendlyName()}."); } if (this.AppliedDirectives.Any()) { throw new GraphTypeDeclarationException( - $"The directive {this.InternalFullName} defines an {nameof(ApplyDirectiveAttribute)}. " + + $"The directive {this.InternalName} defines an {nameof(ApplyDirectiveAttribute)}. " + $"Directives cannot have applied directives."); } @@ -171,12 +171,6 @@ public IGraphDirectiveResolver CreateResolver() /// The type of the declared. public Type DeclaredType => this.ObjectType; - /// - public override string InternalFullName => this.ObjectType?.FriendlyName(true); - - /// - public override string InternalName => this.ObjectType?.FriendlyName(); - /// public override bool IsExplicitDeclaration => true; diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphFieldTemplateBase.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphFieldTemplateBase.cs index f23d96650..3bcb0c642 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphFieldTemplateBase.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphFieldTemplateBase.cs @@ -183,13 +183,13 @@ public override void ValidateOrThrow() if (_invalidTypeExpression) { throw new GraphTypeDeclarationException( - $"The field '{this.InternalFullName}' defines an invalid {nameof(GraphFieldAttribute.TypeExpression)} (Value = '{_fieldDeclaration.TypeExpression}'). " + + $"The field '{this.InternalName}' defines an invalid {nameof(GraphFieldAttribute.TypeExpression)} (Value = '{_fieldDeclaration.TypeExpression}'). " + $"The provided type expression must be a valid query language type expression or null."); } if (this.DeclaredReturnType == typeof(void)) { - throw new GraphTypeDeclarationException($"The graph field '{this.InternalFullName}' has a void return. All graph fields must return something."); + throw new GraphTypeDeclarationException($"The graph field '{this.InternalName}' has a void return. All graph fields must return something."); } if (this.IsAsyncField) @@ -199,7 +199,7 @@ public override void ValidateOrThrow() if (genericArgs.Length != 1) { throw new GraphTypeDeclarationException( - $"The field '{this.InternalFullName}' defines a return type of'{typeof(Task).Name}' but " + + $"The field '{this.InternalName}' defines a return type of'{typeof(Task).Name}' but " + "defines no contained return type for the resultant model object yielding a void return after " + "completion of the task. All graph methods must return a single model object. Consider using " + $"'{typeof(Task<>).Name}' instead for asyncronous methods"); @@ -208,11 +208,11 @@ public override void ValidateOrThrow() if (this.UnionProxy != null) { - GraphValidation.EnsureGraphNameOrThrow($"{this.InternalFullName}[{nameof(GraphFieldAttribute)}][{nameof(IGraphUnionProxy)}]", this.UnionProxy.Name); + GraphValidation.EnsureGraphNameOrThrow($"{this.InternalName}[{nameof(GraphFieldAttribute)}][{nameof(IGraphUnionProxy)}]", this.UnionProxy.Name); if (this.UnionProxy.Types.Count < 1) { throw new GraphTypeDeclarationException( - $"The field '{this.InternalFullName}' declares union type of '{this.UnionProxy.Name}' " + + $"The field '{this.InternalName}' declares union type of '{this.UnionProxy.Name}' " + "but that type includes 0 possible types in the union. Unions require 1 or more possible types. Add additional types" + "or remove the union."); } @@ -223,7 +223,7 @@ public override void ValidateOrThrow() if (this.PossibleTypes.Count == 0) { throw new GraphTypeDeclarationException( - $"The field '{this.InternalFullName}' declared no possible return types either as part of its specification or as the " + + $"The field '{this.InternalName}' declared no possible return types either as part of its specification or as the " + "declared return type for the field. GraphQL requires the type information be known " + $"to setup the schema and client tooling properly. If this field returns a '{nameof(IGraphActionResult)}' you must " + "provide a graph field declaration attribute and add at least one type; be that a concrete type, an interface or a union."); @@ -240,21 +240,21 @@ public override void ValidateOrThrow() if (type.IsEnum) { throw new GraphTypeDeclarationException( - $"The field '{this.InternalFullName}' declares a union with a possible type of '{type.FriendlyName()}' " + + $"The field '{this.InternalName}' declares a union with a possible type of '{type.FriendlyName()}' " + "but that type is an enum. Only concrete, non-abstract classes may be used. Value types, such as structs or enumerations, are not allowed."); } if (GraphValidation.MustBeLeafType(type)) { throw new GraphTypeDeclarationException( - $"The field '{this.InternalFullName}' declares union with a possible type of '{type.FriendlyName()}' " + + $"The field '{this.InternalName}' declares union with a possible type of '{type.FriendlyName()}' " + "but that type is a scalar. Scalars cannot be included in a field's possible type collection, only object types can."); } if (type.IsInterface) { throw new GraphTypeDeclarationException( - $"The field '{this.InternalFullName}' declares union with a possible type of '{type.FriendlyName()}' " + + $"The field '{this.InternalName}' declares union with a possible type of '{type.FriendlyName()}' " + "but that type is an interface. Interfaces cannot be included in a field's possible type collection, only object types can."); } } @@ -264,7 +264,7 @@ public override void ValidateOrThrow() if (Validation.IsCastable(type, invalidFieldType)) { throw new GraphTypeDeclarationException( - $"The field '{this.InternalFullName}' declares a possible return type of '{type.FriendlyName()}' " + + $"The field '{this.InternalName}' declares a possible return type of '{type.FriendlyName()}' " + $"but that type inherits from '{invalidFieldType.FriendlyName()}' which is a reserved type declared by the graphql-aspnet library. This type cannot cannot be returned by a graphql field."); } } @@ -281,7 +281,7 @@ public override void ValidateOrThrow() if (!_returnsActionResult && this.Mode == FieldResolutionMode.PerSourceItem && !Validation.IsCastable(type, this.ObjectType)) { throw new GraphTypeDeclarationException( - $"The field '{this.InternalFullName}' returns '{this.ObjectType.FriendlyName()}' and declares a possible type of '{type.FriendlyName()}' " + + $"The field '{this.InternalName}' returns '{this.ObjectType.FriendlyName()}' and declares a possible type of '{type.FriendlyName()}' " + $"but that type is not castable to '{this.ObjectType.FriendlyName()}' and therefore not returnable by this field. Due to the strongly-typed nature of C# any possible type on a field " + "must be castable to the type of the field in order to ensure its not inadvertantly nulled out during processing. If this field returns a union " + $"of multiple, disperate types consider returning '{typeof(object).Name}' from the field to ensure each possible return type can be successfully processed."); @@ -295,7 +295,7 @@ public override void ValidateOrThrow() if (this.Complexity.HasValue && this.Complexity < 0) { throw new GraphTypeDeclarationException( - $"The field '{this.InternalFullName}' declares a complexity value of " + + $"The field '{this.InternalName}' declares a complexity value of " + $"`{this.Complexity.Value}`. The complexity factor must be greater than or equal to 0."); } @@ -325,7 +325,7 @@ private void ValidateBatchMethodSignatureOrThrow() if (this.Arguments.All(arg => arg.DeclaredArgumentType != requiredEnumerable)) { throw new GraphTypeDeclarationException( - $"Invalid batch method signature. The field '{this.InternalFullName}' declares itself as batch method but does not accept a batch " + + $"Invalid batch method signature. The field '{this.InternalName}' declares itself as batch method but does not accept a batch " + $"of data as an input parameter. This method must accept a parameter of type '{requiredEnumerable.FriendlyName()}' somewhere in its method signature to " + $"be used as a batch extension for the type '{this.SourceObjectType.FriendlyName()}'."); } @@ -343,7 +343,7 @@ private void ValidateBatchMethodSignatureOrThrow() if (!BatchResultProcessor.IsBatchDictionaryType(declaredType, this.SourceObjectType, this.ObjectType)) { throw new GraphTypeDeclarationException( - $"Invalid batch method signature. The field '{this.InternalFullName}' declares a return type of '{declaredType.FriendlyName()}', however; " + + $"Invalid batch method signature. The field '{this.InternalName}' declares a return type of '{declaredType.FriendlyName()}', however; " + $"batch methods must return either an '{typeof(IGraphActionResult).FriendlyName()}' or a dictionary keyed " + "on the provided source data (e.g. 'IDictionary')."); } @@ -358,7 +358,7 @@ private void ValidateBatchMethodSignatureOrThrow() if (!Validation.IsCastable(type, dictionaryValue)) { throw new GraphTypeDeclarationException( - $"The field '{this.InternalFullName}' returns '{this.ObjectType.FriendlyName()}' and declares a possible type of '{type.FriendlyName()}' " + + $"The field '{this.InternalName}' returns '{this.ObjectType.FriendlyName()}' and declares a possible type of '{type.FriendlyName()}' " + $"but that type is not castable to '{this.ObjectType.FriendlyName()}' and therefore not returnable by this field. Due to the strongly-typed nature of C# any possible type on a field " + "must be castable to the type of the field in order to ensure its not inadvertantly nulled out during processing. If this field returns a union " + $"of multiple, disperate types consider returning '{typeof(object).Name}' from the field to ensure each possible return type can be successfully processed."); diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphTypeExtensionFieldTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphTypeExtensionFieldTemplate.cs index f6ee6b1a3..94da70514 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphTypeExtensionFieldTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphTypeExtensionFieldTemplate.cs @@ -98,14 +98,14 @@ public override void ValidateOrThrow() { // should be an impossible situation but just in case someone manually invokes this template bypassing global checks. throw new GraphTypeDeclarationException( - $"The type extension '{this.InternalFullName}' does not define a {typeof(TypeExtensionAttribute).FriendlyName()} or defines more than one instance. " + + $"The type extension '{this.InternalName}' does not define a {typeof(TypeExtensionAttribute).FriendlyName()} or defines more than one instance. " + "All methods wishing to be treated as type extensions must define one instance of this attribute to properly configure the runtime."); } if (!this.SourceObjectType.IsClass && !this.SourceObjectType.IsStruct() && !this.SourceObjectType.IsInterface) { throw new GraphTypeDeclarationException( - $"The type extension '{this.InternalFullName}' is attempting to extend '{this.SourceObjectType.FriendlyName()}'. " + + $"The type extension '{this.InternalName}' is attempting to extend '{this.SourceObjectType.FriendlyName()}'. " + "Only classes, structs and interfaces can be extended."); } @@ -114,7 +114,7 @@ public override void ValidateOrThrow() if (this.Route == null || !this.Route.IsValid) { throw new GraphTypeDeclarationException( - $"The type extension '{this.InternalFullName}' declares an invalid field name of '{_typeAttrib.Template ?? ""}'. " + + $"The type extension '{this.InternalName}' declares an invalid field name of '{_typeAttrib.Template ?? ""}'. " + $"Each segment of the route must conform to standard graphql naming rules. (Regex: {Constants.RegExPatterns.NameRegex} )", this.ObjectType); } diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphTypeTemplateBase.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphTypeTemplateBase.cs index ca540e6f5..4b44f697a 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphTypeTemplateBase.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphTypeTemplateBase.cs @@ -34,9 +34,7 @@ protected GraphTypeTemplateBase(ICustomAttributeProvider attributeProvider) this.Publish = true; } - /// - /// When overridden in a child class this method builds out the template according to its own individual requirements. - /// + /// protected override void ParseTemplateDefinition() { base.ParseTemplateDefinition(); @@ -46,11 +44,17 @@ protected override void ParseTemplateDefinition() if (graphTypeDeclaration != null) { this.Publish = graphTypeDeclaration.Publish; + + if (string.IsNullOrEmpty(this.InternalName)) + this.InternalName = graphTypeDeclaration.InternalName; if (graphTypeDeclaration.RequirementsWereDeclared) { _fieldDeclarationOverrides = graphTypeDeclaration.FieldDeclarationRequirements; } } + + if (string.IsNullOrWhiteSpace(this.InternalName)) + this.InternalName = this.ObjectType?.FriendlyName(); } /// diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/InputGraphFieldTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/InputGraphFieldTemplate.cs index 6e823e7ae..8ac5d2fe9 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/InputGraphFieldTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/InputGraphFieldTemplate.cs @@ -52,19 +52,24 @@ protected override void ParseTemplateDefinition() { base.ParseTemplateDefinition(); + var objectType = GraphValidation.EliminateWrappersFromCoreType(this.DeclaredReturnType); + this.ObjectType = objectType; + _fieldDeclaration = this.AttributeProvider.SingleAttributeOfTypeOrDefault(); this.Route = this.GenerateFieldPath(); this.Description = this.AttributeProvider.SingleAttributeOfTypeOrDefault()?.Description; - var objectType = GraphValidation.EliminateWrappersFromCoreType(this.DeclaredReturnType); - this.ObjectType = objectType; - var typeExpression = GraphTypeExpression.FromType(this.DeclaredReturnType, this.DeclaredTypeWrappers); - typeExpression = typeExpression.CloneTo(GraphTypeNames.ParseName(objectType, this.Parent.Kind)); + typeExpression = typeExpression.CloneTo(Constants.Other.DEFAULT_TYPE_EXPRESSION_TYPE_NAME); this.IsRequired = this.AttributeProvider.SingleAttributeOrDefault() != null; this.TypeExpression = typeExpression; + + if (_fieldDeclaration != null) + this.InternalName = _fieldDeclaration.InternalName; + if (string.IsNullOrEmpty(this.InternalName)) + this.InternalName = $"{this.Parent.InternalName}.{this.Property.Name}"; } /// @@ -79,7 +84,7 @@ public override IEnumerable RetrieveRequiredTypes() private SchemaItemPath GenerateFieldPath() { - var graphName = this.AttributeProvider.SingleAttributeOfTypeOrDefault()?.Template?.Trim() ?? Constants.Routing.ACTION_METHOD_META_NAME; + var graphName = _fieldDeclaration?.Template?.Trim() ?? Constants.Routing.ACTION_METHOD_META_NAME; graphName = graphName.Replace(Constants.Routing.ACTION_METHOD_META_NAME, this.Property.Name).Trim(); return new SchemaItemPath(SchemaItemPath.Join(this.Parent.Route.Path, graphName)); @@ -93,28 +98,28 @@ public override void ValidateOrThrow() if (Validation.IsCastable(this.DeclaredReturnType)) { throw new GraphTypeDeclarationException( - $"The input field '{this.InternalFullName}' defines a return type of'{nameof(Task)}'. " + + $"The input field '{this.InternalName}' defines a return type of'{nameof(Task)}'. " + $"Input fields must not be asyncronous."); } if (this.ObjectType.IsInterface) { throw new GraphTypeDeclarationException( - $"The input field '{this.InternalFullName}' returns '{this.ObjectType.FriendlyName()}' which is an interface. " + + $"The input field '{this.InternalName}' returns '{this.ObjectType.FriendlyName()}' which is an interface. " + $"Input fields must not return interface objects."); } if (Validation.IsCastable(this.ObjectType)) { throw new GraphTypeDeclarationException( - $"The input field '{this.InternalFullName}' returns '{this.ObjectType.FriendlyName()}' which implements {nameof(IGraphUnionProxy)}. " + + $"The input field '{this.InternalName}' returns '{this.ObjectType.FriendlyName()}' which implements {nameof(IGraphUnionProxy)}. " + $"Input fields must not implement {nameof(IGraphUnionProxy)}."); } if (Validation.IsCastable(this.ObjectType)) { throw new GraphTypeDeclarationException( - $"The input field '{this.InternalFullName}' returns '{this.ObjectType.FriendlyName()}' which implements {nameof(IGraphActionResult)}. " + + $"The input field '{this.InternalName}' returns '{this.ObjectType.FriendlyName()}' which implements {nameof(IGraphActionResult)}. " + $"Input fields must not implement {nameof(IGraphActionResult)}."); } } @@ -143,12 +148,6 @@ public override void ValidateOrThrow() /// public TypeKind OwnerTypeKind => TypeKind.INPUT_OBJECT; - /// - public override string InternalFullName => $"{this.Parent.InternalFullName}.{this.Property.Name}"; - - /// - public override string InternalName => this.Property.Name; - /// public MetaGraphTypes[] DeclaredTypeWrappers { diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/InputObjectGraphTypeTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/InputObjectGraphTypeTemplate.cs index fd2d02439..9df0e481c 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/InputObjectGraphTypeTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/InputObjectGraphTypeTemplate.cs @@ -188,9 +188,9 @@ public override void ValidateOrThrow() if (_invalidFields != null && _invalidFields.Count > 0) { - var fieldNames = string.Join("\n", _invalidFields.Select(x => $"Field: '{x.InternalFullName} ({x.Route.RootCollection.ToString()})'")); + var fieldNames = string.Join("\n", _invalidFields.Select(x => $"Field: '{x.InternalName} ({x.Route.RootCollection.ToString()})'")); throw new GraphTypeDeclarationException( - $"Invalid input field declaration. The type '{this.InternalFullName}' declares fields belonging to a graph collection not allowed given its context. This type can " + + $"Invalid input field declaration. The type '{this.InternalName}' declares fields belonging to a graph collection not allowed given its context. This type can " + $"only declare the following graph collections: '{string.Join(", ", this.AllowedGraphCollectionTypes.Select(x => x.ToString()))}'. " + $"If this field is declared on an object (not a controller) be sure to use '{nameof(GraphFieldAttribute)}' instead " + $"of '{nameof(QueryAttribute)}' or '{nameof(MutationAttribute)}'.\n---------\n " + fieldNames, @@ -210,12 +210,6 @@ public override void ValidateOrThrow() /// public override AppliedSecurityPolicyGroup SecurityPolicies => AppliedSecurityPolicyGroup.Empty; - /// - public override string InternalFullName => this.ObjectType?.FriendlyName(true); - - /// - public override string InternalName => this.ObjectType?.FriendlyName(); - private IEnumerable AllowedGraphCollectionTypes => SchemaItemCollections.Types.AsEnumerable(); } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplate.cs index fe246abe1..70103c1ba 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplate.cs @@ -57,7 +57,7 @@ protected override SchemaItemPath GenerateFieldPath() var graphName = this.Method.SingleAttributeOrDefault()?.Template?.Trim() ?? Constants.Routing.ACTION_METHOD_META_NAME; graphName = graphName.Replace(Constants.Routing.ACTION_METHOD_META_NAME, this.Method.Name).Trim(); - GraphValidation.EnsureGraphNameOrThrow(this.InternalFullName, graphName); + GraphValidation.EnsureGraphNameOrThrow(this.InternalName, graphName); return new SchemaItemPath(SchemaItemPath.Join(this.Parent.Route.Path, graphName)); } @@ -74,7 +74,7 @@ public override void ValidateOrThrow() if (declaration != null && declaration != typeof(GraphFieldAttribute)) { throw new GraphTypeDeclarationException( - $"Invalid graph method declaration. The method '{this.InternalFullName}' declares a '{declaration.FriendlyName()}'. This " + + $"Invalid graph method declaration. The method '{this.InternalName}' declares a '{declaration.FriendlyName()}'. This " + $"attribute is reserved for controller actions. For a general object type use '{nameof(GraphFieldAttribute)}' instead."); } } diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplateBase.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplateBase.cs index cff78d02f..249fe9c82 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplateBase.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplateBase.cs @@ -14,7 +14,9 @@ namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates using System.Diagnostics; using System.Linq; using System.Reflection; + using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Common; + using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Execution.Resolvers; using GraphQL.AspNet.Interfaces.Execution; @@ -62,6 +64,13 @@ protected override void ParseTemplateDefinition() { base.ParseTemplateDefinition(); + // set the internal name of the item + var fieldDeclaration = this.AttributeProvider.SingleAttributeOfTypeOrDefault(); + if (fieldDeclaration != null) + this.InternalName = fieldDeclaration.InternalName; + if (string.IsNullOrWhiteSpace(this.InternalName)) + this.InternalName = $"{this.Parent.InternalName}.{this.Method.Name}"; + // parse all input parameters from the method signature foreach (var parameter in this.Parameters) { @@ -95,7 +104,7 @@ public override void ValidateOrThrow() if (this.ExpectedReturnType == null) { throw new GraphTypeDeclarationException( - $"Invalid graph method declaration. The method '{this.InternalFullName}' has no valid {nameof(this.ExpectedReturnType)}. An expected " + + $"Invalid graph method declaration. The method '{this.InternalName}' has no valid {nameof(this.ExpectedReturnType)}. An expected " + "return type must be assigned from the declared return type."); } } @@ -118,18 +127,10 @@ public override IGraphFieldResolverMetaData CreateResolverMetaData() this.ExpectedReturnType, this.IsAsyncField, this.InternalName, - this.InternalFullName, this.Parent.ObjectType, - this.Parent.InternalName, - this.Parent.InternalFullName); + this.Parent.InternalName); } - /// - public override string InternalFullName => $"{this.Parent?.InternalFullName}.{this.Method.Name}"; - - /// - public override string InternalName => this.Method.Name; - /// public override IReadOnlyList Arguments => _arguments; diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/NonLeafGraphTypeTemplateBase.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/NonLeafGraphTypeTemplateBase.cs index 62396749e..87abddbea 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/NonLeafGraphTypeTemplateBase.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/NonLeafGraphTypeTemplateBase.cs @@ -264,9 +264,9 @@ public override void ValidateOrThrow() if (_invalidFields != null && _invalidFields.Count > 0) { - var fieldNames = string.Join("\n", _invalidFields.Select(x => $"Field: '{x.InternalFullName} ({x.Route.RootCollection.ToString()})'")); + var fieldNames = string.Join("\n", _invalidFields.Select(x => $"Field: '{x.InternalName} ({x.Route.RootCollection.ToString()})'")); throw new GraphTypeDeclarationException( - $"Invalid field declarations. The type '{this.InternalFullName}' declares fields belonging to a graph collection not allowed given its context. This type can " + + $"Invalid field declarations. The type '{this.InternalName}' declares fields belonging to a graph collection not allowed given its context. This type can " + $"only declare the following graph collections: '{string.Join(", ", this.AllowedSchemaItemCollections.Select(x => x.ToString()))}'. " + $"If this field is declared on an object (not a controller) be sure to use '{nameof(GraphFieldAttribute)}' instead " + $"of '{nameof(QueryAttribute)}' or '{nameof(MutationAttribute)}'.\n---------\n " + fieldNames, @@ -286,12 +286,6 @@ public override void ValidateOrThrow() /// The methods. public IReadOnlyDictionary FieldTemplates => _fields; - /// - public override string InternalFullName => this.ObjectType?.FriendlyName(true); - - /// - public override string InternalName => this.ObjectType?.FriendlyName(); - /// /// Gets a set of item collections to which this object template can be declared. /// diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/PropertyGraphFieldTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/PropertyGraphFieldTemplate.cs index 0755108c0..2259b4ec9 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/PropertyGraphFieldTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/PropertyGraphFieldTemplate.cs @@ -78,22 +78,22 @@ protected override SchemaItemPath GenerateFieldPath() /// public override void ValidateOrThrow() { - base.ValidateOrThrow(); - // ensure property has a public getter (kinda useless otherwise) if (this.Property.GetGetMethod() == null) { throw new GraphTypeDeclarationException( - $"The graph property {this.InternalFullName} does not define a public getter. It cannot be parsed or added " + + $"The graph property {this.InternalName} does not define a public getter. It cannot be parsed or added " + "to the object graph."); } if (this.ExpectedReturnType == null) { throw new GraphTypeDeclarationException( - $"The graph property '{this.InternalFullName}' has no valid {nameof(this.ExpectedReturnType)}. An expected " + + $"The graph property '{this.InternalName}' has no valid {nameof(this.ExpectedReturnType)}. An expected " + "return type must be assigned from the declared return type."); } + + base.ValidateOrThrow(); } /// @@ -101,6 +101,13 @@ protected override void ParseTemplateDefinition() { base.ParseTemplateDefinition(); + // set the internal name of the item + var fieldDeclaration = this.AttributeProvider.SingleAttributeOfTypeOrDefault(); + if (fieldDeclaration != null) + this.InternalName = fieldDeclaration.InternalName; + if (string.IsNullOrWhiteSpace(this.InternalName) && this.Method != null) + this.InternalName = $"{this.Parent.InternalName}.{this.Method.Name}"; + this.ExpectedReturnType = GraphValidation.EliminateWrappersFromCoreType( this.DeclaredReturnType, false, @@ -126,10 +133,8 @@ public override IGraphFieldResolverMetaData CreateResolverMetaData() this.ExpectedReturnType, this.IsAsyncField, this.InternalName, - this.InternalFullName, this.Parent.ObjectType, - this.Parent.InternalName, - this.Parent.InternalFullName); + this.Parent.InternalName); } /// @@ -164,11 +169,5 @@ public override IGraphFieldResolverMetaData CreateResolverMetaData() /// public override IReadOnlyList Arguments { get; } = new List(); - - /// - public override string InternalFullName => $"{this.Parent.InternalFullName}.{this.Property.Name}"; - - /// - public override string InternalName => this.Property.Name; } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/ScalarGraphTypeTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/ScalarGraphTypeTemplate.cs index 5ef35648f..31524f118 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/ScalarGraphTypeTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/ScalarGraphTypeTemplate.cs @@ -13,6 +13,7 @@ namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates using System.Collections.Generic; using System.Linq; using GraphQL.AspNet.Common; + using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Execution; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; @@ -49,7 +50,11 @@ protected override void ParseTemplateDefinition() { this.Route = new SchemaItemPath(SchemaItemPath.Join(SchemaItemCollections.Types, _instance.Name)); this.ObjectType = _instance.ObjectType; + this.InternalName = _instance.InternalName; } + + if (string.IsNullOrWhiteSpace(this.InternalName)) + this.InternalName = _scalarType?.FriendlyName(); } /// @@ -82,12 +87,6 @@ protected override IEnumerable ParseAppliedDiretives( /// public override TypeKind Kind => TypeKind.SCALAR; - /// - public override string InternalFullName => _instance?.InternalFullName; - - /// - public override string InternalName => _scalarType?.Name; - /// public override string Name => _instance?.Name; diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/SchemaItemTemplateBase.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/SchemaItemTemplateBase.cs index 72636ffcf..38cfc0354 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/SchemaItemTemplateBase.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/SchemaItemTemplateBase.cs @@ -87,14 +87,14 @@ public virtual void ValidateOrThrow() if (!_isParsed) { throw new InvalidOperationException( - $"The graph item has not been parsed and cannot pass validation. Be sure to call {nameof(this.Parse)}() before attempting to " + + $"The schema template item has not been parsed and cannot pass validation. Be sure to call {nameof(this.Parse)}() before attempting to " + "validate this instance."); } if (this.AttributeProvider.SingleAttributeOfTypeOrDefault() != null) { throw new GraphTypeDeclarationException( - $"The graph item {this.InternalFullName} defines a {nameof(GraphSkipAttribute)}. It cannot be parsed or added " + + $"The schema template item {this.InternalName} defines a {nameof(GraphSkipAttribute)}. It cannot be parsed or added " + "to the object graph.", this.ObjectType); } @@ -102,11 +102,18 @@ public virtual void ValidateOrThrow() if (this.Route == null || !this.Route.IsValid) { throw new GraphTypeDeclarationException( - $"The template item '{this.InternalFullName}' declares an invalid route of '{this.Route?.Raw ?? ""}'. " + + $"The schema template item '{this.InternalName}' declares an invalid route of '{this.Route?.Raw ?? ""}'. " + $"Each segment of the route must conform to standard graphql naming rules. (Regex: {Constants.RegExPatterns.NameRegex} )", this.ObjectType); } + if (string.IsNullOrWhiteSpace(this.InternalName)) + { + throw new GraphTypeDeclarationException( + $"The schema template item identified by `{this.ObjectType.FriendlyName()}` and named '{this.Name}' on a schema " + + $"does not declare a valid internal name."); + } + foreach (var directive in this.AppliedDirectives) directive.ValidateOrThrow(); } @@ -124,10 +131,7 @@ public virtual void ValidateOrThrow() public SchemaItemPath Route { get; protected set; } /// - public abstract string InternalFullName { get; } - - /// - public abstract string InternalName { get; } + public string InternalName { get; protected set; } /// public ICustomAttributeProvider AttributeProvider { get; } diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/UnionGraphTypeTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/UnionGraphTypeTemplate.cs index 5965281d4..79cd7a571 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/UnionGraphTypeTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/UnionGraphTypeTemplate.cs @@ -51,12 +51,21 @@ protected override void ParseTemplateDefinition() if (_instance != null) { this.Route = new SchemaItemPath(SchemaItemPath.Join(SchemaItemCollections.Types, _instance.Name)); + this.InternalName = _instance.Name; } } } catch { } + + if (string.IsNullOrWhiteSpace(this.InternalName)) + { + // ad-hoc unions will be a flat instance of GraphUnionProxy, not a differentiated instance + // BUT internally it will always be guarunteed that the flat instance is instantiable + // and that a name will be defined so this "should" never run....best laid plans though, am i rite? + this.InternalName = _proxyType?.FriendlyName(); + } } /// @@ -78,12 +87,6 @@ public override void ValidateOrThrow() /// public override TypeKind Kind => TypeKind.UNION; - /// - public override string InternalFullName => _proxyType?.FriendlyName(true); - - /// - public override string InternalName => _proxyType?.Name; - /// public Type ProxyType => _proxyType; diff --git a/src/graphql-aspnet/Schemas/SchemaLanguageGenerator.cs b/src/graphql-aspnet/Schemas/SchemaLanguageGenerator.cs index ea4121ef0..cd082e67e 100644 --- a/src/graphql-aspnet/Schemas/SchemaLanguageGenerator.cs +++ b/src/graphql-aspnet/Schemas/SchemaLanguageGenerator.cs @@ -148,10 +148,10 @@ private string SerializeInputObject(object obj, IInputObjectGraphType inputObjec var getters = InstanceFactory.CreatePropertyGetterInvokerCollection(obj.GetType()); foreach (var field in inputObjectGraphType.Fields) { - if (!getters.ContainsKey(field.InternalFullName)) + if (!getters.ContainsKey(field.InternalName)) continue; - var getter = getters[field.InternalFullName]; + var getter = getters[field.InternalName]; builder.Append(field.Name); builder.Append(Constants.QueryLanguage.FieldValueSeperator); builder.Append(" "); diff --git a/src/graphql-aspnet/Schemas/Structural/EnumValueCollection.cs b/src/graphql-aspnet/Schemas/Structural/EnumValueCollection.cs index 0c5481cc6..4893ae636 100644 --- a/src/graphql-aspnet/Schemas/Structural/EnumValueCollection.cs +++ b/src/graphql-aspnet/Schemas/Structural/EnumValueCollection.cs @@ -51,13 +51,13 @@ public void Add(IEnumValue value) } _enumValuesByName.Add(value.Name, value); - _enumValuesByInternalLabel.Add(value.InternalLabel, value); + _enumValuesByInternalLabel.Add(value.DeclaredLabel, value); } /// - /// Removes the specified name if it exists. When found, the removed item is returned. + /// Removes the specified enum value if it exists. When found, the removed item is returned. /// - /// The name of the item to remove. + /// The name of the enum value, as it exists in the schema. /// IEnumValue. public IEnumValue Remove(string name) { @@ -66,8 +66,8 @@ public IEnumValue Remove(string name) var removedOption = _enumValuesByName[name]; _enumValuesByName.Remove(name); - if (_enumValuesByInternalLabel.ContainsKey(removedOption.InternalLabel)) - _enumValuesByInternalLabel.Remove(removedOption.InternalLabel); + if (_enumValuesByInternalLabel.ContainsKey(removedOption.DeclaredLabel)) + _enumValuesByInternalLabel.Remove(removedOption.DeclaredLabel); return removedOption; } @@ -83,9 +83,9 @@ public IEnumValue FindByEnumValue(object enumValue) if (_graphType.ValidateObject(enumValue)) { - var internalLabel = Enum.GetName(_graphType.ObjectType, enumValue); - if (_enumValuesByInternalLabel.ContainsKey(internalLabel)) - return _enumValuesByInternalLabel[internalLabel]; + var declaredLabel = Enum.GetName(_graphType.ObjectType, enumValue); + if (_enumValuesByInternalLabel.ContainsKey(declaredLabel)) + return _enumValuesByInternalLabel[declaredLabel]; } return null; diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Directive.cs b/src/graphql-aspnet/Schemas/TypeSystem/Directive.cs index 84bbad048..4278f19cb 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Directive.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Directive.cs @@ -55,7 +55,7 @@ public Directive( this.Publish = true; this.Route = Validation.ThrowIfNullOrReturn(route, nameof(route)); this.ObjectType = Validation.ThrowIfNullOrReturn(directiveType, nameof(directiveType)); - this.InternalFullName = this.ObjectType.FriendlyName(); + this.InternalName = this.ObjectType.FriendlyName(); this.AppliedDirectives = new AppliedDirectiveCollection(this); this.IsRepeatable = isRepeatable; @@ -102,7 +102,7 @@ public bool ValidateObject(object item) public Type ObjectType { get; } /// - public string InternalFullName { get; } + public string InternalName { get; } /// public bool IsRepeatable { get; set; } diff --git a/src/graphql-aspnet/Schemas/TypeSystem/EnumGraphType.cs b/src/graphql-aspnet/Schemas/TypeSystem/EnumGraphType.cs index e1ddabfeb..6fd7315d3 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/EnumGraphType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/EnumGraphType.cs @@ -59,7 +59,7 @@ public EnumGraphType( this.Route = Validation.ThrowIfNullOrReturn(route, nameof(route)); this.SourceResolver = Validation.ThrowIfNullOrReturn(resolver, nameof(resolver)); - this.InternalFullName = this.ObjectType.FriendlyName(); + this.InternalName = this.ObjectType.FriendlyName(); this.Publish = true; this.AppliedDirectives = directives?.Clone(this) ?? new AppliedDirectiveCollection(this); @@ -111,7 +111,7 @@ public virtual bool ValidateObject(object item) public virtual Type ObjectType { get; } /// - public virtual string InternalFullName { get; } + public virtual string InternalName { get; } /// public virtual bool IsVirtual => false; diff --git a/src/graphql-aspnet/Schemas/TypeSystem/EnumValue.cs b/src/graphql-aspnet/Schemas/TypeSystem/EnumValue.cs index 68d02caf4..c71225730 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/EnumValue.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/EnumValue.cs @@ -29,7 +29,9 @@ public class EnumValue : IEnumValue /// The description. /// The route path that uniquely identifies this enum option. /// The value of the enum as its declared in .NET. - /// A string representation of label applied to the enum value in .NET. + /// A string representation of label declared on the enum value in .NET. + /// The internal name assigned to this enum value. Typically the same as + /// but can be customized by the developer for reporting purposes. /// The set of directives to execute /// against this option when it is added to the schema. public EnumValue( @@ -38,7 +40,8 @@ public EnumValue( string description, SchemaItemPath route, object internalValue, - string internalLabel, + string declaredLabel, + string internalName, IAppliedDirectiveCollection directives = null) { this.Parent = Validation.ThrowIfNullOrReturn(parent, nameof(parent)); @@ -46,8 +49,9 @@ public EnumValue( this.Route = Validation.ThrowIfNullOrReturn(route, nameof(route)); this.Description = description?.Trim(); this.AppliedDirectives = directives?.Clone(this) ?? new AppliedDirectiveCollection(this); - this.InternalValue = Validation.ThrowIfNullOrReturn(internalValue, nameof(internalValue)); - this.InternalLabel = Validation.ThrowIfNullWhiteSpaceOrReturn(internalLabel, nameof(internalLabel)); + this.DeclaredValue = Validation.ThrowIfNullOrReturn(internalValue, nameof(internalValue)); + this.DeclaredLabel = Validation.ThrowIfNullWhiteSpaceOrReturn(declaredLabel, nameof(declaredLabel)); + this.InternalName = Validation.ThrowIfNullWhiteSpaceOrReturn(internalName, nameof(internalName)); if (Constants.QueryLanguage.IsReservedKeyword(this.Name)) { @@ -78,9 +82,12 @@ public EnumValue( public IEnumGraphType Parent { get; } /// - public object InternalValue { get; } + public object DeclaredValue { get; } /// - public string InternalLabel { get; } + public string DeclaredLabel { get; } + + /// + public string InternalName { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/TypeSystem/GraphFieldArgument.cs b/src/graphql-aspnet/Schemas/TypeSystem/GraphFieldArgument.cs index ed1e14d37..48313a57a 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/GraphFieldArgument.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/GraphFieldArgument.cs @@ -57,7 +57,7 @@ public GraphFieldArgument( this.Parent = Validation.ThrowIfNullOrReturn(parent, nameof(parent)); this.Name = Validation.ThrowIfNullWhiteSpaceOrReturn(argumentName, nameof(argumentName)); this.Route = Validation.ThrowIfNullOrReturn(route, nameof(route)); - this.InternalFullName = Validation.ThrowIfNullWhiteSpaceOrReturn(internalFullName, nameof(internalFullName)); + this.InternalName = Validation.ThrowIfNullWhiteSpaceOrReturn(internalFullName, nameof(internalFullName)); this.ParameterName = Validation.ThrowIfNullWhiteSpaceOrReturn(parameterName, nameof(parameterName)); this.TypeExpression = Validation.ThrowIfNullOrReturn(typeExpression, nameof(typeExpression)); this.ObjectType = Validation.ThrowIfNullOrReturn(objectType, nameof(objectType)); @@ -82,7 +82,7 @@ public IGraphArgument Clone(ISchemaItem parent) this.TypeExpression.Clone(), parent.Route.CreateChild(this.Name), this.ParameterName, - this.InternalFullName, + this.InternalName, this.ObjectType, this.HasDefaultValue, this.DefaultValue, @@ -109,7 +109,7 @@ public IGraphArgument Clone(ISchemaItem parent) public Type ObjectType { get; } /// - public string InternalFullName { get; } + public string InternalName { get; } /// public IAppliedDirectiveCollection AppliedDirectives { get; } diff --git a/src/graphql-aspnet/Schemas/TypeSystem/GraphOperation.cs b/src/graphql-aspnet/Schemas/TypeSystem/GraphOperation.cs index e607b234a..492a55fc5 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/GraphOperation.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/GraphOperation.cs @@ -67,6 +67,6 @@ public IGraphField Extend(IGraphField newField) public Type ObjectType => typeof(GraphOperation); /// - public string InternalFullName => $"{typeof(GraphOperation).FriendlyName()}.{this.OperationType}"; + public string InternalName => $"{typeof(GraphOperation).FriendlyName()}.{this.OperationType}"; } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/TypeSystem/InputGraphField.cs b/src/graphql-aspnet/Schemas/TypeSystem/InputGraphField.cs index da8eeed96..584be400b 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/InputGraphField.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/InputGraphField.cs @@ -67,7 +67,7 @@ public InputGraphField( this.AppliedDirectives = directives?.Clone(this) ?? new AppliedDirectiveCollection(this); - this.InternalFullName = declaredPropertyName; + this.InternalName = declaredPropertyName; this.HasDefaultValue = !isRequired; this.IsRequired = isRequired && this.TypeExpression.IsNonNullable; this.DefaultValue = defaultValue; @@ -113,7 +113,7 @@ public void AssignParent(IGraphType parent) /// is used in many exceptions and internal error messages. /// /// The fully qualified name of the proeprty this field was created from. - public string InternalFullName { get; } + public string InternalName { get; } /// public object DefaultValue { get; } diff --git a/src/graphql-aspnet/Schemas/TypeSystem/InputObjectGraphType.cs b/src/graphql-aspnet/Schemas/TypeSystem/InputObjectGraphType.cs index 501fdd9d9..8500732e7 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/InputObjectGraphType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/InputObjectGraphType.cs @@ -41,7 +41,7 @@ public InputObjectGraphType( { this.Name = Validation.ThrowIfNullWhiteSpaceOrReturn(name, nameof(name)); this.ObjectType = Validation.ThrowIfNullOrReturn(objectType, nameof(objectType)); - this.InternalFullName = this.ObjectType.FriendlyName(); + this.InternalName = this.ObjectType.FriendlyName(); this.Route = Validation.ThrowIfNullOrReturn(route, nameof(route)); this.AppliedDirectives = directives?.Clone(this) ?? new AppliedDirectiveCollection(this); this.Publish = true; @@ -68,7 +68,7 @@ public void AddField(IInputGraphField field) public Type ObjectType { get; } /// - public string InternalFullName { get; } + public string InternalName { get; } /// /// Gets the collection of fields, keyed on their name, of all the fields nested or contained within this field. diff --git a/src/graphql-aspnet/Schemas/TypeSystem/InterfaceGraphType.cs b/src/graphql-aspnet/Schemas/TypeSystem/InterfaceGraphType.cs index 6b91cb673..7fd4bb213 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/InterfaceGraphType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/InterfaceGraphType.cs @@ -43,7 +43,7 @@ public InterfaceGraphType( this.Name = Validation.ThrowIfNullOrReturn(name, nameof(name)); this.Route = Validation.ThrowIfNullOrReturn(route, nameof(route)); this.ObjectType = Validation.ThrowIfNullOrReturn(concreteType, nameof(concreteType)); - this.InternalFullName = this.ObjectType.FriendlyName(); + this.InternalName = this.ObjectType.FriendlyName(); this.InterfaceNames = new HashSet(); _fieldSet = new GraphFieldCollection(this); @@ -102,7 +102,7 @@ public bool ValidateObject(object item) public Type ObjectType { get; } /// - public virtual string InternalFullName { get; } + public virtual string InternalName { get; } /// public HashSet InterfaceNames { get; } diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/BaseIntrospectionObjectType.cs b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/BaseIntrospectionObjectType.cs index 42b6201d4..6aad89827 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/BaseIntrospectionObjectType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/BaseIntrospectionObjectType.cs @@ -47,6 +47,6 @@ public IGraphField Extend(IGraphField newField) public virtual Type ObjectType => this.GetType(); /// - public virtual string InternalFullName => this.ObjectType.FriendlyName(); + public virtual string InternalName => this.ObjectType.FriendlyName(); } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_DirectiveLocationType.cs b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_DirectiveLocationType.cs index e52702577..f9371da01 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_DirectiveLocationType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_DirectiveLocationType.cs @@ -47,6 +47,7 @@ public Introspection_DirectiveLocationType() description, this.Route.CreateChild(name), value, + fi.Name, name); this.AddOption(option); diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_TypeKindType.cs b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_TypeKindType.cs index 20ed5187d..2f0eb5f90 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_TypeKindType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_TypeKindType.cs @@ -47,6 +47,7 @@ public Introspection_TypeKindType() description, this.Route.CreateChild(name), value, + fi.Name, name); this.AddOption(option); diff --git a/src/graphql-aspnet/Schemas/TypeSystem/MethodGraphField.cs b/src/graphql-aspnet/Schemas/TypeSystem/MethodGraphField.cs index 1bb13eeb9..3fa2a6a9c 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/MethodGraphField.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/MethodGraphField.cs @@ -62,7 +62,7 @@ public MethodGraphField( this.Arguments = new GraphFieldArgumentCollection(this); this.ObjectType = Validation.ThrowIfNullOrReturn(objectType, nameof(objectType)); this.DeclaredReturnType = Validation.ThrowIfNullOrReturn(declaredReturnType, nameof(declaredReturnType)); - this.InternalFullName = Validation.ThrowIfNullWhiteSpaceOrReturn(internalFullName, nameof(internalFullName)); + this.InternalName = Validation.ThrowIfNullWhiteSpaceOrReturn(internalFullName, nameof(internalFullName)); this.AppliedDirectives = directives?.Clone(this) ?? new AppliedDirectiveCollection(this); @@ -150,7 +150,7 @@ protected virtual MethodGraphField CreateNewInstance(IGraphType parent) this.Name, this.TypeExpression.Clone(), parent.Route.CreateChild(this.Name), - this.InternalFullName, + this.InternalName, this.ObjectType, this.DeclaredReturnType, this.Mode, @@ -214,6 +214,6 @@ protected virtual MethodGraphField CreateNewInstance(IGraphType parent) public IAppliedDirectiveCollection AppliedDirectives { get; } /// - public string InternalFullName { get; } + public string InternalName { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/TypeSystem/ObjectGraphType.cs b/src/graphql-aspnet/Schemas/TypeSystem/ObjectGraphType.cs index 692323d47..2a35272b3 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/ObjectGraphType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/ObjectGraphType.cs @@ -40,7 +40,7 @@ public ObjectGraphType( : base(name, route, directives) { this.ObjectType = Validation.ThrowIfNullOrReturn(objectType, nameof(objectType)); - this.InternalFullName = this.ObjectType.FriendlyName(); + this.InternalName = this.ObjectType.FriendlyName(); this.GraphFieldCollection.AddField(new Introspection_TypeNameMetaField(name)); } @@ -61,6 +61,6 @@ public override bool ValidateObject(object item) public Type ObjectType { get; } /// - public string InternalFullName { get; } + public string InternalName { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/TypeSystem/PropertyGraphField.cs b/src/graphql-aspnet/Schemas/TypeSystem/PropertyGraphField.cs index 69e6e91a2..220028001 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/PropertyGraphField.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/PropertyGraphField.cs @@ -62,7 +62,7 @@ protected override MethodGraphField CreateNewInstance(IGraphType parent) this.Name, this.TypeExpression.Clone(), parent.Route.CreateChild(this.Name), - this.InternalFullName, + this.InternalName, this.ObjectType, this.DeclaredReturnType, this.Mode, diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/ScalarGraphTypeBase.cs b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/ScalarGraphTypeBase.cs index 99a8639f9..d5810aab8 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Scalars/ScalarGraphTypeBase.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Scalars/ScalarGraphTypeBase.cs @@ -41,7 +41,7 @@ protected ScalarGraphTypeBase( this.Name = Validation.ThrowIfNullWhiteSpaceOrReturn(name, nameof(name)); this.Route = new SchemaItemPath(SchemaItemCollections.Scalars, this.Name); this.ObjectType = Validation.ThrowIfNullOrReturn(primaryType, nameof(primaryType)); - this.InternalFullName = this.ObjectType.FriendlyName(); + this.InternalName = this.ObjectType.FriendlyName(); this.Publish = true; this.SourceResolver = this; this.AppliedDirectives = new AppliedDirectiveCollection(this); @@ -120,7 +120,7 @@ public virtual IScalarGraphType Clone(string newName) public virtual Type ObjectType { get; } /// - public virtual string InternalFullName { get; } + public virtual string InternalName { get; } /// public string Description { get; set; } diff --git a/src/graphql-aspnet/Schemas/TypeSystem/VirtualGraphField.cs b/src/graphql-aspnet/Schemas/TypeSystem/VirtualGraphField.cs index 377f6bd7b..5a2ce5cad 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/VirtualGraphField.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/VirtualGraphField.cs @@ -66,7 +66,7 @@ public VirtualGraphField( this.TypeExpression = new GraphTypeExpression(parentTypeName); this.Arguments = new GraphFieldArgumentCollection(this); this.Resolver = new GraphControllerRouteFieldResolver(new VirtualResolvedObject(this.TypeExpression.TypeName)); - this.InternalFullName = $"VirtualField_{this.Name}"; + this.InternalName = $"VirtualField_{this.Name}"; // fields made from controller route parameters have no policies directly unto themselves // any controller class level policies are individually added to fields they declare @@ -192,6 +192,6 @@ public virtual bool CanResolveForGraphType(IGraphType graphType) public IAppliedDirectiveCollection AppliedDirectives { get; } /// - public string InternalFullName { get; } + public string InternalName { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/TypeSystem/VirtualGraphFieldArgument.cs b/src/graphql-aspnet/Schemas/TypeSystem/VirtualGraphFieldArgument.cs index b8cd9db4e..fa9329e18 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/VirtualGraphFieldArgument.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/VirtualGraphFieldArgument.cs @@ -46,7 +46,7 @@ public VirtualGraphFieldArgument( { this.Parent = Validation.ThrowIfNullOrReturn(parent, nameof(parent)); this.ObjectType = Validation.ThrowIfNullOrReturn(concreteType, nameof(concreteType)); - this.InternalFullName = Validation.ThrowIfNullWhiteSpaceOrReturn(internalFullName, nameof(internalFullName)); + this.InternalName = Validation.ThrowIfNullWhiteSpaceOrReturn(internalFullName, nameof(internalFullName)); this.Name = Validation.ThrowIfNullWhiteSpaceOrReturn(name, nameof(name)); this.Route = Validation.ThrowIfNullOrReturn(route, nameof(route)); this.ParameterName = this.Name; @@ -70,7 +70,7 @@ public IGraphArgument Clone(ISchemaItem parent) public Type ObjectType { get; } /// - public string InternalFullName { get; } + public string InternalName { get; } /// public string Name { get; set; } diff --git a/src/graphql-aspnet/Schemas/TypeSystem/VirtualObjectGraphType.cs b/src/graphql-aspnet/Schemas/TypeSystem/VirtualObjectGraphType.cs index d6b62e62c..1f9bdeca2 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/VirtualObjectGraphType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/VirtualObjectGraphType.cs @@ -65,6 +65,6 @@ public IGraphField Extend(IGraphField newField) public Type ObjectType => typeof(VirtualObjectGraphType); /// - public string InternalFullName => typeof(VirtualObjectGraphType).FriendlyName(); + public string InternalName => typeof(VirtualObjectGraphType).FriendlyName(); } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/SubscriptionEnabledFieldFieldMakerTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/SubscriptionEnabledFieldFieldMakerTests.cs index 677c2eecd..dc3782d4e 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/SubscriptionEnabledFieldFieldMakerTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/SubscriptionEnabledFieldFieldMakerTests.cs @@ -30,7 +30,7 @@ public class SubscriptionEnabledFieldFieldMakerTests public void SubscriptionActionField_TransfersDirectives() { var mockController = new Mock(); - mockController.Setup(x => x.InternalFullName).Returns(typeof(SubscriptionTestController).FullName); + mockController.Setup(x => x.InternalName).Returns(typeof(SubscriptionTestController).FullName); mockController.Setup(x => x.InternalName).Returns(typeof(SubscriptionTestController).Name); mockController.Setup(x => x.Route).Returns(new SchemaItemPath("path0")); mockController.Setup(x => x.Name).Returns("path0"); diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/GraphActionTemplateTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/GraphActionTemplateTests.cs index 41afa1372..174ebffde 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/GraphActionTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/GraphActionTemplateTests.cs @@ -30,7 +30,7 @@ private SubscriptionControllerActionGraphFieldTemplate CreateActionTemplate(); - mockController.Setup(x => x.InternalFullName).Returns(typeof(TControllerType).FullName); + mockController.Setup(x => x.InternalName).Returns(typeof(TControllerType).FullName); mockController.Setup(x => x.InternalName).Returns(typeof(TControllerType).Name); mockController.Setup(x => x.Route).Returns(new SchemaItemPath("path0")); mockController.Setup(x => x.Name).Returns("path0"); @@ -56,7 +56,7 @@ public void ActionTemplate_Parse_BasicPropertySets() Assert.AreEqual(typeof(OneMethodSubscriptionController), action.Parent.ObjectType); Assert.AreEqual(SchemaItemCollections.Subscription, action.Route.RootCollection); Assert.AreEqual("[subscription]/path0/path1", action.Route.Path); - Assert.AreEqual($"{action.Parent.InternalFullName}.{nameof(OneMethodSubscriptionController.SingleMethod)}", action.InternalFullName); + Assert.AreEqual($"{action.Parent.InternalName}.{nameof(OneMethodSubscriptionController.SingleMethod)}", action.InternalName); Assert.AreEqual(methodInfo.ReflectedType, metaData.ParentObjectType); Assert.AreEqual("path0", action.Parent.Name); Assert.AreEqual(methodInfo, action.Method); diff --git a/src/unit-tests/graphql-aspnet-testframework/GraphQLTemplateHelper.cs b/src/unit-tests/graphql-aspnet-testframework/GraphQLTemplateHelper.cs index 59b798c3f..7e2789869 100644 --- a/src/unit-tests/graphql-aspnet-testframework/GraphQLTemplateHelper.cs +++ b/src/unit-tests/graphql-aspnet-testframework/GraphQLTemplateHelper.cs @@ -58,7 +58,7 @@ public static IGraphFieldTemplate CreateActionMethodTemplate(string template.ValidateOrThrow(); return template .FieldTemplates - .FirstOrDefault(x => x.Value.InternalName.Equals(methodName, StringComparison.OrdinalIgnoreCase)).Value; + .FirstOrDefault(x => x.Value.DeclaredName.Equals(methodName, StringComparison.OrdinalIgnoreCase)).Value; } /// diff --git a/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/DirectiveContextBuilder.cs b/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/DirectiveContextBuilder.cs index 4a94d92f5..646f61edb 100644 --- a/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/DirectiveContextBuilder.cs +++ b/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/DirectiveContextBuilder.cs @@ -95,14 +95,12 @@ public DirectiveContextBuilder( if (resolverMetadata != null) { _mockResolverMetadata = new Mock(); - _mockResolverMetadata.Setup(x => x.ParentInternalFullName).Returns(resolverMetadata.ParentInternalFullName); _mockResolverMetadata.Setup(x => x.ParentInternalName).Returns(resolverMetadata.ParentInternalName); _mockResolverMetadata.Setup(x => x.ParentObjectType).Returns(resolverMetadata.ParentObjectType); _mockResolverMetadata.Setup(x => x.ExpectedReturnType).Returns(resolverMetadata.ExpectedReturnType); _mockResolverMetadata.Setup(x => x.Method).Returns(resolverMetadata.Method); _mockResolverMetadata.Setup(x => x.IsAsyncField).Returns(resolverMetadata.IsAsyncField); _mockResolverMetadata.Setup(x => x.InternalName).Returns(resolverMetadata.InternalName); - _mockResolverMetadata.Setup(x => x.InternalFullName).Returns(resolverMetadata.InternalFullName); _mockResolverMetadata.Setup(x => x.InternalName).Returns(resolverMetadata.InternalName); _mockResolverMetadata.Setup(x => x.Parameters).Returns(resolverMetadata.Parameters); } diff --git a/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/FieldContextBuilder.cs b/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/FieldContextBuilder.cs index 88a9d5914..f27306bcc 100644 --- a/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/FieldContextBuilder.cs +++ b/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/FieldContextBuilder.cs @@ -104,14 +104,12 @@ public FieldContextBuilder( _mockRequest.Setup(x => x.InvocationContext).Returns(_mockInvocationContext.Object); _mockResolverMetaData = new Mock(); - _mockResolverMetaData.Setup(x => x.ParentInternalFullName).Returns(resolverMetadata.ParentInternalFullName); _mockResolverMetaData.Setup(x => x.ParentInternalName).Returns(resolverMetadata.ParentInternalName); _mockResolverMetaData.Setup(x => x.ParentObjectType).Returns(resolverMetadata.ParentObjectType); _mockResolverMetaData.Setup(x => x.ExpectedReturnType).Returns(resolverMetadata.ExpectedReturnType); _mockResolverMetaData.Setup(x => x.Method).Returns(resolverMetadata.Method); _mockResolverMetaData.Setup(x => x.IsAsyncField).Returns(resolverMetadata.IsAsyncField); _mockResolverMetaData.Setup(x => x.InternalName).Returns(resolverMetadata.InternalName); - _mockResolverMetaData.Setup(x => x.InternalFullName).Returns(resolverMetadata.InternalFullName); _mockResolverMetaData.Setup(x => x.InternalName).Returns(resolverMetadata.InternalName); _mockResolverMetaData.Setup(x => x.Parameters).Returns(resolverMetadata.Parameters); } diff --git a/src/unit-tests/graphql-aspnet-tests/Controllers/ActionResults/ActionResultTests.cs b/src/unit-tests/graphql-aspnet-tests/Controllers/ActionResults/ActionResultTests.cs index 478d9fb39..1fd4a6e7e 100644 --- a/src/unit-tests/graphql-aspnet-tests/Controllers/ActionResults/ActionResultTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Controllers/ActionResults/ActionResultTests.cs @@ -167,12 +167,12 @@ public async Task ObjectRetrunedGraph_ReturnsSameItemGivenToIt() } [Test] - public async Task RouteNotFound_ViaGraphAction_YieldsNegativeResult() + public async Task RouteNotFound_ViaResolverMetaData_WithThrownException_YieldsNegativeResult_AndThrowsExceptionWrappedException() { - var action = GraphQLTemplateHelper.CreateFieldTemplate(nameof(ActionableController.DoStuff)).CreateResolverMetaData(); + var resolverMetadata = GraphQLTemplateHelper.CreateFieldTemplate(nameof(ActionableController.DoStuff)).CreateResolverMetaData(); var exception = new Exception("fail"); - var actionResult = new RouteNotFoundGraphActionResult(action, exception); + var actionResult = new RouteNotFoundGraphActionResult(resolverMetadata, exception); var context = this.CreateResolutionContext(); await actionResult.CompleteAsync(context); @@ -180,7 +180,11 @@ public async Task RouteNotFound_ViaGraphAction_YieldsNegativeResult() Assert.IsTrue(context.IsCancelled); Assert.AreEqual(1, context.Messages.Count); Assert.AreEqual(Constants.ErrorCodes.INVALID_ROUTE, context.Messages[0].Code); - Assert.IsTrue(context.Messages[0].Message.Contains(action.InternalName)); + + // exception message should have the resolver name in it + Assert.IsTrue(context.Messages[0].Message.Contains(context.Route.Name)); + Assert.IsTrue(context.Messages[0].Exception.Message.Contains(resolverMetadata.InternalName)); + Assert.AreEqual(context.Messages[0].Exception.InnerException, exception); } [Test] diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultScalarTypeProviderTestData/ScalarTestBase.cs b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultScalarTypeProviderTestData/ScalarTestBase.cs index 7be9102bc..6bb0e99d0 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultScalarTypeProviderTestData/ScalarTestBase.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultScalarTypeProviderTestData/ScalarTestBase.cs @@ -27,7 +27,7 @@ protected ScalarTestBase() this.Publish = true; this.IsVirtual = false; this.ObjectType = typeof(ScalarDataType); - this.InternalFullName = "myInternalName"; + this.InternalName = "myInternalName"; this.Route = new SchemaItemPath(AspNet.Execution.SchemaItemCollections.Types, "myScalar"); this.Name = "MyScalar"; this.Description = "my description"; @@ -57,7 +57,7 @@ public virtual IScalarGraphType Clone(string newName) public Type ObjectType { get; set; } - public string InternalFullName { get; set; } + public string InternalName { get; set; } public SchemaItemPath Route { get; set; } diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/IntrospectionTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/IntrospectionTests.cs index 83529f943..fe53cd66d 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/IntrospectionTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/IntrospectionTests.cs @@ -1165,7 +1165,7 @@ public async Task DeprecatedLateBoundEnumValue_ReturnsTrueDeprecationFlag() schemaItem != null && schemaItem is IEnumValue ev && ev.Parent.ObjectType == typeof(IntrospectableEnum) - && Convert.ToInt32(ev.InternalValue) == (int)IntrospectableEnum.Value1); + && Convert.ToInt32(ev.DeclaredValue) == (int)IntrospectableEnum.Value1); }) .Build(); diff --git a/src/unit-tests/graphql-aspnet-tests/Logging/ActionMethodModelStateValidatedLogEntryTests.cs b/src/unit-tests/graphql-aspnet-tests/Logging/ActionMethodModelStateValidatedLogEntryTests.cs index 91ab9a68b..9e5bd3973 100644 --- a/src/unit-tests/graphql-aspnet-tests/Logging/ActionMethodModelStateValidatedLogEntryTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Logging/ActionMethodModelStateValidatedLogEntryTests.cs @@ -47,14 +47,14 @@ private ExecutionArgument CreateArgument( } private void ValidateModelDictionaryToLogEntry( - IGraphFieldResolverMetaData graphMethod, + IGraphFieldResolverMetaData resolverMetaData, IGraphFieldRequest fieldRequest, InputModelStateDictionary dictionary, ActionMethodModelStateValidatedLogEntry logEntry) { Assert.AreEqual(fieldRequest.Id.ToString(), logEntry.PipelineRequestId); - Assert.AreEqual(graphMethod.ParentInternalFullName, logEntry.ControllerName); - Assert.AreEqual(graphMethod.InternalName, logEntry.ActionName); + Assert.AreEqual(resolverMetaData.ParentInternalName, logEntry.ControllerName); + Assert.AreEqual(resolverMetaData.InternalName, logEntry.ActionName); Assert.AreEqual(dictionary.IsValid, logEntry.ModelDataIsValid); foreach (var kvp in dictionary) diff --git a/src/unit-tests/graphql-aspnet-tests/Logging/GeneralEventLogEntryPropertyChecks.cs b/src/unit-tests/graphql-aspnet-tests/Logging/GeneralEventLogEntryPropertyChecks.cs index b476b2830..cd896b014 100644 --- a/src/unit-tests/graphql-aspnet-tests/Logging/GeneralEventLogEntryPropertyChecks.cs +++ b/src/unit-tests/graphql-aspnet-tests/Logging/GeneralEventLogEntryPropertyChecks.cs @@ -399,18 +399,21 @@ public void ActionMethodInvocationStartedLogEntry() var server = new TestServerBuilder(TestOptions.UseCodeDeclaredNames) .AddType() .Build(); - var graphMethod = GraphQLTemplateHelper.CreateActionMethodTemplate(nameof(LogTestController.ExecuteField2)).CreateResolverMetaData(); + var resolverMetaData = GraphQLTemplateHelper + .CreateActionMethodTemplate(nameof(LogTestController.ExecuteField2)) + .CreateResolverMetaData(); + var package = server.CreateFieldContextBuilder( nameof(LogTestController.ExecuteField2)); var fieldRequest = package.FieldRequest.Object; - var entry = new ActionMethodInvocationStartedLogEntry(graphMethod, fieldRequest); + var entry = new ActionMethodInvocationStartedLogEntry(resolverMetaData, fieldRequest); Assert.AreEqual(LogEventIds.ControllerInvocationStarted.Id, entry.EventId); Assert.AreEqual(fieldRequest.Id.ToString(), entry.PipelineRequestId); - Assert.AreEqual(graphMethod.ParentInternalFullName, entry.ControllerName); - Assert.AreEqual(graphMethod.InternalName, entry.ActionName); - Assert.AreEqual(graphMethod.IsAsyncField, entry.IsAsync); + Assert.AreEqual(resolverMetaData.ParentInternalName, entry.ControllerName); + Assert.AreEqual(resolverMetaData.InternalName, entry.ActionName); + Assert.AreEqual(resolverMetaData.IsAsyncField, entry.IsAsync); Assert.IsNotNull(entry.ToString()); } @@ -433,7 +436,7 @@ public void ActionMethodInvocationCompletedLogEntry() Assert.AreEqual(LogEventIds.ControllerInvocationCompleted.Id, entry.EventId); Assert.AreEqual(fieldRequest.Id.ToString(), entry.PipelineRequestId); - Assert.AreEqual(metaData.ParentInternalFullName, entry.ControllerName); + Assert.AreEqual(metaData.ParentInternalName, entry.ControllerName); Assert.AreEqual(metaData.InternalName, entry.ActionName); Assert.AreEqual(result.GetType().FriendlyName(true), entry.ResultTypeName); Assert.IsNotNull(entry.ToString()); @@ -459,7 +462,7 @@ public void ActionMethodInvocationExceptionLogEntry() Assert.AreEqual(LogEventIds.ControllerInvocationException.Id, entry.EventId); Assert.AreEqual(fieldRequest.Id.ToString(), entry.PipelineRequestId); - Assert.AreEqual(metaData.ParentInternalFullName, entry.ControllerTypeName); + Assert.AreEqual(metaData.ParentInternalName, entry.ControllerTypeName); Assert.AreEqual(metaData.InternalName, entry.ActionName); Assert.IsNotNull(entry.ToString()); @@ -490,7 +493,7 @@ public void ActionMethodUnhandledExceptionLogEntry() Assert.AreEqual(LogEventIds.ControllerUnhandledException.Id, entry.EventId); Assert.AreEqual(fieldRequest.Id.ToString(), entry.PipelineRequestId); - Assert.AreEqual(metaData.ParentInternalFullName, entry.ControllerTypeName); + Assert.AreEqual(metaData.ParentInternalName, entry.ControllerTypeName); Assert.AreEqual(metaData.InternalName, entry.ActionName); Assert.IsNotNull(entry.ToString()); @@ -506,7 +509,7 @@ public void TypeSystemDirectiveAppliedLogEntry() { var directive = new Mock(); directive.Setup(x => x.Name).Returns("The Directive"); - directive.Setup(x => x.InternalFullName).Returns("The Directive Internal"); + directive.Setup(x => x.InternalName).Returns("The Directive Internal"); var item = new Mock(); item.Setup(x => x.Route).Returns(new AspNet.Schemas.Structural.SchemaItemPath(SchemaItemCollections.Types, "path1")); @@ -515,7 +518,7 @@ public void TypeSystemDirectiveAppliedLogEntry() Assert.AreEqual(LogEventIds.TypeSystemDirectiveApplied.Id, entry.EventId); Assert.AreEqual(directive.Object.Name, entry.DirectiveName); - Assert.AreEqual(directive.Object.InternalFullName, entry.DirectiveInternalName); + Assert.AreEqual(directive.Object.InternalName, entry.DirectiveInternalName); Assert.AreEqual(item.Object.Route.Path, entry.SchemaItemPath); Assert.AreEqual(typeof(GraphSchema).FriendlyName(true), entry.SchemaTypeName); } @@ -525,7 +528,7 @@ public void ExecutionDirectiveAppliedLogEntry() { var directive = new Mock(); directive.Setup(x => x.Name).Returns("The Directive"); - directive.Setup(x => x.InternalFullName).Returns("The Directive Internal"); + directive.Setup(x => x.InternalName).Returns("The Directive Internal"); var docPart = new DocumentOperation( new Mock().Object, @@ -539,7 +542,7 @@ public void ExecutionDirectiveAppliedLogEntry() Assert.AreEqual(LogEventIds.ExecutionDirectiveApplied.Id, entry.EventId); Assert.AreEqual(directive.Object.Name, entry.DirectiveName); - Assert.AreEqual(directive.Object.InternalFullName, entry.DirectiveInternalName); + Assert.AreEqual(directive.Object.InternalName, entry.DirectiveInternalName); Assert.AreEqual(DirectiveLocation.QUERY.ToString(), entry.DirectiveLocation); Assert.AreEqual(typeof(GraphSchema).FriendlyName(true), entry.SchemaTypeName); Assert.AreEqual(33, entry.SourceLine); diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/EnumValueCollectionTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/EnumValueCollectionTests.cs index 9226d9a79..726c2d0e8 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/EnumValueCollectionTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/EnumValueCollectionTests.cs @@ -36,13 +36,13 @@ public void Add_DuplicateEnumValueNameThrowsException() var enumValue = new Mock(); enumValue.Setup(x => x.Name).Returns("VALUE1"); - enumValue.Setup(x => x.InternalValue).Returns(EnumValueTestEnum.Value1); - enumValue.Setup(x => x.InternalLabel).Returns(EnumValueTestEnum.Value1.ToString()); + enumValue.Setup(x => x.DeclaredValue).Returns(EnumValueTestEnum.Value1); + enumValue.Setup(x => x.DeclaredLabel).Returns(EnumValueTestEnum.Value1.ToString()); var enumValue2 = new Mock(); enumValue2.Setup(x => x.Name).Returns("VALUE1"); - enumValue2.Setup(x => x.InternalValue).Returns(EnumValueTestEnum.Value1); - enumValue.Setup(x => x.InternalLabel).Returns(EnumValueTestEnum.Value1.ToString()); + enumValue2.Setup(x => x.DeclaredValue).Returns(EnumValueTestEnum.Value1); + enumValue.Setup(x => x.DeclaredLabel).Returns(EnumValueTestEnum.Value1.ToString()); var collection = new EnumValueCollection(owner.Object); collection.Add(enumValue.Object); @@ -69,8 +69,8 @@ public void FindEnumValue(EnumValueTestEnum testValue, bool doesValidate, bool s var enumValue = new Mock(); enumValue.Setup(x => x.Name).Returns("VALUE1"); - enumValue.Setup(x => x.InternalValue).Returns(EnumValueTestEnum.Value1); - enumValue.Setup(x => x.InternalLabel).Returns(EnumValueTestEnum.Value1.ToString()); + enumValue.Setup(x => x.DeclaredValue).Returns(EnumValueTestEnum.Value1); + enumValue.Setup(x => x.DeclaredLabel).Returns(EnumValueTestEnum.Value1.ToString()); var collection = new EnumValueCollection(owner.Object); collection.Add(enumValue.Object); @@ -93,8 +93,8 @@ public void FindEnumValue_NullPassed_RetunsNull() var enumValue = new Mock(); enumValue.Setup(x => x.Name).Returns("VALUE1"); - enumValue.Setup(x => x.InternalValue).Returns(EnumValueTestEnum.Value1); - enumValue.Setup(x => x.InternalLabel).Returns(EnumValueTestEnum.Value1.ToString()); + enumValue.Setup(x => x.DeclaredValue).Returns(EnumValueTestEnum.Value1); + enumValue.Setup(x => x.DeclaredLabel).Returns(EnumValueTestEnum.Value1.ToString()); var collection = new EnumValueCollection(owner.Object); collection.Add(enumValue.Object); @@ -114,8 +114,8 @@ public void ContainsKey(string testValue, bool shouldBeFound) var enumValue = new Mock(); enumValue.Setup(x => x.Name).Returns("VALUE1"); - enumValue.Setup(x => x.InternalValue).Returns(EnumValueTestEnum.Value1); - enumValue.Setup(x => x.InternalLabel).Returns(EnumValueTestEnum.Value1.ToString()); + enumValue.Setup(x => x.DeclaredValue).Returns(EnumValueTestEnum.Value1); + enumValue.Setup(x => x.DeclaredLabel).Returns(EnumValueTestEnum.Value1.ToString()); var collection = new EnumValueCollection(owner.Object); collection.Add(enumValue.Object); @@ -135,8 +135,8 @@ public void ThisByName(string name, bool shouldBeFound) var enumValue = new Mock(); enumValue.Setup(x => x.Name).Returns("VALUE1"); - enumValue.Setup(x => x.InternalValue).Returns(EnumValueTestEnum.Value1); - enumValue.Setup(x => x.InternalLabel).Returns(EnumValueTestEnum.Value1.ToString()); + enumValue.Setup(x => x.DeclaredValue).Returns(EnumValueTestEnum.Value1); + enumValue.Setup(x => x.DeclaredLabel).Returns(EnumValueTestEnum.Value1.ToString()); var collection = new EnumValueCollection(owner.Object); collection.Add(enumValue.Object); @@ -167,8 +167,8 @@ public void TryGetValue(string name, bool shouldBeFound) var enumValue = new Mock(); enumValue.Setup(x => x.Name).Returns("VALUE1"); - enumValue.Setup(x => x.InternalValue).Returns(EnumValueTestEnum.Value1); - enumValue.Setup(x => x.InternalLabel).Returns(EnumValueTestEnum.Value1.ToString()); + enumValue.Setup(x => x.DeclaredValue).Returns(EnumValueTestEnum.Value1); + enumValue.Setup(x => x.DeclaredLabel).Returns(EnumValueTestEnum.Value1.ToString()); var collection = new EnumValueCollection(owner.Object); collection.Add(enumValue.Object); @@ -196,8 +196,8 @@ public void Remove_ValidValueIsRemoved() var enumValue = new Mock(); enumValue.Setup(x => x.Name).Returns("VALUE1"); - enumValue.Setup(x => x.InternalValue).Returns(EnumValueTestEnum.Value1); - enumValue.Setup(x => x.InternalLabel).Returns(EnumValueTestEnum.Value1.ToString()); + enumValue.Setup(x => x.DeclaredValue).Returns(EnumValueTestEnum.Value1); + enumValue.Setup(x => x.DeclaredLabel).Returns(EnumValueTestEnum.Value1.ToString()); var collection = new EnumValueCollection(owner.Object); collection.Add(enumValue.Object); @@ -216,8 +216,8 @@ public void Remove_InvalidValueIsIgnored() var enumValue = new Mock(); enumValue.Setup(x => x.Name).Returns("VALUE1"); - enumValue.Setup(x => x.InternalValue).Returns(EnumValueTestEnum.Value1); - enumValue.Setup(x => x.InternalLabel).Returns(EnumValueTestEnum.Value1.ToString()); + enumValue.Setup(x => x.DeclaredValue).Returns(EnumValueTestEnum.Value1); + enumValue.Setup(x => x.DeclaredLabel).Returns(EnumValueTestEnum.Value1.ToString()); var collection = new EnumValueCollection(owner.Object); collection.Add(enumValue.Object); diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/FieldMaker_InputFieldTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/FieldMaker_InputFieldTests.cs index 051311d1a..9159c065a 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/FieldMaker_InputFieldTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/FieldMaker_InputFieldTests.cs @@ -38,7 +38,7 @@ public void Parse_NotRequiredValueTypePropertyCheck() // non-nullable value type Assert.AreEqual("Int!", graphField.TypeExpression.ToString()); Assert.AreEqual("[type]/Input_InputTestObject/NotRequiredValueTypeField", graphField.Route.ToString()); - Assert.AreEqual("NotRequiredValueTypeField", graphField.InternalFullName); + Assert.AreEqual("NotRequiredValueTypeField", graphField.InternalName); Assert.AreEqual(typeof(int), graphField.DeclaredReturnType); Assert.AreEqual(1, graphField.AppliedDirectives.Count); @@ -63,7 +63,7 @@ public void Parse_RequiredValueTypePropertyCheck() Assert.AreEqual("Int!", graphField.TypeExpression.ToString()); Assert.AreEqual("[type]/Input_InputTestObject/RequiredValueTypeField", graphField.Route.ToString()); - Assert.AreEqual("RequiredValueTypeField", graphField.InternalFullName); + Assert.AreEqual("RequiredValueTypeField", graphField.InternalName); Assert.AreEqual(typeof(int), graphField.DeclaredReturnType); Assert.AreEqual(0, graphField.AppliedDirectives.Count); @@ -89,7 +89,7 @@ public void Parse_NotRequiredReferenceTypePropertyCheck() // meaning the type expression should also be "nullable" Assert.AreEqual("Input_TwoPropertyObject", graphField.TypeExpression.ToString()); Assert.AreEqual("[type]/Input_InputTestObject/NotRequiredReferenceTypeField", graphField.Route.ToString()); - Assert.AreEqual("NotRequiredReferenceTypeField", graphField.InternalFullName); + Assert.AreEqual("NotRequiredReferenceTypeField", graphField.InternalName); Assert.AreEqual(typeof(TwoPropertyObject), graphField.DeclaredReturnType); Assert.AreEqual(0, graphField.AppliedDirectives.Count); @@ -117,7 +117,7 @@ public void Parse_RequiredReferenceTypePropertyCheck() // the type expression is automatically hoisted to be "non-nullable" Assert.AreEqual("Input_TwoPropertyObject", graphField.TypeExpression.ToString()); Assert.AreEqual("[type]/Input_InputTestObject/RequiredReferenceTypeField", graphField.Route.ToString()); - Assert.AreEqual("RequiredReferenceTypeField", graphField.InternalFullName); + Assert.AreEqual("RequiredReferenceTypeField", graphField.InternalName); Assert.AreEqual(typeof(TwoPropertyObject), graphField.DeclaredReturnType); Assert.AreEqual(0, graphField.AppliedDirectives.Count); @@ -143,7 +143,7 @@ public void Parse_RequiredNonNullableReferenceTypePropertyCheck() // the type expression is automatically hoisted to be "non-nullable" Assert.AreEqual("Input_TwoPropertyObject!", graphField.TypeExpression.ToString()); Assert.AreEqual("[type]/Input_InputTestObject/RequiredReferenceExplicitNonNullTypeField", graphField.Route.ToString()); - Assert.AreEqual("RequiredReferenceExplicitNonNullTypeField", graphField.InternalFullName); + Assert.AreEqual("RequiredReferenceExplicitNonNullTypeField", graphField.InternalName); Assert.AreEqual(typeof(TwoPropertyObject), graphField.DeclaredReturnType); Assert.AreEqual(0, graphField.AppliedDirectives.Count); @@ -168,7 +168,7 @@ public void Parse_RequiredGraphIdPropertyCheck() // scalar is required by default Assert.AreEqual("ID!", graphField.TypeExpression.ToString()); Assert.AreEqual("[type]/Input_InputTestObject/GraphIdRequired", graphField.Route.ToString()); - Assert.AreEqual("GraphIdRequired", graphField.InternalFullName); + Assert.AreEqual("GraphIdRequired", graphField.InternalName); Assert.AreEqual(typeof(GraphId), graphField.DeclaredReturnType); Assert.AreEqual(0, graphField.AppliedDirectives.Count); @@ -192,7 +192,7 @@ public void Parse_NotRequiredGraphIdPropertyCheck() Assert.AreEqual("ID!", graphField.TypeExpression.ToString()); Assert.AreEqual("[type]/Input_InputTestObject/GraphIdNotRequired", graphField.Route.ToString()); - Assert.AreEqual("GraphIdNotRequired", graphField.InternalFullName); + Assert.AreEqual("GraphIdNotRequired", graphField.InternalName); Assert.AreEqual(typeof(GraphId), graphField.DeclaredReturnType); Assert.AreEqual(0, graphField.AppliedDirectives.Count); @@ -216,7 +216,7 @@ public void Parse_NotRequiredNullableGraphIdPropertyCheck() Assert.AreEqual("ID", graphField.TypeExpression.ToString()); Assert.AreEqual("[type]/Input_InputTestObject/GraphIdNullable", graphField.Route.ToString()); - Assert.AreEqual("GraphIdNullable", graphField.InternalFullName); + Assert.AreEqual("GraphIdNullable", graphField.InternalName); Assert.AreEqual(typeof(GraphId?), graphField.DeclaredReturnType); Assert.AreEqual(0, graphField.AppliedDirectives.Count); diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/FieldMaker_StandardFieldTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/FieldMaker_StandardFieldTests.cs index 3c7ad638f..f720be41a 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/FieldMaker_StandardFieldTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/FieldMaker_StandardFieldTests.cs @@ -127,7 +127,7 @@ public void PropertyGraphField_DefaultValuesCheck() var obj = new Mock(); obj.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/Item0")); - obj.Setup(x => x.InternalFullName).Returns("LongItem0"); + obj.Setup(x => x.InternalName).Returns("LongItem0"); obj.Setup(x => x.InternalName).Returns("Item0"); obj.Setup(x => x.ObjectType).Returns(typeof(SimplePropertyObject)); @@ -148,7 +148,7 @@ public void PropertyGraphField_GraphName_OverridesDefaultName() { var obj = new Mock(); obj.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/Item0")); - obj.Setup(x => x.InternalFullName).Returns("LongItem0"); + obj.Setup(x => x.InternalName).Returns("LongItem0"); obj.Setup(x => x.InternalName).Returns("Item0"); obj.Setup(x => x.ObjectType).Returns(typeof(SimplePropertyObject)); @@ -173,7 +173,7 @@ public void PropertyGraphField_DirectivesAreAppliedToCreatedField() var server = new TestServerBuilder().Build(); var obj = new Mock(); obj.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/Item0")); - obj.Setup(x => x.InternalFullName).Returns("LongItem0"); + obj.Setup(x => x.InternalName).Returns("LongItem0"); obj.Setup(x => x.InternalName).Returns("Item0"); obj.Setup(x => x.ObjectType).Returns(typeof(SimplePropertyObject)); @@ -199,7 +199,7 @@ public void MethodGraphField_DirectivesAreAppliedToCreatedField() var server = new TestServerBuilder().Build(); var obj = new Mock(); obj.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/Item0")); - obj.Setup(x => x.InternalFullName).Returns("LongItem0"); + obj.Setup(x => x.InternalName).Returns("LongItem0"); obj.Setup(x => x.InternalName).Returns("Item0"); obj.Setup(x => x.ObjectType).Returns(typeof(ObjectDirectiveTestItem)); @@ -225,7 +225,7 @@ public void Arguments_DirectivesAreApplied() var server = new TestServerBuilder().Build(); var obj = new Mock(); obj.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/Item0")); - obj.Setup(x => x.InternalFullName).Returns("LongItem0"); + obj.Setup(x => x.InternalName).Returns("LongItem0"); obj.Setup(x => x.InternalName).Returns("Item0"); obj.Setup(x => x.ObjectType).Returns(typeof(ObjectDirectiveTestItem)); @@ -309,7 +309,7 @@ public void Arguments_ArgumentBindingRuleTests(SchemaArgumentBindingRules bindin var obj = new Mock(); obj.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/Item0")); - obj.Setup(x => x.InternalFullName).Returns("LongItem0"); + obj.Setup(x => x.InternalName).Returns("LongItem0"); obj.Setup(x => x.InternalName).Returns("Item0"); obj.Setup(x => x.ObjectType).Returns(typeof(ObjectWithAttributedFieldArguments)); diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionMethodTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionMethodTemplateTests.cs index 6d13e11c8..5d4fbba09 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionMethodTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionMethodTemplateTests.cs @@ -30,7 +30,7 @@ private ControllerActionGraphFieldTemplate CreateActionTemplate where TControllerType : GraphController { var mockController = new Mock(); - mockController.Setup(x => x.InternalFullName).Returns(typeof(TControllerType).Name); + mockController.Setup(x => x.InternalName).Returns(typeof(TControllerType).Name); mockController.Setup(x => x.Route).Returns(new SchemaItemPath("path0")); mockController.Setup(x => x.Name).Returns("path0"); mockController.Setup(x => x.ObjectType).Returns(typeof(TControllerType)); @@ -55,7 +55,7 @@ public void ActionTemplate_Parse_BasicPropertySets() Assert.AreEqual(typeof(OneMethodController), action.Parent.ObjectType); Assert.AreEqual(SchemaItemCollections.Query, action.Route.RootCollection); Assert.AreEqual("[query]/path0/path1", action.Route.Path); - Assert.AreEqual($"{nameof(OneMethodController)}.{nameof(OneMethodController.MethodWithBasicAttribtributes)}", action.InternalFullName); + Assert.AreEqual($"{nameof(OneMethodController)}.{nameof(OneMethodController.MethodWithBasicAttribtributes)}", action.InternalName); Assert.AreEqual(methodInfo.ReflectedType, action.Parent.ObjectType); Assert.AreEqual("path0", action.Parent.Name); Assert.AreEqual(methodInfo, action.Method); diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/AppliedDirectiveTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/AppliedDirectiveTemplateTests.cs index 0ad14fc04..1e7887234 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/AppliedDirectiveTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/AppliedDirectiveTemplateTests.cs @@ -25,7 +25,7 @@ public class AppliedDirectiveTemplateTests public void PropertyCheck() { var owner = new Mock(); - owner.Setup(x => x.InternalFullName).Returns("OWNER"); + owner.Setup(x => x.InternalName).Returns("OWNER"); var template = new AppliedDirectiveTemplate( owner.Object, typeof(DirectiveWithArgs), @@ -43,7 +43,7 @@ public void PropertyCheck() public void NulLTemplateType_ThrowsException() { var owner = new Mock(); - owner.Setup(x => x.InternalFullName).Returns("OWNER"); + owner.Setup(x => x.InternalName).Returns("OWNER"); var template = new AppliedDirectiveTemplate( owner.Object, null as Type, @@ -61,7 +61,7 @@ public void NulLTemplateType_ThrowsException() public void NullName_ThrowsException() { var owner = new Mock(); - owner.Setup(x => x.InternalFullName).Returns("OWNER"); + owner.Setup(x => x.InternalName).Returns("OWNER"); var template = new AppliedDirectiveTemplate( owner.Object, null as string, @@ -79,7 +79,7 @@ public void NullName_ThrowsException() public void EmptyName_ThrowsException() { var owner = new Mock(); - owner.Setup(x => x.InternalFullName).Returns("OWNER"); + owner.Setup(x => x.InternalName).Returns("OWNER"); var template = new AppliedDirectiveTemplate( owner.Object, string.Empty, @@ -97,7 +97,7 @@ public void EmptyName_ThrowsException() public void NonDirectiveType_ThrowsException() { var owner = new Mock(); - owner.Setup(x => x.InternalFullName).Returns("OWNER"); + owner.Setup(x => x.InternalName).Returns("OWNER"); var template = new AppliedDirectiveTemplate( owner.Object, typeof(AppliedDirectiveTemplateTests), diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ArgumentTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ArgumentTemplateTests.cs index 84d6f73b8..9afed820a 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ArgumentTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ArgumentTemplateTests.cs @@ -37,7 +37,7 @@ private GraphArgumentTemplate ExtractParameterTemplate(string paramName, out Par .FirstOrDefault(x => x.Name == paramName); var mockMethod = new Mock(); - mockMethod.Setup(x => x.InternalFullName) + mockMethod.Setup(x => x.InternalName) .Returns($"{nameof(ParameterTestClass)}.{nameof(ParameterTestClass.TestMethod)}"); mockMethod.Setup(x => x.ObjectType).Returns(typeof(ParameterTestClass)); mockMethod.Setup(x => x.Arguments).Returns(new List()); @@ -64,8 +64,9 @@ public void StringParam_ParsesCorrectly() Assert.AreEqual(null, template.Description); Assert.IsEmpty((IEnumerable)template.TypeExpression.Wrappers); Assert.IsNull(template.DefaultValue); - Assert.AreEqual($"{nameof(ParameterTestClass)}.{nameof(ParameterTestClass.TestMethod)}.stringArg", template.InternalFullName); - Assert.AreEqual("stringArg", template.InternalName); + Assert.AreEqual($"{nameof(ParameterTestClass)}.{nameof(ParameterTestClass.TestMethod)}.stringArg", template.InternalName); + Assert.AreEqual("stringArg", template.ParameterName); + Assert.AreEqual("ParameterTestClass.TestMethod.stringArg", template.InternalName); } [Test] diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveMethodTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveMethodTemplateTests.cs index 05e7aeccf..6cae8e70f 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveMethodTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveMethodTemplateTests.cs @@ -30,7 +30,7 @@ public void SimpleDescriptor_AllDefaults_GeneralPropertyCheck() .GetMethod(nameof(SimpleExecutableDirective.Execute)); var mock = new Mock(); - mock.Setup(x => x.InternalFullName).Returns("Simple"); + mock.Setup(x => x.InternalName).Returns("Simple"); var route = new SchemaItemPath(SchemaItemCollections.Directives, "Simple"); mock.Setup(x => x.Route).Returns(route); var template = new GraphDirectiveMethodTemplate(mock.Object, method); @@ -42,7 +42,7 @@ public void SimpleDescriptor_AllDefaults_GeneralPropertyCheck() Assert.AreEqual("IGraphActionResult (object source, int arg1, string arg2)", template.MethodSignature); Assert.AreEqual(nameof(SimpleExecutableDirective.Execute), template.Name); - Assert.AreEqual($"Simple.{nameof(SimpleExecutableDirective.Execute)}", template.InternalFullName); + Assert.AreEqual($"Simple.{nameof(SimpleExecutableDirective.Execute)}", template.InternalName); Assert.IsTrue(template.IsAsyncField); Assert.AreEqual(typeof(IGraphActionResult), template.ObjectType); Assert.AreEqual(DirectiveLocation.FIELD, template.Locations); @@ -67,7 +67,7 @@ public void MethodWithSkipAttached_ThrowsException() .GetMethod(nameof(TestDirectiveMethodTemplateContainer.SkippedMethod)); var mock = new Mock(); - mock.Setup(x => x.InternalFullName).Returns("Simple"); + mock.Setup(x => x.InternalName).Returns("Simple"); var route = new SchemaItemPath(SchemaItemCollections.Directives, "Simple"); mock.Setup(x => x.Route).Returns(route); var template = new GraphDirectiveMethodTemplate(mock.Object, method); @@ -86,7 +86,7 @@ public void InvalidReturnType_ThrowsException() .GetMethod(nameof(TestDirectiveMethodTemplateContainer.IncorrrectReturnType)); var mock = new Mock(); - mock.Setup(x => x.InternalFullName).Returns("Simple"); + mock.Setup(x => x.InternalName).Returns("Simple"); var route = new SchemaItemPath(SchemaItemCollections.Directives, "Simple"); mock.Setup(x => x.Route).Returns(route); @@ -105,7 +105,7 @@ public void AsyncMethodWithNoReturnType_ThrowsException() .GetMethod(nameof(TestDirectiveMethodTemplateContainer2.InvalidTaskReference)); var mock = new Mock(); - mock.Setup(x => x.InternalFullName).Returns("Simple"); + mock.Setup(x => x.InternalName).Returns("Simple"); var route = new SchemaItemPath(SchemaItemCollections.Directives, "Simple"); mock.Setup(x => x.Route).Returns(route); diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTemplateTests.cs index d87c4216c..a9dc92ba1 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTemplateTests.cs @@ -30,7 +30,6 @@ public void Simpletemplate_AllDefaults_GeneralPropertyCheck() Assert.AreEqual("SimpleExecutable", template.Name); Assert.AreEqual(nameof(SimpleExecutableDirective), template.InternalName); - Assert.AreEqual(typeof(SimpleExecutableDirective).FriendlyName(true), template.InternalFullName); Assert.AreEqual("Simple Description", template.Description); Assert.AreEqual(1, template.Methods.Count); Assert.IsTrue(template.Locations.HasFlag(DirectiveLocation.FIELD)); diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InputGraphFieldTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InputGraphFieldTemplateTests.cs index c657d5ab6..48d489299 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InputGraphFieldTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InputGraphFieldTemplateTests.cs @@ -26,7 +26,7 @@ public void Parse_GeneralPropertyCheck() { var obj = new Mock(); obj.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/Item0")); - obj.Setup(x => x.InternalFullName).Returns("Item0"); + obj.Setup(x => x.InternalName).Returns("Item0"); obj.Setup(x => x.Kind).Returns(TypeKind.INPUT_OBJECT); var parent = obj.Object; @@ -40,10 +40,10 @@ public void Parse_GeneralPropertyCheck() Assert.AreEqual("name desc", template.Description); Assert.AreEqual(typeof(string), template.ObjectType); Assert.IsFalse(template.IsRequired); - Assert.AreEqual("String", template.TypeExpression.ToString()); + Assert.AreEqual("Type", template.TypeExpression.ToString()); Assert.AreEqual(1, template.AppliedDirectives.Count()); Assert.AreEqual("nameDirective", template.AppliedDirectives.Single().DirectiveName); - Assert.AreEqual("Name", template.InternalName); + Assert.AreEqual("Item0.Name", template.InternalName); } [Test] @@ -51,7 +51,7 @@ public void Parse_IsRequired_IsNotSet() { var obj = new Mock(); obj.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/Item0")); - obj.Setup(x => x.InternalFullName).Returns("Item0"); + obj.Setup(x => x.InternalName).Returns("Item0"); obj.Setup(x => x.Kind).Returns(TypeKind.INPUT_OBJECT); var parent = obj.Object; @@ -70,7 +70,7 @@ public void Parse_IsRequired_IsSet() { var obj = new Mock(); obj.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/Item0")); - obj.Setup(x => x.InternalFullName).Returns("Item0"); + obj.Setup(x => x.InternalName).Returns("Item0"); obj.Setup(x => x.Kind).Returns(TypeKind.INPUT_OBJECT); var parent = obj.Object; @@ -88,7 +88,7 @@ public void Parse_NotRequired_NullableType_ButWithExplicitNonNullTypeExpression_ { var obj = new Mock(); obj.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/Item0")); - obj.Setup(x => x.InternalFullName).Returns("Item0"); + obj.Setup(x => x.InternalName).Returns("Item0"); obj.Setup(x => x.Kind).Returns(TypeKind.INPUT_OBJECT); var parent = obj.Object; @@ -98,7 +98,7 @@ public void Parse_NotRequired_NullableType_ButWithExplicitNonNullTypeExpression_ template.ValidateOrThrow(); // field does declare [Required] there for cannot have a default value - Assert.AreEqual("Input_ShoeData!", template.TypeExpression.ToString()); + Assert.AreEqual("Type!", template.TypeExpression.ToString()); } [Test] @@ -106,7 +106,7 @@ public void Parse_InterfaceAsPropertyType_ThrowsException() { var obj = new Mock(); obj.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/Item0")); - obj.Setup(x => x.InternalFullName).Returns("Item0"); + obj.Setup(x => x.InternalName).Returns("Item0"); obj.Setup(x => x.Kind).Returns(TypeKind.INPUT_OBJECT); var parent = obj.Object; @@ -125,7 +125,7 @@ public void Parse_TaskAsPropertyType_ThrowsException() { var obj = new Mock(); obj.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/Item0")); - obj.Setup(x => x.InternalFullName).Returns("Item0"); + obj.Setup(x => x.InternalName).Returns("Item0"); obj.Setup(x => x.Kind).Returns(TypeKind.INPUT_OBJECT); var parent = obj.Object; @@ -144,7 +144,7 @@ public void Parse_UnionAsPropertyType_ThrowsException() { var obj = new Mock(); obj.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/Item0")); - obj.Setup(x => x.InternalFullName).Returns("Item0"); + obj.Setup(x => x.InternalName).Returns("Item0"); obj.Setup(x => x.Kind).Returns(TypeKind.INPUT_OBJECT); var parent = obj.Object; @@ -163,7 +163,7 @@ public void Parse_ActionResultAsPropertyType_ThrowsException() { var obj = new Mock(); obj.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/Item0")); - obj.Setup(x => x.InternalFullName).Returns("Item0"); + obj.Setup(x => x.InternalName).Returns("Item0"); obj.Setup(x => x.Kind).Returns(TypeKind.INPUT_OBJECT); var parent = obj.Object; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InputObjectTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InputObjectTemplateTests.cs index d803c89d8..57876f4a1 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InputObjectTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InputObjectTemplateTests.cs @@ -60,7 +60,6 @@ public void Parse_Object_GeneralPropertySettings_SetCorrectly() Assert.AreEqual(0, template.FieldTemplates.Count()); Assert.AreEqual(TypeKind.INPUT_OBJECT, template.Kind); Assert.AreEqual(nameof(SimpleObjectNoMethods), template.InternalName); - Assert.AreEqual("GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests.SimpleObjectNoMethods", template.InternalFullName); Assert.AreEqual(0, template.SecurityPolicies.Count); } diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplateTests.cs index 4652e6128..4de4de40a 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplateTests.cs @@ -30,7 +30,7 @@ private MethodGraphFieldTemplate CreateMethodTemplate(string methodName { var obj = new Mock(); obj.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/Item0")); - obj.Setup(x => x.InternalFullName).Returns("Item0"); + obj.Setup(x => x.InternalName).Returns("Item0"); var parent = obj.Object; var methodInfo = typeof(TObject).GetMethod(methodName); @@ -45,7 +45,7 @@ public void DefaultValuesCheck() { var obj = new Mock(); obj.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/Item0")); - obj.Setup(x => x.InternalFullName).Returns("Item0"); + obj.Setup(x => x.InternalName).Returns("Item0"); var parent = obj.Object; var methodInfo = typeof(MethodClass).GetMethod(nameof(MethodClass.SimpleMethodNoAttributes)); @@ -54,7 +54,7 @@ public void DefaultValuesCheck() template.ValidateOrThrow(); Assert.AreEqual(nameof(MethodClass.SimpleMethodNoAttributes), template.Name); - Assert.AreEqual($"Item0.{nameof(MethodClass.SimpleMethodNoAttributes)}", template.InternalFullName); + Assert.AreEqual($"Item0.{nameof(MethodClass.SimpleMethodNoAttributes)}", template.InternalName); Assert.AreEqual($"[type]/Item0/{nameof(MethodClass.SimpleMethodNoAttributes)}", template.Route.Path); Assert.AreEqual(parent.Route.Path, template.Route.Parent.Path); Assert.AreEqual(methodInfo, template.Method); @@ -103,7 +103,7 @@ public void AlternateNameParameterParsing_SetsParamsCorrectly() Assert.AreEqual(1, template.Arguments.Count); var param = template.Arguments[0]; Assert.AreEqual("arg55", param.Name); - Assert.AreEqual("Item0.ParamWithAlternateName.arg1", param.InternalFullName); + Assert.AreEqual("Item0.ParamWithAlternateName.arg1", param.InternalName); } [Test] @@ -157,7 +157,7 @@ public void ArrayFromMethod_YieldsTemplate() { var obj = new Mock(); obj.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/Item0")); - obj.Setup(x => x.InternalFullName).Returns("Item0"); + obj.Setup(x => x.InternalName).Returns("Item0"); var expectedTypeExpression = new GraphTypeExpression( Constants.Other.DEFAULT_TYPE_EXPRESSION_TYPE_NAME, @@ -175,7 +175,7 @@ public void Parse_AssignedDirective_IsTemplatized() { var obj = new Mock(); obj.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/Item0")); - obj.Setup(x => x.InternalFullName).Returns("Item0"); + obj.Setup(x => x.InternalName).Returns("Item0"); var expectedTypeExpression = new GraphTypeExpression( typeof(TwoPropertyObject).FriendlyName(), @@ -196,7 +196,7 @@ public void DefaultNonNullableParameter_NotMarkedRequired() { var obj = new Mock(); obj.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/Item0")); - obj.Setup(x => x.InternalFullName).Returns("Item0"); + obj.Setup(x => x.InternalName).Returns("Item0"); var parent = obj.Object; var template = this.CreateMethodTemplate(nameof(MethodClass.DefaultNonNullableParameter)); diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectGraphTypeTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectGraphTypeTemplateTests.cs index ca615ce3f..6945b6601 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectGraphTypeTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectGraphTypeTemplateTests.cs @@ -375,8 +375,8 @@ public void Parse_ExplicitInheritedMethodBasedField_IsSeenAsAGraphField() template.ValidateOrThrow(); Assert.AreEqual(2, template.FieldTemplates.Count); - Assert.IsTrue(template.FieldTemplates.Any(x => x.Value.InternalName == nameof(ObjectThatInheritsExplicitMethodField.FieldOnObject))); - Assert.IsTrue(template.FieldTemplates.Any(x => x.Value.InternalName == nameof(ObjectWithExplicitMethodField.FieldOnBaseObject))); + Assert.IsTrue(template.FieldTemplates.Any(x => x.Value.InternalName == $"{nameof(ObjectThatInheritsExplicitMethodField)}.{nameof(ObjectThatInheritsExplicitMethodField.FieldOnObject)}")); + Assert.IsTrue(template.FieldTemplates.Any(x => x.Value.InternalName == $"{nameof(ObjectThatInheritsExplicitMethodField)}.{nameof(ObjectWithExplicitMethodField.FieldOnBaseObject)}")); } [Test] @@ -387,8 +387,8 @@ public void Parse_NonExplicitMethodBasedField_IsSeenAsTemplatefield() template.ValidateOrThrow(); Assert.AreEqual(2, template.FieldTemplates.Count); - Assert.IsTrue(template.FieldTemplates.Any(x => x.Value.InternalName == nameof(ObjectThatInheritsNonExplicitMethodField.FieldOnObject))); - Assert.IsTrue(template.FieldTemplates.Any(x => x.Value.InternalName == nameof(ObjectWithNonExplicitMethodField.FieldOnBaseObject))); + Assert.IsTrue(template.FieldTemplates.Any(x => x.Value.DeclaredName == nameof(ObjectThatInheritsNonExplicitMethodField.FieldOnObject))); + Assert.IsTrue(template.FieldTemplates.Any(x => x.Value.DeclaredName == nameof(ObjectWithNonExplicitMethodField.FieldOnBaseObject))); } [Test] diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyGraphFieldTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyGraphFieldTemplateTests.cs index 453221743..bd2ecd212 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyGraphFieldTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyGraphFieldTemplateTests.cs @@ -32,7 +32,7 @@ public void Parse_DescriptionAttribute_SetsValue() { var obj = new Mock(); obj.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/Item0")); - obj.Setup(x => x.InternalFullName).Returns("Item0"); + obj.Setup(x => x.InternalName).Returns("Item0"); var parent = obj.Object; var propInfo = typeof(SimplePropertyObject).GetProperty(nameof(SimplePropertyObject.Address1)); @@ -48,7 +48,7 @@ public void Parse_DepreciationAttribute_SetsValues() { var obj = new Mock(); obj.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/Item0")); - obj.Setup(x => x.InternalFullName).Returns("Item0"); + obj.Setup(x => x.InternalName).Returns("Item0"); var parent = obj.Object; var propInfo = typeof(SimplePropertyObject).GetProperty(nameof(SimplePropertyObject.Address2)); @@ -62,7 +62,7 @@ public void Parse_PropertyAsAnObject_SetsReturnTypeCorrectly() { var obj = new Mock(); obj.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/Item0")); - obj.Setup(x => x.InternalFullName).Returns("Item0"); + obj.Setup(x => x.InternalName).Returns("Item0"); var parent = obj.Object; var propInfo = typeof(SimplePropertyObject).GetProperty(nameof(SimplePropertyObject.Hair)); @@ -78,7 +78,7 @@ public void Parse_PropertyAsAList_SetsReturnType_AsCoreItemNotTheList() { var obj = new Mock(); obj.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/Item0")); - obj.Setup(x => x.InternalFullName).Returns("Item0"); + obj.Setup(x => x.InternalName).Returns("Item0"); var parent = obj.Object; @@ -96,7 +96,7 @@ public void Parse_SecurityPolices_AreAdded() { var obj = new Mock(); obj.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/Item0")); - obj.Setup(x => x.InternalFullName).Returns("Item0"); + obj.Setup(x => x.InternalName).Returns("Item0"); var parent = obj.Object; var propInfo = typeof(SimplePropertyObject).GetProperty(nameof(SimplePropertyObject.LastName)); @@ -112,7 +112,7 @@ public void Parse_InvalidName_ThrowsException() { var obj = new Mock(); obj.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/Item0")); - obj.Setup(x => x.InternalFullName).Returns("Item0"); + obj.Setup(x => x.InternalName).Returns("Item0"); var parent = obj.Object; var propInfo = typeof(SimplePropertyObject).GetProperty(nameof(SimplePropertyObject.City)); @@ -130,7 +130,7 @@ public void Parse_SkipDefined_ThrowsException() { var obj = new Mock(); obj.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/Item0")); - obj.Setup(x => x.InternalFullName).Returns("Item0"); + obj.Setup(x => x.InternalName).Returns("Item0"); var parent = obj.Object; var propInfo = typeof(SimplePropertyObject).GetProperty(nameof(SimplePropertyObject.State)); @@ -149,7 +149,7 @@ public void Parse_BasicObject_PropertyWithNoGetter_ThrowsException() { var obj = new Mock(); obj.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/Item0")); - obj.Setup(x => x.InternalFullName).Returns("Item0"); + obj.Setup(x => x.InternalName).Returns("Item0"); var parent = obj.Object; var propInfo = typeof(NoGetterOnProperty).GetProperty(nameof(NoGetterOnProperty.Prop1)); @@ -157,10 +157,12 @@ public void Parse_BasicObject_PropertyWithNoGetter_ThrowsException() var template = new PropertyGraphFieldTemplate(parent, propInfo, TypeKind.OBJECT); template.Parse(); - Assert.Throws(() => + var ex = Assert.Throws(() => { template.ValidateOrThrow(); }); + + Assert.IsTrue(ex.Message.Contains("does not define a public getter")); } [Test] @@ -168,7 +170,7 @@ public void Parse_BasicObject_PropertyReturnsArray_YieldsTemplate() { var obj = new Mock(); obj.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/Item0")); - obj.Setup(x => x.InternalFullName).Returns("Item0"); + obj.Setup(x => x.InternalName).Returns("Item0"); var expectedTypeExpression = new GraphTypeExpression( Constants.Other.DEFAULT_TYPE_EXPRESSION_TYPE_NAME, @@ -190,7 +192,7 @@ public void Parse_BasicObject_PropertyReturnsArrayOfKeyValuePair_YieldsTemplate( { var obj = new Mock(); obj.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/Item0")); - obj.Setup(x => x.InternalFullName).Returns("Item0"); + obj.Setup(x => x.InternalName).Returns("Item0"); var expectedTypeExpression = new GraphTypeExpression( Constants.Other.DEFAULT_TYPE_EXPRESSION_TYPE_NAME, // expression is expected to be unnamed at the template level @@ -213,7 +215,7 @@ public void Parse_AssignedDirective_IsTemplatized() { var obj = new Mock(); obj.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/Item0")); - obj.Setup(x => x.InternalFullName).Returns("Item0"); + obj.Setup(x => x.InternalName).Returns("Item0"); var expectedTypeExpression = new GraphTypeExpression( typeof(KeyValuePair).FriendlyGraphTypeName(), @@ -238,7 +240,7 @@ public void InvalidTypeExpression_ThrowsException() { var obj = new Mock(); obj.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/Item0")); - obj.Setup(x => x.InternalFullName).Returns("Item0"); + obj.Setup(x => x.InternalName).Returns("Item0"); var parent = obj.Object; var propInfo = typeof(SimplePropertyObject).GetProperty(nameof(SimplePropertyObject.InvalidTypeExpression)); diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ScalarGraphTypeTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ScalarGraphTypeTemplateTests.cs index c8806b0b0..eaae9faf2 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ScalarGraphTypeTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ScalarGraphTypeTemplateTests.cs @@ -35,9 +35,8 @@ public void ValidScalar_PropertyCheck() Assert.AreEqual("[type]/myScalar", template.Route.Path); Assert.AreEqual("myScalar Desc", template.Description); Assert.IsTrue(template.Publish); - Assert.AreEqual("My.Test.Scalar", template.InternalFullName); + Assert.AreEqual("My.Test.Scalar", template.InternalName); Assert.AreEqual(typeof(MyTestScalar), template.ScalarType); - Assert.AreEqual(nameof(MyTestScalar), template.InternalName); Assert.AreEqual(typeof(MyTestObject), template.ObjectType); Assert.IsFalse(template.DeclarationRequirements.HasValue); diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ScalarTestData/MyTestScalar.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ScalarTestData/MyTestScalar.cs index f5be9c9de..fbe57148a 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ScalarTestData/MyTestScalar.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ScalarTestData/MyTestScalar.cs @@ -31,7 +31,7 @@ public MyTestScalar() this.Name = "myScalar"; this.Description = "myScalar Desc"; this.Route = new SchemaItemPath(SchemaItemCollections.Scalars, this.Name); - this.InternalFullName = "My.Test.Scalar"; + this.InternalName = "My.Test.Scalar"; this.ObjectType = typeof(MyTestObject); this.SourceResolver = new Mock().Object; this.Publish = true; @@ -56,7 +56,7 @@ public MyTestScalar() public Type ObjectType { get; } - public string InternalFullName { get; } + public string InternalName { get; } public SchemaItemPath Route { get; } diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/TypeExtensionFieldTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/TypeExtensionFieldTemplateTests.cs index 1c72d5bcb..6c8cfdc55 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/TypeExtensionFieldTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/TypeExtensionFieldTemplateTests.cs @@ -29,7 +29,7 @@ private GraphTypeExtensionFieldTemplate CreateExtensionTemplate where TControllerType : GraphController { var mockController = new Mock(); - mockController.Setup(x => x.InternalFullName).Returns(typeof(TControllerType).Name); + mockController.Setup(x => x.InternalName).Returns(typeof(TControllerType).Name); mockController.Setup(x => x.Route).Returns(new SchemaItemPath("path0")); mockController.Setup(x => x.Name).Returns("path0"); mockController.Setup(x => x.ObjectType).Returns(typeof(TControllerType)); @@ -53,7 +53,7 @@ public void ClassTypeExtension_PropertyCheck() Assert.AreEqual(typeof(ExtensionMethodController), template.Parent.ObjectType); Assert.AreEqual(typeof(TwoPropertyObject), template.SourceObjectType); Assert.AreEqual($"[type]/{nameof(TwoPropertyObject)}/Property3", template.Route.Path); - Assert.AreEqual($"{nameof(ExtensionMethodController)}.{nameof(ExtensionMethodController.ClassTypeExtension)}", template.InternalFullName); + Assert.AreEqual($"{nameof(ExtensionMethodController)}.{nameof(ExtensionMethodController.ClassTypeExtension)}", template.InternalName); Assert.AreEqual(methodInfo.ReflectedType, template.Parent.ObjectType); Assert.AreEqual("path0", template.Parent.Name); Assert.AreEqual(methodInfo, template.Method); @@ -99,7 +99,7 @@ public void StructTypeExtension_PropertyCheck() Assert.AreEqual(typeof(ExtensionMethodController), template.Parent.ObjectType); Assert.AreEqual(typeof(TwoPropertyStruct), template.SourceObjectType); Assert.AreEqual($"[type]/{nameof(TwoPropertyStruct)}/Property3", template.Route.Path); - Assert.AreEqual($"{nameof(ExtensionMethodController)}.{nameof(ExtensionMethodController.StructTypeExtension)}", template.InternalFullName); + Assert.AreEqual($"{nameof(ExtensionMethodController)}.{nameof(ExtensionMethodController.StructTypeExtension)}", template.InternalName); Assert.AreEqual(methodInfo.ReflectedType, template.Parent.ObjectType); Assert.AreEqual("path0", template.Parent.Name); Assert.AreEqual(methodInfo, template.Method); @@ -145,7 +145,7 @@ public void InterfaceTypeExtension_PropertyCheck() Assert.AreEqual(typeof(ExtensionMethodController), template.Parent.ObjectType); Assert.AreEqual(typeof(ISinglePropertyObject), template.SourceObjectType); Assert.AreEqual($"[type]/TwoPropertyInterface/Property3", template.Route.Path); - Assert.AreEqual($"{nameof(ExtensionMethodController)}.{nameof(ExtensionMethodController.InterfaceTypeExtension)}", template.InternalFullName); + Assert.AreEqual($"{nameof(ExtensionMethodController)}.{nameof(ExtensionMethodController.InterfaceTypeExtension)}", template.InternalName); Assert.AreEqual(methodInfo.ReflectedType, template.Parent.ObjectType); Assert.AreEqual("path0", template.Parent.Name); Assert.AreEqual(methodInfo, template.Method); diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/UnionGraphTypeTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/UnionGraphTypeTemplateTests.cs index 2e1492ef7..113444904 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/UnionGraphTypeTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/UnionGraphTypeTemplateTests.cs @@ -46,8 +46,7 @@ public void ValidateProxy_ParsesCorrectly() Assert.AreEqual(TypeKind.UNION, instance.Kind); Assert.AreEqual("ValidUnion", instance.Name); Assert.AreEqual("My Union Desc", instance.Description); - Assert.AreEqual(typeof(ValidTestUnion).FriendlyName(true), instance.InternalFullName); - Assert.AreEqual("ValidTestUnion", typeof(ValidTestUnion).Name); + Assert.AreEqual("ValidUnion", instance.InternalName); // should use union name when supplied Assert.AreEqual(typeof(ValidTestUnion), instance.ProxyType); Assert.IsTrue(instance.Publish); } diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/InvalidParentAppliedDirectivesScalar.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/InvalidParentAppliedDirectivesScalar.cs index ddbe3b124..1aaa5bb78 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/InvalidParentAppliedDirectivesScalar.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/InvalidParentAppliedDirectivesScalar.cs @@ -43,7 +43,7 @@ public InvalidParentAppliedDirectivesScalar() public Type ObjectType { get; } - public string InternalFullName { get; } + public string InternalName { get; } public SchemaItemPath Route { get; } diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NoObjectTypeScalar.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NoObjectTypeScalar.cs index 381b8f329..f6bec9cce 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NoObjectTypeScalar.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NoObjectTypeScalar.cs @@ -42,7 +42,7 @@ public NoObjectTypeScalar() public Type ObjectType { get; } - public string InternalFullName { get; } + public string InternalName { get; } public SchemaItemPath Route { get; } diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NoSourceResolverScalar.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NoSourceResolverScalar.cs index 08fc07a0b..ec428c54c 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NoSourceResolverScalar.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NoSourceResolverScalar.cs @@ -44,7 +44,7 @@ public NoSourceResolverScalar() public Type ObjectType { get; } - public string InternalFullName { get; } + public string InternalName { get; } public SchemaItemPath Route { get; } diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NoValueTypeScalar.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NoValueTypeScalar.cs index 6cff6e8a7..274373751 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NoValueTypeScalar.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NoValueTypeScalar.cs @@ -43,7 +43,7 @@ public NoValueTypeScalar() public Type ObjectType { get; } - public string InternalFullName { get; } + public string InternalName { get; } public SchemaItemPath Route { get; } diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NotScalarKindScalar.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NotScalarKindScalar.cs index 841ed90bf..db0a52d29 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NotScalarKindScalar.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NotScalarKindScalar.cs @@ -43,7 +43,7 @@ public NotScalarKindScalar() public Type ObjectType { get; } - public string InternalFullName { get; } + public string InternalName { get; } public SchemaItemPath Route { get; } diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NullAppliedDirectivesScalar.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NullAppliedDirectivesScalar.cs index 4bd6b1940..e031ced31 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NullAppliedDirectivesScalar.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NullAppliedDirectivesScalar.cs @@ -43,7 +43,7 @@ public NullAppliedDirectivesScalar() public Type ObjectType { get; } - public string InternalFullName { get; } + public string InternalName { get; } public SchemaItemPath Route { get; } diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/ObjectTypeIsNullableScalar.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/ObjectTypeIsNullableScalar.cs index 00fce028b..4a918262f 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/ObjectTypeIsNullableScalar.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/ObjectTypeIsNullableScalar.cs @@ -43,7 +43,7 @@ public ObjectTypeIsNullableScalar() public Type ObjectType { get; } - public string InternalFullName { get; } + public string InternalName { get; } public SchemaItemPath Route { get; } diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GraphFieldArgumentCloningTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GraphFieldArgumentCloningTests.cs index 7d050f1c7..e954cfe6a 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/GraphFieldArgumentCloningTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GraphFieldArgumentCloningTests.cs @@ -52,7 +52,7 @@ public void ClonedArgument_PropertyCheck() Assert.AreEqual(arg.Description, clonedArg.Description); Assert.AreEqual(arg.DefaultValue, clonedArg.DefaultValue); Assert.AreEqual(arg.ObjectType, clonedArg.ObjectType); - Assert.AreEqual(arg.InternalFullName, clonedArg.InternalFullName); + Assert.AreEqual(arg.InternalName, clonedArg.InternalName); Assert.AreEqual(arg.TypeExpression, clonedArg.TypeExpression); Assert.AreEqual(arg.ParameterName, clonedArg.ParameterName); Assert.AreEqual(arg.AppliedDirectives.Count, arg.AppliedDirectives.Count); diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GraphFieldCloningTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GraphFieldCloningTests.cs index 64ace5ee0..d240bfaae 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/GraphFieldCloningTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GraphFieldCloningTests.cs @@ -90,7 +90,7 @@ public void MethodField_PropertyCheck() Assert.AreEqual(field.DeprecationReason, clonedField.DeprecationReason); Assert.AreEqual(field.Complexity, clonedField.Complexity); Assert.AreEqual(field.FieldSource, clonedField.FieldSource); - Assert.AreEqual(field.InternalFullName, clonedField.InternalFullName); + Assert.AreEqual(field.InternalName, clonedField.InternalName); Assert.IsFalse(object.ReferenceEquals(field.TypeExpression, clonedField.TypeExpression)); Assert.IsTrue(object.ReferenceEquals(field.Resolver, clonedField.Resolver)); @@ -159,7 +159,7 @@ public void PropertyField_PropertyCheck() var clonedField = field.Clone(clonedParent.Object) as PropertyGraphField; Assert.IsNotNull(clonedField); - Assert.AreEqual(field.InternalFullName, clonedField.InternalFullName); + Assert.AreEqual(field.InternalName, clonedField.InternalName); Assert.AreEqual(field.Name, clonedField.Name); Assert.AreEqual(field.ObjectType, clonedField.ObjectType); Assert.AreEqual(field.DeclaredReturnType, clonedField.DeclaredReturnType); diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTypeCollectionInterefaceImplementationTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTypeCollectionInterefaceImplementationTests.cs index 765071038..ebed56e70 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTypeCollectionInterefaceImplementationTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/SchemaTypeCollectionInterefaceImplementationTests.cs @@ -83,9 +83,9 @@ public SchemaTypeCollectionInterefaceImplementationTests() template.Parse(); template.ValidateOrThrow(); - var hasSugarTemplate = template.Extensions.FirstOrDefault(x => x.InternalName == nameof(PastryExtensionController.HasSugarExtension)); - var hasGlazeTemplate = template.Extensions.FirstOrDefault(x => x.InternalName == nameof(PastryExtensionController.HasGlazeExtension)); - var hasDoubleGlazeTemplate = template.Extensions.FirstOrDefault(x => x.InternalName == nameof(PastryExtensionController.HasDoubleGlazeExtension)); + var hasSugarTemplate = template.Extensions.FirstOrDefault(x => x.DeclaredName == nameof(PastryExtensionController.HasSugarExtension)); + var hasGlazeTemplate = template.Extensions.FirstOrDefault(x => x.DeclaredName == nameof(PastryExtensionController.HasGlazeExtension)); + var hasDoubleGlazeTemplate = template.Extensions.FirstOrDefault(x => x.DeclaredName == nameof(PastryExtensionController.HasDoubleGlazeExtension)); _hasSugarFieldExtension = this.MakeGraphField(hasSugarTemplate); _hasGlazeFieldExtension = this.MakeGraphField(hasGlazeTemplate); _hasDoubleGlazeFieldExtension = this.MakeGraphField(hasDoubleGlazeTemplate); @@ -276,6 +276,9 @@ public void InterfaceAndObjectTypeExtensions_Scenarios( int positionToAddGlazeField, int positiontoAddDoubleGlazeField) { + // Tests the various scenarios of when a type extension, an OBJECT graph type and an INTERFACE + // graph type may be registered to ensure that all graph types contain all extensions by the end + // of the inclusion process regardless of the order encountered for (var i = 1; i <= 7; i++) { if (positionToAddIPastry == i) From 2db72237d20a45b3388dcb86d2261a9bf865e77a Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Sat, 22 Jul 2023 13:31:40 -0700 Subject: [PATCH 45/63] WIP, clean up from internal name restructure --- .../SubscriptionMethodGraphField.cs | 2 +- .../Resolvers/FieldResolverMetaData.cs | 12 ++- .../Resolvers/InputObjectValueResolver.cs | 4 +- .../InternalFieldResolverMetaData.cs | 1 + .../Execution/IGraphFieldResolverMetaData.cs | 15 +++- .../Interfaces/Schema/IEnumValue.cs | 8 -- .../Interfaces/Schema/IInputGraphField.cs | 5 ++ .../Interfaces/Schema/INamedItem.cs | 18 ++++ .../Interfaces/Schema/ITypedSchemaItem.cs | 16 ---- .../TypeMakers/GraphArgumentMaker.cs | 4 +- .../Generation/TypeMakers/GraphFieldMaker.cs | 20 +---- .../TypeMakers/ObjectGraphTypeMaker.cs | 1 + .../TypeMakers/UnionGraphTypeMaker.cs | 1 + .../GraphDirectiveMethodTemplate.cs | 1 + .../TypeTemplates/GraphFieldTemplateBase.cs | 2 +- .../MethodGraphFieldTemplateBase.cs | 1 + .../PropertyGraphFieldTemplate.cs | 1 + src/graphql-aspnet/Schemas/GraphSchema.cs | 4 + .../Schemas/SchemaLanguageGenerator.cs | 4 +- .../Structural/GraphFieldCollection.cs | 4 +- .../ExtendableGraphTypeExtensions.cs | 4 +- .../Schemas/TypeSystem/GraphFieldArgument.cs | 14 +-- .../Schemas/TypeSystem/GraphOperation.cs | 4 +- .../Schemas/TypeSystem/GraphUnionProxy.cs | 48 +++++++--- .../Schemas/TypeSystem/InputGraphField.cs | 23 ++--- .../BaseIntrospectionObjectType.cs | 11 +-- .../Fields/Introspection_SchemaField.cs | 2 +- .../Fields/Introspection_TypeGraphField.cs | 4 +- .../Fields/Introspection_TypeNameMetaField.cs | 2 +- .../Introspection_DirectiveType.cs | 2 +- .../Introspection_EnumValueType.cs | 2 +- .../Introspection/Introspection_FieldType.cs | 2 +- .../Introspection_InputValueType.cs | 2 +- .../Introspection/Introspection_SchemaType.cs | 2 +- .../Introspection/Introspection_TypeType.cs | 10 +-- .../Introspection/Model/IntrospectedItem.cs | 4 + .../Schemas/TypeSystem/MethodGraphField.cs | 16 ++-- .../Schemas/TypeSystem/ObjectGraphType.cs | 9 +- .../Schemas/TypeSystem/ObjectGraphTypeBase.cs | 6 ++ .../Schemas/TypeSystem/PropertyGraphField.cs | 74 --------------- .../Schemas/TypeSystem/UnionGraphType.cs | 6 ++ .../TypeSystem/VirtualObjectGraphType.cs | 4 +- .../TestServer.cs | 2 +- .../ScalarIncorrectAppliedDirectivesParent.cs | 2 + .../SodaTypeUnionProxy.cs | 2 + .../TypeMakers/FieldMaker_InputFieldTests.cs | 20 +++-- .../TypeMakers/TestData/UnionTestProxy.cs | 2 + .../ActionTestData/UnionTestProxy.cs | 2 + .../NullTypesUnionProxy.cs | 3 + .../Schemas/GraphFieldArgumentCloningTests.cs | 4 +- .../Schemas/GraphFieldCloningTests.cs | 89 +------------------ 51 files changed, 204 insertions(+), 297 deletions(-) delete mode 100644 src/graphql-aspnet/Schemas/TypeSystem/PropertyGraphField.cs diff --git a/src/graphql-aspnet-subscriptions/Schemas/TypeSystem/SubscriptionMethodGraphField.cs b/src/graphql-aspnet-subscriptions/Schemas/TypeSystem/SubscriptionMethodGraphField.cs index bc7fa6903..1f9434078 100644 --- a/src/graphql-aspnet-subscriptions/Schemas/TypeSystem/SubscriptionMethodGraphField.cs +++ b/src/graphql-aspnet-subscriptions/Schemas/TypeSystem/SubscriptionMethodGraphField.cs @@ -48,7 +48,7 @@ public SubscriptionMethodGraphField( IEnumerable securityPolicies = null, string eventName = null, IAppliedDirectiveCollection directives = null) - : base(fieldName, typeExpression, route, internalFullName, objectType, declaredReturnType, mode, resolver, securityPolicies, directives) + : base(fieldName, internalFullName, typeExpression, route, declaredReturnType, objectType, mode, resolver, securityPolicies, directives) { this.EventName = eventName; } diff --git a/src/graphql-aspnet/Execution/Resolvers/FieldResolverMetaData.cs b/src/graphql-aspnet/Execution/Resolvers/FieldResolverMetaData.cs index ab77f110a..8b4b9c286 100644 --- a/src/graphql-aspnet/Execution/Resolvers/FieldResolverMetaData.cs +++ b/src/graphql-aspnet/Execution/Resolvers/FieldResolverMetaData.cs @@ -23,14 +23,16 @@ namespace GraphQL.AspNet.Execution.Resolvers internal class FieldResolverMetaData : IGraphFieldResolverMetaData { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The method info will be invoked to fulfill the resolver. /// The parameters metadata collection related to this resolver method. /// Expected type of the data to be returned by the method. May be different /// from concrete return types (e.g. expecting an interface but actually returning a concrete type that implements that interface). /// if set to true the invoked method is asyncronous. - /// The name of the resolver method or property as it exists in source code. + /// The internal name of the resolver method or property that can uniquely identify it in + /// exceptions and log entries. + /// The exact name of the resolver method or property name as its declared in source code. /// The type of the .NET class or struct where the resolver method is declared. /// The name of the .NET class or struct where the resolver method is declared. public FieldResolverMetaData( @@ -39,6 +41,7 @@ public FieldResolverMetaData( Type expectedReturnType, bool isAsyncField, string internalName, + string declaredName, Type parentObjectType, string parentInternalName) { @@ -50,7 +53,7 @@ public FieldResolverMetaData( this.Parameters = Validation.ThrowIfNullOrReturn(parameters, nameof(parameters)); this.InternalName = Validation.ThrowIfNullWhiteSpaceOrReturn(internalName, nameof(internalName)); - + this.DeclaredName = Validation.ThrowIfNullWhiteSpaceOrReturn(declaredName, nameof(declaredName)); this.ParentObjectType = Validation.ThrowIfNullOrReturn(parentObjectType, nameof(parentObjectType)); this.ParentInternalName = Validation.ThrowIfNullWhiteSpaceOrReturn(parentInternalName, nameof(parentInternalName)); } @@ -75,5 +78,8 @@ public FieldResolverMetaData( /// public Type ParentObjectType { get; } + + /// + public string DeclaredName { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Execution/Resolvers/InputObjectValueResolver.cs b/src/graphql-aspnet/Execution/Resolvers/InputObjectValueResolver.cs index d06d04939..cba037b8c 100644 --- a/src/graphql-aspnet/Execution/Resolvers/InputObjectValueResolver.cs +++ b/src/graphql-aspnet/Execution/Resolvers/InputObjectValueResolver.cs @@ -105,7 +105,9 @@ public object Resolve(IResolvableValueItem resolvableItem, IResolvedVariableColl var actualField = _graphType.Fields.FindField(inputField.Key); if (actualField != null) { - propSetter = _propSetters.ContainsKey(actualField.InternalName) ? _propSetters[actualField.InternalName] : null; + propSetter = _propSetters.ContainsKey(actualField.DeclaredName) + ? _propSetters[actualField.DeclaredName] + : null; } if (resolver == null || propSetter == null) diff --git a/src/graphql-aspnet/Execution/Resolvers/InternalFieldResolverMetaData.cs b/src/graphql-aspnet/Execution/Resolvers/InternalFieldResolverMetaData.cs index 5297e5748..0d42bf5eb 100644 --- a/src/graphql-aspnet/Execution/Resolvers/InternalFieldResolverMetaData.cs +++ b/src/graphql-aspnet/Execution/Resolvers/InternalFieldResolverMetaData.cs @@ -39,6 +39,7 @@ public static IGraphFieldResolverMetaData CreateMetadata(Type owningType) typeof(int), false, nameof(InternalValueResolver), + methodInfo.Name, owningType, owningType.FriendlyName()); } diff --git a/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverMetaData.cs b/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverMetaData.cs index d61b60efb..36654115f 100644 --- a/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverMetaData.cs +++ b/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverMetaData.cs @@ -44,12 +44,23 @@ public interface IGraphFieldResolverMetaData bool IsAsyncField { get; } /// - /// Gets the name that defines this item within the .NET code of the application; - /// typically a qualifed method name or property name. (e.g. MyObject.MyMethodName). + /// Gets the name that defines this item internally. Typically a qualifed method name or property name. (e.g. MyObject.MyMethodName). /// + /// + /// This can be changed by the developer to facilitate logging and messaging identification. + /// /// The internal name given to this item. string InternalName { get; } + /// + /// Gets the name of the resolver (method name or property name) exactly as its declared in source code. + /// + /// + /// This cannot be changed by the developer and is used for internal indexing and searching. + /// + /// The name of the resolver as its declared in source code. + string DeclaredName { get; } + /// /// Gets the type representing the graph type that will invoke the resolver identified by this /// metadata object. diff --git a/src/graphql-aspnet/Interfaces/Schema/IEnumValue.cs b/src/graphql-aspnet/Interfaces/Schema/IEnumValue.cs index 535f7ec3b..eef409022 100644 --- a/src/graphql-aspnet/Interfaces/Schema/IEnumValue.cs +++ b/src/graphql-aspnet/Interfaces/Schema/IEnumValue.cs @@ -26,14 +26,6 @@ public interface IEnumValue : ISchemaItem, IDeprecatable /// The value of the neum. object DeclaredValue { get; } - /// - /// Gets the internal name assigned to this enum value. Typically this is the same - /// as but can be customized by the developer to provider additional - /// context in error messages and log entries. - /// - /// The assigned internal name of this enum value. - string InternalName { get; } - /// /// Gets the declared label applied to the enum value by .NET. /// (e.g. 'Value1' for the enum value MyEnum.Value1). diff --git a/src/graphql-aspnet/Interfaces/Schema/IInputGraphField.cs b/src/graphql-aspnet/Interfaces/Schema/IInputGraphField.cs index 514fdefb1..e886c2408 100644 --- a/src/graphql-aspnet/Interfaces/Schema/IInputGraphField.cs +++ b/src/graphql-aspnet/Interfaces/Schema/IInputGraphField.cs @@ -14,5 +14,10 @@ namespace GraphQL.AspNet.Interfaces.Schema /// public interface IInputGraphField : IGraphFieldBase, IDefaultValueSchemaItem, ITypedSchemaItem { + /// + /// Gets the unaltered name of the property that defines this input field in source code. + /// + /// The property name that generated this data field. + public string DeclaredName { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Schema/INamedItem.cs b/src/graphql-aspnet/Interfaces/Schema/INamedItem.cs index a90cebfa5..cccb96ec5 100644 --- a/src/graphql-aspnet/Interfaces/Schema/INamedItem.cs +++ b/src/graphql-aspnet/Interfaces/Schema/INamedItem.cs @@ -20,6 +20,24 @@ public interface INamedItem /// The publically referenced name of this entity in the graph. string Name { get; } + /// + /// Gets the assigned internal name of this schema item as it exists on the server. This name + /// is used in many exceptions and internal error messages. + /// + /// + /// + /// + /// Examples:
+ /// Scalar: System.Int
+ /// Controller Resolver Method: MyProject.MyController.RetrieveWidgets
+ /// Object Property: MyProject.Widget.Name
+ ///
+ /// This value is customizable by the developer to assign a more specific name if desired. + ///
+ ///
+ /// The assigned internal name of this schema item. + string InternalName { get; } + /// /// Gets or sets the human-readable description distributed with this item /// when requested. The description should accurately describe the contents of this entity diff --git a/src/graphql-aspnet/Interfaces/Schema/ITypedSchemaItem.cs b/src/graphql-aspnet/Interfaces/Schema/ITypedSchemaItem.cs index 768f21349..542192f3d 100644 --- a/src/graphql-aspnet/Interfaces/Schema/ITypedSchemaItem.cs +++ b/src/graphql-aspnet/Interfaces/Schema/ITypedSchemaItem.cs @@ -21,21 +21,5 @@ public interface ITypedSchemaItem : ISchemaItem /// /// The type of the object. Type ObjectType { get; } - - /// - /// Gets the assigned internal name of schema item as it exists on the server. This name - /// is used in many exceptions and internal error messages. - /// - /// - /// - /// Examples:
- /// Scalar: System.Int
- /// Controller Resolver Method: MyProject.MyController.RetrieveWidgets
- /// Object Property: MyProject.Widget.Name
- ///
- /// This value is customizable by the developer to assign a more specific name if desired. - ///
- /// The assigned internal name of this schema item. - string InternalName { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphArgumentMaker.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphArgumentMaker.cs index 60c9fecfd..1c8a97cd8 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphArgumentMaker.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphArgumentMaker.cs @@ -72,10 +72,10 @@ public GraphArgumentCreationResult CreateArgument(ISchemaItem owner, IGraphArgum var argument = new GraphFieldArgument( owner, formatter.FormatFieldName(template.Name), + template.InternalName, + template.ParameterName, typeExpression, template.Route, - template.ParameterName, - template.InternalName, template.ObjectType, template.HasDefaultValue, template.DefaultValue, diff --git a/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphFieldMaker.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphFieldMaker.cs index b2e2de95e..653a45a91 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphFieldMaker.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphFieldMaker.cs @@ -117,10 +117,11 @@ public GraphFieldCreationResult CreateField(IInputGraphFieldTe var field = new InputGraphField( formatter.FormatFieldName(template.Name), + template.InternalName, template.TypeExpression.CloneTo(schemaTypeName), template.Route, - template.DeclaredName, template.ObjectType, + template.DeclaredName, template.DeclaredReturnType, template.IsRequired, defaultValue, @@ -189,7 +190,6 @@ protected virtual string PrepareTypeName(IGraphFieldTemplate template) /// System.String. protected virtual string PrepareTypeName(IInputGraphFieldTemplate template) { - // all input fields return either an object, scalar or enum (never a union) string schemaTypeName; var existingGraphType = _schema.KnownTypes.FindGraphType(template.ObjectType, template.OwnerTypeKind); @@ -238,27 +238,15 @@ protected virtual MethodGraphField CreateFieldInstance( switch (template.FieldSource) { case GraphFieldSource.Method: + case GraphFieldSource.Property: case GraphFieldSource.Action: return new MethodGraphField( formatter.FormatFieldName(template.Name), + template.InternalName, typeExpression, template.Route, - template.DeclaredName, - template.ObjectType, template.DeclaredReturnType, - template.Mode, - template.CreateResolver(), - securityGroups, - directives); - - case GraphFieldSource.Property: - return new PropertyGraphField( - formatter.FormatFieldName(template.Name), - typeExpression, - template.Route, - template.DeclaredName, template.ObjectType, - template.DeclaredReturnType, template.Mode, template.CreateResolver(), securityGroups, diff --git a/src/graphql-aspnet/Schemas/Generation/TypeMakers/ObjectGraphTypeMaker.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/ObjectGraphTypeMaker.cs index 855822732..8995ca636 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeMakers/ObjectGraphTypeMaker.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/ObjectGraphTypeMaker.cs @@ -57,6 +57,7 @@ public virtual GraphTypeCreationResult CreateGraphType(IGraphTypeTemplate typeTe var objectType = new ObjectGraphType( formatter.FormatGraphTypeName(template.Name), + template.InternalName, template.ObjectType, template.Route, directives) diff --git a/src/graphql-aspnet/Schemas/Generation/TypeMakers/UnionGraphTypeMaker.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/UnionGraphTypeMaker.cs index 23779eaad..0c05be1a2 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeMakers/UnionGraphTypeMaker.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/UnionGraphTypeMaker.cs @@ -71,6 +71,7 @@ public GraphTypeCreationResult CreateUnionFromProxy(IGraphUnionProxy proxy) var name = formatter.FormatGraphTypeName(proxy.Name); var union = new UnionGraphType( name, + proxy.InternalName, (IUnionGraphTypeMapper)proxy, new SchemaItemPath(SchemaItemCollections.Types, name), directives) diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveMethodTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveMethodTemplate.cs index 5f90edf23..9eff8c11b 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveMethodTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveMethodTemplate.cs @@ -226,6 +226,7 @@ public IGraphFieldResolverMetaData CreateResolverMetaData() this.ExpectedReturnType, this.IsAsyncField, this.InternalName, + this.Method.Name, this.Parent.ObjectType, this.Parent.InternalName); } diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphFieldTemplateBase.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphFieldTemplateBase.cs index 3bcb0c642..01767e076 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphFieldTemplateBase.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphFieldTemplateBase.cs @@ -416,7 +416,7 @@ private void BuildUnionProxyInstance() // if and only if a name was supplied for the union if (proxy == null && !string.IsNullOrWhiteSpace(fieldAttribute.UnionTypeName)) { - proxy = new GraphUnionProxy(fieldAttribute.UnionTypeName, fieldAttribute.Types); + proxy = new GraphUnionProxy(fieldAttribute.UnionTypeName, fieldAttribute.UnionTypeName, fieldAttribute.Types); } this.UnionProxy = proxy; diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplateBase.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplateBase.cs index 249fe9c82..692df3dad 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplateBase.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplateBase.cs @@ -127,6 +127,7 @@ public override IGraphFieldResolverMetaData CreateResolverMetaData() this.ExpectedReturnType, this.IsAsyncField, this.InternalName, + this.Method.Name, this.Parent.ObjectType, this.Parent.InternalName); } diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/PropertyGraphFieldTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/PropertyGraphFieldTemplate.cs index 2259b4ec9..c7aa728a5 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/PropertyGraphFieldTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/PropertyGraphFieldTemplate.cs @@ -133,6 +133,7 @@ public override IGraphFieldResolverMetaData CreateResolverMetaData() this.ExpectedReturnType, this.IsAsyncField, this.InternalName, + this.Property.Name, this.Parent.ObjectType, this.Parent.InternalName); } diff --git a/src/graphql-aspnet/Schemas/GraphSchema.cs b/src/graphql-aspnet/Schemas/GraphSchema.cs index d4e51a4da..94152956c 100644 --- a/src/graphql-aspnet/Schemas/GraphSchema.cs +++ b/src/graphql-aspnet/Schemas/GraphSchema.cs @@ -60,6 +60,7 @@ public GraphSchema() this.Route = new SchemaItemPath(SchemaItemCollections.Schemas, graphName); this.Name = DEFAULT_NAME; + this.InternalName = this.GetType().FriendlyName(); this.Description = DEFAULT_DESCRIPTION; } @@ -78,6 +79,9 @@ public GraphSchema() /// public virtual string Name { get; set; } + /// + public virtual string InternalName { get; set; } + /// public virtual string Description { get; set; } diff --git a/src/graphql-aspnet/Schemas/SchemaLanguageGenerator.cs b/src/graphql-aspnet/Schemas/SchemaLanguageGenerator.cs index cd082e67e..3df80e902 100644 --- a/src/graphql-aspnet/Schemas/SchemaLanguageGenerator.cs +++ b/src/graphql-aspnet/Schemas/SchemaLanguageGenerator.cs @@ -148,10 +148,10 @@ private string SerializeInputObject(object obj, IInputObjectGraphType inputObjec var getters = InstanceFactory.CreatePropertyGetterInvokerCollection(obj.GetType()); foreach (var field in inputObjectGraphType.Fields) { - if (!getters.ContainsKey(field.InternalName)) + if (!getters.ContainsKey(field.DeclaredName)) continue; - var getter = getters[field.InternalName]; + var getter = getters[field.DeclaredName]; builder.Append(field.Name); builder.Append(Constants.QueryLanguage.FieldValueSeperator); builder.Append(" "); diff --git a/src/graphql-aspnet/Schemas/Structural/GraphFieldCollection.cs b/src/graphql-aspnet/Schemas/Structural/GraphFieldCollection.cs index 8b373efde..526c8edc1 100644 --- a/src/graphql-aspnet/Schemas/Structural/GraphFieldCollection.cs +++ b/src/graphql-aspnet/Schemas/Structural/GraphFieldCollection.cs @@ -85,11 +85,11 @@ internal IGraphField AddField( { var field = new MethodGraphField( fieldName, + "GraphQLCustomInternalField", typeExpression, route, - "GraphQLCustomInternalField", - GraphValidation.EliminateNextWrapperFromCoreType(typeof(TReturn)), typeof(TReturn), + GraphValidation.EliminateNextWrapperFromCoreType(typeof(TReturn)), FieldResolutionMode.PerSourceItem, new FunctionGraphFieldResolver(resolver)); field.Description = description; diff --git a/src/graphql-aspnet/Schemas/TypeSystem/ExtendableGraphTypeExtensions.cs b/src/graphql-aspnet/Schemas/TypeSystem/ExtendableGraphTypeExtensions.cs index b57ebd62f..8fa73f419 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/ExtendableGraphTypeExtensions.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/ExtendableGraphTypeExtensions.cs @@ -71,11 +71,11 @@ public static IGraphField Extend( var field = new MethodGraphField( fieldName, + $"GraphQLExtendedField", typeExpression, fieldRoute, - $"GraphQLExtendedField", - GraphValidation.EliminateNextWrapperFromCoreType(typeof(TReturn)), typeof(TReturn), + GraphValidation.EliminateNextWrapperFromCoreType(typeof(TReturn)), FieldResolutionMode.PerSourceItem, new FunctionGraphFieldResolver(resolver)); field.Description = description; diff --git a/src/graphql-aspnet/Schemas/TypeSystem/GraphFieldArgument.cs b/src/graphql-aspnet/Schemas/TypeSystem/GraphFieldArgument.cs index 48313a57a..18b9c102f 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/GraphFieldArgument.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/GraphFieldArgument.cs @@ -30,10 +30,10 @@ public class GraphFieldArgument : IGraphArgument ///
/// The parent schema item that owns this argument. /// Name of the argument. + /// The internal name identifiying this argument. + /// Name of the parameter as it is declared in the source code. /// The type expression. /// The route path that identifies this argument. - /// Name of the parameter as it is declared in the source code. - /// The fully qualified internal name identifiying this argument. /// The concrete type of the object representing this argument. /// if set to true indicates that this /// argument has a default value assigned, even if that argument is null. @@ -44,10 +44,10 @@ public class GraphFieldArgument : IGraphArgument public GraphFieldArgument( ISchemaItem parent, string argumentName, + string internalName, + string parameterName, GraphTypeExpression typeExpression, SchemaItemPath route, - string parameterName, - string internalFullName, Type objectType, bool hasDefaultValue, object defaultValue = null, @@ -57,7 +57,7 @@ public GraphFieldArgument( this.Parent = Validation.ThrowIfNullOrReturn(parent, nameof(parent)); this.Name = Validation.ThrowIfNullWhiteSpaceOrReturn(argumentName, nameof(argumentName)); this.Route = Validation.ThrowIfNullOrReturn(route, nameof(route)); - this.InternalName = Validation.ThrowIfNullWhiteSpaceOrReturn(internalFullName, nameof(internalFullName)); + this.InternalName = Validation.ThrowIfNullWhiteSpaceOrReturn(internalName, nameof(internalName)); this.ParameterName = Validation.ThrowIfNullWhiteSpaceOrReturn(parameterName, nameof(parameterName)); this.TypeExpression = Validation.ThrowIfNullOrReturn(typeExpression, nameof(typeExpression)); this.ObjectType = Validation.ThrowIfNullOrReturn(objectType, nameof(objectType)); @@ -79,10 +79,10 @@ public IGraphArgument Clone(ISchemaItem parent) return new GraphFieldArgument( parent, this.Name, + this.InternalName, + this.ParameterName, this.TypeExpression.Clone(), parent.Route.CreateChild(this.Name), - this.ParameterName, - this.InternalName, this.ObjectType, this.HasDefaultValue, this.DefaultValue, diff --git a/src/graphql-aspnet/Schemas/TypeSystem/GraphOperation.cs b/src/graphql-aspnet/Schemas/TypeSystem/GraphOperation.cs index 492a55fc5..f63be460b 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/GraphOperation.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/GraphOperation.cs @@ -35,6 +35,7 @@ public GraphOperation( IAppliedDirectiveCollection directives = null) : base( Constants.ReservedNames.FindOperationTypeNameByType(operationType), + $"{nameof(GraphOperation)}.{Constants.ReservedNames.FindOperationTypeNameByType(operationType)}", new SchemaItemPath(SchemaItemCollections.Types, Constants.ReservedNames.FindOperationTypeNameByType(operationType)), directives) { @@ -65,8 +66,5 @@ public IGraphField Extend(IGraphField newField) /// public Type ObjectType => typeof(GraphOperation); - - /// - public string InternalName => $"{typeof(GraphOperation).FriendlyName()}.{this.OperationType}"; } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/TypeSystem/GraphUnionProxy.cs b/src/graphql-aspnet/Schemas/TypeSystem/GraphUnionProxy.cs index 7c41dba8f..b88365628 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/GraphUnionProxy.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/GraphUnionProxy.cs @@ -12,6 +12,8 @@ namespace GraphQL.AspNet.Schemas.TypeSystem using System; using System.Collections.Generic; using System.Diagnostics; + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Interfaces.Schema; /// @@ -22,17 +24,26 @@ namespace GraphQL.AspNet.Schemas.TypeSystem public class GraphUnionProxy : IGraphUnionProxy { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// Name of the union. - /// The types to include. - public GraphUnionProxy(string unionName, IEnumerable typesToInclude) + /// The name of the union as it appears in the graph. + /// The internal name of the union definition, usually the proxy class, + /// if one exists. + /// The types to include in the union. + public GraphUnionProxy( + string unionName, + string internalName, + IEnumerable typesToInclude) { this.Name = unionName?.Trim(); + this.InternalName = internalName?.Trim(); if (string.IsNullOrWhiteSpace(this.Name)) this.Name = this.GetType().FriendlyGraphTypeName(); + if (string.IsNullOrWhiteSpace(this.InternalName)) + this.InternalName = this.GetType().FriendlyName(); + this.Description = null; this.Types = new HashSet(typesToInclude); this.Publish = true; @@ -41,19 +52,31 @@ public GraphUnionProxy(string unionName, IEnumerable typesToInclude) /// /// Initializes a new instance of the class. /// - /// Name of the union as it should appear in the schema. - /// The types to include. + /// Name of the union as it appears in the schema. + /// The internal name of the union definition, usually the proxy class, + /// if one exists. + /// The types to include in the union. + public GraphUnionProxy(string unionName, string internalName, params Type[] typesToInclude) + : this(unionName, internalName, typesToInclude as IEnumerable) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// Name of the union as it appears in the schema. + /// The types to include in the union. public GraphUnionProxy(string unionName, params Type[] typesToInclude) - : this(unionName, typesToInclude as IEnumerable) + : this(unionName, null, typesToInclude as IEnumerable) { } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// The types to include. - protected GraphUnionProxy(params Type[] typesToInclude) - : this(null, typesToInclude as IEnumerable) + /// The types to include in the union. + public GraphUnionProxy(params Type[] typesToInclude) + : this(null, null, typesToInclude as IEnumerable) { } @@ -76,6 +99,9 @@ public virtual Type MapType(Type runtimeObjectType) /// public virtual string Name { get; set; } + /// + public string InternalName { get; } + /// public virtual string Description { get; set; } diff --git a/src/graphql-aspnet/Schemas/TypeSystem/InputGraphField.cs b/src/graphql-aspnet/Schemas/TypeSystem/InputGraphField.cs index 584be400b..aae48aa7b 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/InputGraphField.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/InputGraphField.cs @@ -36,29 +36,34 @@ public class InputGraphField : IInputGraphField /// Initializes a new instance of the class. /// /// Name of the field in the graph. + /// The internal name of this input field. Usually this is the property name, but it + /// can be changed by the developer. /// The meta data describing the type of data this field returns. /// The formal route to this field in the object graph. - /// The name of the property as it was declared on a (its internal name). /// The .NET type of the item or items that represent the graph type returned by this field. + /// The name of the property as it was declared on a (its internal name). /// The .NET type as it was declared on the property which generated this field.. /// if set to true this field was explicitly marked as being required being it has no - /// explicitly declared default value. The value passsed on will be ignored. Note that + /// explicitly declared default value. The value passsed on will be ignored. Note that /// the field will only truely be marked as required if it is has a non-nullable type expression. - /// When is false, represents + /// When is false, represents /// the value that should be used for this field when its not declared on a query document. /// The directives to apply to this field when its added to a schema. public InputGraphField( string fieldName, + string internalName, GraphTypeExpression typeExpression, SchemaItemPath route, - string declaredPropertyName, Type objectType, + string declaredPropertyName, Type declaredReturnType, bool isRequired, object defaultValue = null, IAppliedDirectiveCollection directives = null) { this.Name = Validation.ThrowIfNullWhiteSpaceOrReturn(fieldName, nameof(fieldName)); + this.InternalName = Validation.ThrowIfNullWhiteSpaceOrReturn(internalName, nameof(internalName)); + this.DeclaredName = Validation.ThrowIfNullWhiteSpaceOrReturn(declaredPropertyName, nameof(declaredPropertyName)); this.TypeExpression = Validation.ThrowIfNullOrReturn(typeExpression, nameof(typeExpression)); this.Route = Validation.ThrowIfNullOrReturn(route, nameof(route)); @@ -67,7 +72,6 @@ public InputGraphField( this.AppliedDirectives = directives?.Clone(this) ?? new AppliedDirectiveCollection(this); - this.InternalName = declaredPropertyName; this.HasDefaultValue = !isRequired; this.IsRequired = isRequired && this.TypeExpression.IsNonNullable; this.DefaultValue = defaultValue; @@ -108,13 +112,12 @@ public void AssignParent(IGraphType parent) /// public bool Publish { get; set; } - /// - /// Gets a fully qualified name of the type as it exists on the server (i.e. Namespace.ClassName.PropertyName). This name - /// is used in many exceptions and internal error messages. - /// - /// The fully qualified name of the proeprty this field was created from. + /// public string InternalName { get; } + /// + public string DeclaredName { get; } + /// public object DefaultValue { get; } diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/BaseIntrospectionObjectType.cs b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/BaseIntrospectionObjectType.cs index 6aad89827..0555b7439 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/BaseIntrospectionObjectType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/BaseIntrospectionObjectType.cs @@ -10,7 +10,6 @@ namespace GraphQL.AspNet.Schemas.TypeSystem.Introspection { using System; - using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Schemas.Structural; @@ -23,11 +22,12 @@ namespace GraphQL.AspNet.Schemas.TypeSystem.Introspection internal abstract class BaseIntrospectionObjectType : ObjectGraphTypeBase, IObjectGraphType, IInternalSchemaItem { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The name of the graph type as it is displayed in the __type information. - protected BaseIntrospectionObjectType(string name) - : base(name, new GraphIntrospectionFieldPath(name)) + /// The internal name of the introspected graph type as its defined for the target graph type. + protected BaseIntrospectionObjectType(string name, string internalName) + : base(name, internalName, new GraphIntrospectionFieldPath(name)) { } @@ -45,8 +45,5 @@ public IGraphField Extend(IGraphField newField) /// public virtual Type ObjectType => this.GetType(); - - /// - public virtual string InternalName => this.ObjectType.FriendlyName(); } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_SchemaField.cs b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_SchemaField.cs index a03d43a14..6b7ef163b 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_SchemaField.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_SchemaField.cs @@ -37,9 +37,9 @@ internal class Introspection_SchemaField : MethodGraphField public Introspection_SchemaField(IntrospectedSchema schema) : base( Constants.ReservedNames.SCHEMA_FIELD, + nameof(Introspection_SchemaField), new GraphTypeExpression(Constants.ReservedNames.SCHEMA_TYPE), FIELD_PATH, - nameof(Introspection_SchemaField), typeof(IntrospectedSchema), typeof(IntrospectedSchema), resolver: new FunctionGraphFieldResolver((x) => schema.AsCompletedTask())) diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_TypeGraphField.cs b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_TypeGraphField.cs index 31412d509..b2351b0c7 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_TypeGraphField.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_TypeGraphField.cs @@ -35,11 +35,11 @@ internal class Introspection_TypeGraphField : MethodGraphField public Introspection_TypeGraphField(IntrospectedSchema schema) : base( Constants.ReservedNames.TYPE_FIELD, + nameof(Introspection_TypeGraphField), new GraphTypeExpression(Constants.ReservedNames.TYPE_TYPE), FIELD_PATH, - nameof(Introspection_TypeGraphField), - objectType: typeof(IntrospectedType), declaredReturnType: typeof(IntrospectedType), + objectType: typeof(IntrospectedType), mode: FieldResolutionMode.PerSourceItem, resolver: new Schema_TypeGraphFieldResolver(schema)) { diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_TypeNameMetaField.cs b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_TypeNameMetaField.cs index 892933a2c..34babe115 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_TypeNameMetaField.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Fields/Introspection_TypeNameMetaField.cs @@ -37,9 +37,9 @@ public class Introspection_TypeNameMetaField : MethodGraphField public Introspection_TypeNameMetaField(string graphTypeName) : base( Constants.ReservedNames.TYPENAME_FIELD, + nameof(Introspection_TypeNameMetaField), new GraphTypeExpression(Constants.ScalarNames.STRING, MetaGraphTypes.IsNotNull), FIELD_PATH, - nameof(Introspection_TypeNameMetaField), typeof(string), typeof(string), FieldResolutionMode.PerSourceItem) diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_DirectiveType.cs b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_DirectiveType.cs index 4d1737887..dea608a3e 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_DirectiveType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_DirectiveType.cs @@ -27,7 +27,7 @@ internal class Introspection_DirectiveType : BaseIntrospectionObjectType /// Initializes a new instance of the class. ///
public Introspection_DirectiveType() - : base(Constants.ReservedNames.DIRECTIVE_TYPE) + : base(Constants.ReservedNames.DIRECTIVE_TYPE, nameof(Introspection_DirectiveType)) { // "__Directive" type definition // https://graphql.github.io/graphql-spec/October2021/#sec-Introspection diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_EnumValueType.cs b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_EnumValueType.cs index 82d36c441..600c114a2 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_EnumValueType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_EnumValueType.cs @@ -26,7 +26,7 @@ internal class Introspection_EnumValueType : BaseIntrospectionObjectType /// Initializes a new instance of the class. ///
public Introspection_EnumValueType() - : base(Constants.ReservedNames.ENUM_VALUE_TYPE) + : base(Constants.ReservedNames.ENUM_VALUE_TYPE, nameof(Introspection_EnumValueType)) { // "__EnumValue" type definition // https://graphql.github.io/graphql-spec/October2021/#sec-Introspection diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_FieldType.cs b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_FieldType.cs index c9bfc15b5..0fb89369a 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_FieldType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_FieldType.cs @@ -27,7 +27,7 @@ internal class Introspection_FieldType : BaseIntrospectionObjectType /// Initializes a new instance of the class. ///
public Introspection_FieldType() - : base(Constants.ReservedNames.FIELD_TYPE) + : base(Constants.ReservedNames.FIELD_TYPE, nameof(Introspection_FieldType)) { // "__Field" type definition // https://graphql.github.io/graphql-spec/October2021/#sec-Introspection diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_InputValueType.cs b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_InputValueType.cs index e21cbb08d..1250f4cb4 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_InputValueType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_InputValueType.cs @@ -26,7 +26,7 @@ internal class Introspection_InputValueType : BaseIntrospectionObjectType /// Initializes a new instance of the class. ///
public Introspection_InputValueType() - : base(Constants.ReservedNames.INPUT_VALUE_TYPE) + : base(Constants.ReservedNames.INPUT_VALUE_TYPE, nameof(Introspection_InputValueType)) { // "__InputValue" type definition // https://graphql.github.io/graphql-spec/October2021/#sec-Introspection diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_SchemaType.cs b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_SchemaType.cs index cfd1427f1..365b6c807 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_SchemaType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_SchemaType.cs @@ -28,7 +28,7 @@ internal class Introspection_SchemaType : BaseIntrospectionObjectType /// Initializes a new instance of the class. ///
public Introspection_SchemaType() - : base(Constants.ReservedNames.SCHEMA_TYPE) + : base(Constants.ReservedNames.SCHEMA_TYPE, nameof(Introspection_SchemaType)) { // "__Schema" type definition // https://graphql.github.io/graphql-spec/October2021/#sec-Introspection diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_TypeType.cs b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_TypeType.cs index c4d35bf6c..6b2ff5f5b 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_TypeType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_TypeType.cs @@ -28,7 +28,7 @@ internal class Introspection_TypeType : BaseIntrospectionObjectType /// Initializes a new instance of the class. ///
public Introspection_TypeType() - : base(Constants.ReservedNames.TYPE_TYPE) + : base(Constants.ReservedNames.TYPE_TYPE, nameof(Introspection_TypeType)) { // "__Type" type definition // https://graphql.github.io/graphql-spec/October2021/#sec-Introspection @@ -57,11 +57,11 @@ public Introspection_TypeType() // fields var fieldsField = new MethodGraphField( "fields", + "Introspection_TypeType_Fields", new GraphTypeExpression(Constants.ReservedNames.FIELD_TYPE, MetaGraphTypes.IsList, MetaGraphTypes.IsNotNull), new IntrospectedRoutePath(SchemaItemCollections.Types, this.Name, "fields"), - "Introspection_TypeType_Fields", - objectType: typeof(IEnumerable), declaredReturnType: typeof(IEnumerable), + objectType: typeof(IEnumerable), mode: FieldResolutionMode.PerSourceItem, resolver: new Type_TypeGraphFieldResolver()) { @@ -96,11 +96,11 @@ public Introspection_TypeType() // enumValues var enumValuesField = new MethodGraphField( "enumValues", + "Introspection_TypeType_EnumValues", new GraphTypeExpression(Constants.ReservedNames.ENUM_VALUE_TYPE, MetaGraphTypes.IsList, MetaGraphTypes.IsNotNull), new IntrospectedRoutePath(SchemaItemCollections.Types, this.Name, Constants.ReservedNames.ENUM_VALUE_TYPE), - "Introspection_TypeType_EnumValues", - objectType: typeof(IEnumerable), declaredReturnType: typeof(IEnumerable), + objectType: typeof(IEnumerable), mode: FieldResolutionMode.PerSourceItem, resolver: new Type_EnumValuesGraphFieldResolver()) { diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedItem.cs b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedItem.cs index e7134a16d..fe0cad71e 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedItem.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Model/IntrospectedItem.cs @@ -30,6 +30,7 @@ public IntrospectedItem(ISchemaItem item) { _item = Validation.ThrowIfNullOrReturn(item, nameof(item)); this.Name = _item.Name; + this.InternalName = _item.InternalName; this.Description = _item.Description; this.Route = _item.Route.ReParent(Constants.Routing.INTROSPECTION_ROOT); this.AppliedDirectives = new AppliedDirectiveCollection(this); @@ -55,6 +56,9 @@ public virtual void Initialize(IntrospectedSchema introspectedSchema) /// public virtual string Name { get; set; } + /// + public string InternalName { get; } + /// public virtual string Description { get; set; } } diff --git a/src/graphql-aspnet/Schemas/TypeSystem/MethodGraphField.cs b/src/graphql-aspnet/Schemas/TypeSystem/MethodGraphField.cs index 3fa2a6a9c..ca6e09c7d 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/MethodGraphField.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/MethodGraphField.cs @@ -12,7 +12,6 @@ namespace GraphQL.AspNet.Schemas.TypeSystem using System; using System.Collections.Generic; using System.Diagnostics; - using System.Linq; using GraphQL.AspNet.Common; using GraphQL.AspNet.Execution; using GraphQL.AspNet.Interfaces.Execution; @@ -34,23 +33,22 @@ public class MethodGraphField : IGraphField /// Initializes a new instance of the class. ///
/// Name of the field in the graph. + /// The internal name that represents the method this field respresents. /// The meta data describing the type of data this field returns. /// The formal route to this field in the object graph. - /// The fully qualified name of the method this field respresents, as it was declared - /// in C# code. - /// The .NET type of the item or items that represent the graph type returned by this field. /// The .NET type as it was declared on the property which generated this field.. + /// The .NET type of the item or items that represent the graph type returned by this field. /// The mode in which the runtime will process this field. /// The resolver to be invoked to produce data when this field is called. /// The security policies that apply to this field. /// The directives to apply to this field when its added to a schema. public MethodGraphField( string fieldName, + string internalName, GraphTypeExpression typeExpression, SchemaItemPath route, - string internalFullName, - Type objectType, Type declaredReturnType, + Type objectType, FieldResolutionMode mode = FieldResolutionMode.PerSourceItem, IGraphFieldResolver resolver = null, IEnumerable securityPolicies = null, @@ -62,7 +60,7 @@ public MethodGraphField( this.Arguments = new GraphFieldArgumentCollection(this); this.ObjectType = Validation.ThrowIfNullOrReturn(objectType, nameof(objectType)); this.DeclaredReturnType = Validation.ThrowIfNullOrReturn(declaredReturnType, nameof(declaredReturnType)); - this.InternalName = Validation.ThrowIfNullWhiteSpaceOrReturn(internalFullName, nameof(internalFullName)); + this.InternalName = Validation.ThrowIfNullWhiteSpaceOrReturn(internalName, nameof(internalName)); this.AppliedDirectives = directives?.Clone(this) ?? new AppliedDirectiveCollection(this); @@ -148,11 +146,11 @@ protected virtual MethodGraphField CreateNewInstance(IGraphType parent) { return new MethodGraphField( this.Name, + this.InternalName, this.TypeExpression.Clone(), parent.Route.CreateChild(this.Name), - this.InternalName, - this.ObjectType, this.DeclaredReturnType, + this.ObjectType, this.Mode, this.Resolver, this.SecurityGroups, diff --git a/src/graphql-aspnet/Schemas/TypeSystem/ObjectGraphType.cs b/src/graphql-aspnet/Schemas/TypeSystem/ObjectGraphType.cs index 2a35272b3..d7f6a010a 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/ObjectGraphType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/ObjectGraphType.cs @@ -28,20 +28,20 @@ public class ObjectGraphType : ObjectGraphTypeBase, IObjectGraphType /// Initializes a new instance of the class. ///
/// The name of the graph type. + /// The defined internal name for this graph type. /// The concrete type that this graphtype is made from. /// The route path that identifies this object in the schema.. /// The directives applied to this object /// when its added to a schema. public ObjectGraphType( string name, + string internalName, Type objectType, SchemaItemPath route, IAppliedDirectiveCollection directives = null) - : base(name, route, directives) + : base(name, internalName, route, directives) { this.ObjectType = Validation.ThrowIfNullOrReturn(objectType, nameof(objectType)); - this.InternalName = this.ObjectType.FriendlyName(); - this.GraphFieldCollection.AddField(new Introspection_TypeNameMetaField(name)); } @@ -59,8 +59,5 @@ public override bool ValidateObject(object item) /// public Type ObjectType { get; } - - /// - public string InternalName { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/TypeSystem/ObjectGraphTypeBase.cs b/src/graphql-aspnet/Schemas/TypeSystem/ObjectGraphTypeBase.cs index ed5dee2f7..3d57efba2 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/ObjectGraphTypeBase.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/ObjectGraphTypeBase.cs @@ -28,15 +28,18 @@ public abstract class ObjectGraphTypeBase : IGraphType /// Initializes a new instance of the class. ///
/// The name of the graph type as it is displayed in the __type information. + /// The defined internal name for this graph type. /// The route path of this object. /// The directives applied to this schema item /// when its added to a schema. protected ObjectGraphTypeBase( string name, + string internalName, SchemaItemPath route, IAppliedDirectiveCollection directives = null) { this.Name = Validation.ThrowIfNullWhiteSpaceOrReturn(name, nameof(name)); + this.InternalName = Validation.ThrowIfNullWhiteSpaceOrReturn(internalName, nameof(internalName)); this.Route = Validation.ThrowIfNullOrReturn(route, nameof(route)); _graphFields = new GraphFieldCollection(this); this.InterfaceNames = new HashSet(); @@ -70,6 +73,9 @@ protected ObjectGraphTypeBase( /// public virtual string Name { get; set; } + /// + public string InternalName { get; } + /// public virtual string Description { get; set; } diff --git a/src/graphql-aspnet/Schemas/TypeSystem/PropertyGraphField.cs b/src/graphql-aspnet/Schemas/TypeSystem/PropertyGraphField.cs deleted file mode 100644 index 220028001..000000000 --- a/src/graphql-aspnet/Schemas/TypeSystem/PropertyGraphField.cs +++ /dev/null @@ -1,74 +0,0 @@ -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - -namespace GraphQL.AspNet.Schemas.TypeSystem -{ - using System; - using System.Collections.Generic; - using GraphQL.AspNet.Execution; - using GraphQL.AspNet.Interfaces.Execution; - using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Schemas.Structural; - using GraphQL.AspNet.Security; - - /// - /// A representation of a field as it would be defined in an object graph that originated - /// from a .NET property getter. - /// - public class PropertyGraphField : MethodGraphField, ITypedSchemaItem - { - /// - /// Initializes a new instance of the class. - /// - /// Name of the field in the public graph. - /// The type expression declaring what type of data this field returns. - /// The route to this field in the graph. - /// The name of the property as it was declared on the (its internal name). - /// The .NET type of the item or items that represent the graph type returned by this field. - /// The .NET type as it was declared on the property which generated this field.. - /// The mode in which the runtime will process this field. - /// The resolver to be invoked to produce data when this field is called. - /// The security policies that apply to this field. - /// The directives to apply to this field when its added to a schema. - public PropertyGraphField( - string fieldName, - GraphTypeExpression typeExpression, - SchemaItemPath route, - string declaredPropertyName, - Type objectType, - Type declaredReturnType, - FieldResolutionMode mode = FieldResolutionMode.PerSourceItem, - IGraphFieldResolver resolver = null, - IEnumerable securityPolicies = null, - IAppliedDirectiveCollection directives = null) - : base(fieldName, typeExpression, route, declaredPropertyName, objectType, declaredReturnType, mode, resolver, securityPolicies, directives) - { - } - - /// - /// Creates a new instance of a graph field from this type. - /// - /// The item to assign as the parent of the new field. - /// IGraphField. - protected override MethodGraphField CreateNewInstance(IGraphType parent) - { - return new PropertyGraphField( - this.Name, - this.TypeExpression.Clone(), - parent.Route.CreateChild(this.Name), - this.InternalName, - this.ObjectType, - this.DeclaredReturnType, - this.Mode, - this.Resolver, - this.SecurityGroups, - this.AppliedDirectives); - } - } -} \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/TypeSystem/UnionGraphType.cs b/src/graphql-aspnet/Schemas/TypeSystem/UnionGraphType.cs index 4354c4aca..17f54aef4 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/UnionGraphType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/UnionGraphType.cs @@ -34,6 +34,7 @@ public class UnionGraphType : IUnionGraphType /// Initializes a new instance of the class. ///
/// The name of the union as it appears in the target schema (case sensitive). + /// The defined internal name for this graph type. /// The type resolver used to match field resolve values with /// expected graph types in this union. /// The unique route of this item. @@ -41,11 +42,13 @@ public class UnionGraphType : IUnionGraphType /// to execute against this union when it is added to a schema. public UnionGraphType( string name, + string internalName, IUnionGraphTypeMapper typeResolver, SchemaItemPath route, IAppliedDirectiveCollection directives = null) { this.Name = Validation.ThrowIfNullWhiteSpaceOrReturn(name, nameof(name)); + this.InternalName = Validation.ThrowIfNullWhiteSpaceOrReturn(internalName, nameof(internalName)); this.Route = Validation.ThrowIfNullOrReturn(route, nameof(route)); this.TypeMapper = typeResolver; this.Publish = true; @@ -88,6 +91,9 @@ public virtual void AddPossibleGraphType(string graphTypeName, Type concreteType /// public virtual string Name { get; set; } + /// + public string InternalName { get; } + /// public virtual string Description { get; set; } diff --git a/src/graphql-aspnet/Schemas/TypeSystem/VirtualObjectGraphType.cs b/src/graphql-aspnet/Schemas/TypeSystem/VirtualObjectGraphType.cs index 1f9bdeca2..487dbeb87 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/VirtualObjectGraphType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/VirtualObjectGraphType.cs @@ -40,6 +40,7 @@ public class VirtualObjectGraphType : ObjectGraphTypeBase, IObjectGraphType, IIn public VirtualObjectGraphType(string name) : base( name, + $"{nameof(VirtualObjectGraphType)}_{name}", new SchemaItemPath(SchemaItemCollections.Types, name)) { // add the __typename as a field for this virtual object @@ -63,8 +64,5 @@ public IGraphField Extend(IGraphField newField) /// public Type ObjectType => typeof(VirtualObjectGraphType); - - /// - public string InternalName => typeof(VirtualObjectGraphType).FriendlyName(); } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-testframework/TestServer.cs b/src/unit-tests/graphql-aspnet-testframework/TestServer.cs index 681cd35c2..9688f1cab 100644 --- a/src/unit-tests/graphql-aspnet-testframework/TestServer.cs +++ b/src/unit-tests/graphql-aspnet-testframework/TestServer.cs @@ -281,7 +281,7 @@ public virtual FieldContextBuilder CreateFieldContextBuilder(Type entityType, st // fallback, try and find by method/property name foreach (var item in graphType.Fields) { - if (item.Resolver.MetaData.InternalName == fieldOrActionName) + if (item.Resolver.MetaData.DeclaredName == fieldOrActionName) { field = item; break; diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultScalarTypeProviderTestData/ScalarIncorrectAppliedDirectivesParent.cs b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultScalarTypeProviderTestData/ScalarIncorrectAppliedDirectivesParent.cs index ee86ba590..ff64e9d01 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultScalarTypeProviderTestData/ScalarIncorrectAppliedDirectivesParent.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultScalarTypeProviderTestData/ScalarIncorrectAppliedDirectivesParent.cs @@ -23,6 +23,8 @@ public class SomeItem : ISchemaItem public string Name { get; set; } public string Description { get; set; } + + public string InternalName { get; set; } } public ScalarIncorrectAppliedDirectivesParent() diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospectionTestData/SodaTypeUnionProxy.cs b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospectionTestData/SodaTypeUnionProxy.cs index 9b6d8d85a..35583ee29 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospectionTestData/SodaTypeUnionProxy.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/TestData/IntrospectionTestData/SodaTypeUnionProxy.cs @@ -23,6 +23,8 @@ public class SodaTypeUnionProxy : IGraphUnionProxy public bool Publish { get; set; } = true; + public string InternalName { get; } = "InternalSodaTypes"; + public Type MapType(Type runtimeObjectType) { return runtimeObjectType; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/FieldMaker_InputFieldTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/FieldMaker_InputFieldTests.cs index 9159c065a..b036ef0c8 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/FieldMaker_InputFieldTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/FieldMaker_InputFieldTests.cs @@ -38,7 +38,7 @@ public void Parse_NotRequiredValueTypePropertyCheck() // non-nullable value type Assert.AreEqual("Int!", graphField.TypeExpression.ToString()); Assert.AreEqual("[type]/Input_InputTestObject/NotRequiredValueTypeField", graphField.Route.ToString()); - Assert.AreEqual("NotRequiredValueTypeField", graphField.InternalName); + Assert.AreEqual("NotRequiredValueTypeField", graphField.DeclaredName); Assert.AreEqual(typeof(int), graphField.DeclaredReturnType); Assert.AreEqual(1, graphField.AppliedDirectives.Count); @@ -63,7 +63,7 @@ public void Parse_RequiredValueTypePropertyCheck() Assert.AreEqual("Int!", graphField.TypeExpression.ToString()); Assert.AreEqual("[type]/Input_InputTestObject/RequiredValueTypeField", graphField.Route.ToString()); - Assert.AreEqual("RequiredValueTypeField", graphField.InternalName); + Assert.AreEqual("RequiredValueTypeField", graphField.DeclaredName); Assert.AreEqual(typeof(int), graphField.DeclaredReturnType); Assert.AreEqual(0, graphField.AppliedDirectives.Count); @@ -80,7 +80,8 @@ public void Parse_NotRequiredReferenceTypePropertyCheck() .Values .Single(x => x.Name == nameof(InputTestObject.NotRequiredReferenceTypeField)); - var graphField = new GraphFieldMaker(server.Schema, new GraphArgumentMaker(server.Schema)).CreateField(fieldTemplate).Field; + var graphField = new GraphFieldMaker(server.Schema, new GraphArgumentMaker(server.Schema)) + .CreateField(fieldTemplate).Field; Assert.AreEqual("notRequiredReferenceTypeField", graphField.Name); Assert.IsFalse(graphField.IsRequired); @@ -89,7 +90,8 @@ public void Parse_NotRequiredReferenceTypePropertyCheck() // meaning the type expression should also be "nullable" Assert.AreEqual("Input_TwoPropertyObject", graphField.TypeExpression.ToString()); Assert.AreEqual("[type]/Input_InputTestObject/NotRequiredReferenceTypeField", graphField.Route.ToString()); - Assert.AreEqual("NotRequiredReferenceTypeField", graphField.InternalName); + Assert.AreEqual("InputTestObject.NotRequiredReferenceTypeField", graphField.InternalName); + Assert.AreEqual("NotRequiredReferenceTypeField", graphField.DeclaredName); Assert.AreEqual(typeof(TwoPropertyObject), graphField.DeclaredReturnType); Assert.AreEqual(0, graphField.AppliedDirectives.Count); @@ -117,7 +119,7 @@ public void Parse_RequiredReferenceTypePropertyCheck() // the type expression is automatically hoisted to be "non-nullable" Assert.AreEqual("Input_TwoPropertyObject", graphField.TypeExpression.ToString()); Assert.AreEqual("[type]/Input_InputTestObject/RequiredReferenceTypeField", graphField.Route.ToString()); - Assert.AreEqual("RequiredReferenceTypeField", graphField.InternalName); + Assert.AreEqual("RequiredReferenceTypeField", graphField.DeclaredName); Assert.AreEqual(typeof(TwoPropertyObject), graphField.DeclaredReturnType); Assert.AreEqual(0, graphField.AppliedDirectives.Count); @@ -143,7 +145,7 @@ public void Parse_RequiredNonNullableReferenceTypePropertyCheck() // the type expression is automatically hoisted to be "non-nullable" Assert.AreEqual("Input_TwoPropertyObject!", graphField.TypeExpression.ToString()); Assert.AreEqual("[type]/Input_InputTestObject/RequiredReferenceExplicitNonNullTypeField", graphField.Route.ToString()); - Assert.AreEqual("RequiredReferenceExplicitNonNullTypeField", graphField.InternalName); + Assert.AreEqual("RequiredReferenceExplicitNonNullTypeField", graphField.DeclaredName); Assert.AreEqual(typeof(TwoPropertyObject), graphField.DeclaredReturnType); Assert.AreEqual(0, graphField.AppliedDirectives.Count); @@ -168,7 +170,7 @@ public void Parse_RequiredGraphIdPropertyCheck() // scalar is required by default Assert.AreEqual("ID!", graphField.TypeExpression.ToString()); Assert.AreEqual("[type]/Input_InputTestObject/GraphIdRequired", graphField.Route.ToString()); - Assert.AreEqual("GraphIdRequired", graphField.InternalName); + Assert.AreEqual("GraphIdRequired", graphField.DeclaredName); Assert.AreEqual(typeof(GraphId), graphField.DeclaredReturnType); Assert.AreEqual(0, graphField.AppliedDirectives.Count); @@ -192,7 +194,7 @@ public void Parse_NotRequiredGraphIdPropertyCheck() Assert.AreEqual("ID!", graphField.TypeExpression.ToString()); Assert.AreEqual("[type]/Input_InputTestObject/GraphIdNotRequired", graphField.Route.ToString()); - Assert.AreEqual("GraphIdNotRequired", graphField.InternalName); + Assert.AreEqual("GraphIdNotRequired", graphField.DeclaredName); Assert.AreEqual(typeof(GraphId), graphField.DeclaredReturnType); Assert.AreEqual(0, graphField.AppliedDirectives.Count); @@ -216,7 +218,7 @@ public void Parse_NotRequiredNullableGraphIdPropertyCheck() Assert.AreEqual("ID", graphField.TypeExpression.ToString()); Assert.AreEqual("[type]/Input_InputTestObject/GraphIdNullable", graphField.Route.ToString()); - Assert.AreEqual("GraphIdNullable", graphField.InternalName); + Assert.AreEqual("GraphIdNullable", graphField.DeclaredName); Assert.AreEqual(typeof(GraphId?), graphField.DeclaredReturnType); Assert.AreEqual(0, graphField.AppliedDirectives.Count); diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/UnionTestProxy.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/UnionTestProxy.cs index a7129705e..0acbcdd63 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/UnionTestProxy.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/UnionTestProxy.cs @@ -27,6 +27,8 @@ public class UnionTestProxy : IGraphUnionProxy public bool Publish { get; set; } = true; + public string InternalName => "Internal_BobUnion"; + public Type MapType(Type runtimeObjectType) { return runtimeObjectType; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/UnionTestProxy.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/UnionTestProxy.cs index 5e68cbbe2..56e56df71 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/UnionTestProxy.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/UnionTestProxy.cs @@ -17,6 +17,8 @@ public class UnionTestProxy : IGraphUnionProxy { public string Name { get; set; } = "BobUnion"; + public string InternalName { get; } = "BobUnionInternal"; + public string Description { get; set; } = "This is the Bob union"; public HashSet Types { get; } = new HashSet() diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NullTypesUnionProxy.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NullTypesUnionProxy.cs index 599c5107d..5e5439be8 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NullTypesUnionProxy.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GlobalTypesTestData/NullTypesUnionProxy.cs @@ -18,6 +18,7 @@ public class NullTypesUnionProxy : IGraphUnionProxy public NullTypesUnionProxy() { this.Name = "Name"; + this.InternalName = "NulLTypesUnionProxy"; this.Types = null; } @@ -29,6 +30,8 @@ public NullTypesUnionProxy() public string Description { get; set; } + public string InternalName { get; } + public Type MapType(Type runtimeObjectType) { return null; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GraphFieldArgumentCloningTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GraphFieldArgumentCloningTests.cs index e954cfe6a..5710c520e 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/GraphFieldArgumentCloningTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GraphFieldArgumentCloningTests.cs @@ -32,10 +32,10 @@ public void ClonedArgument_PropertyCheck() var arg = new GraphFieldArgument( parentField.Object, "argName", + "internalName", + "paramName", GraphTypeExpression.FromDeclaration("String"), new SchemaItemPath("[type]/GraphType1/Field1/Arg1"), - "paramName", - "internalName", typeof(string), true, "default value", diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GraphFieldCloningTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GraphFieldCloningTests.cs index d240bfaae..f0155a84f 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/GraphFieldCloningTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GraphFieldCloningTests.cs @@ -45,11 +45,11 @@ public void MethodField_PropertyCheck() var field = new MethodGraphField( "field1", + "internalFieldName", GraphTypeExpression.FromDeclaration("[Int]"), new SchemaItemPath("[type]/JohnType/field1"), - "internalFieldName", - typeof(TwoPropertyObject), typeof(List), + typeof(TwoPropertyObject), AspNet.Execution.FieldResolutionMode.PerSourceItem, resolver.Object, polices, @@ -60,90 +60,10 @@ public void MethodField_PropertyCheck() field.Arguments.AddArgument(new GraphFieldArgument( field, "arg1", - GraphTypeExpression.FromDeclaration("String"), - field.Route.CreateChild("arg1"), "arg1", "arg1", - typeof(string), - false)); - - field.Complexity = 1.3f; - field.IsDeprecated = true; - field.DeprecationReason = "Because I said so"; - field.Publish = false; - field.FieldSource = GraphFieldSource.Method; - - var clonedParent = new Mock(); - clonedParent.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/BobType")); - clonedParent.Setup(x => x.Name).Returns("BobType"); - var clonedField = field.Clone(clonedParent.Object); - - Assert.AreEqual(field.Name, clonedField.Name); - Assert.AreEqual(field.ObjectType, clonedField.ObjectType); - Assert.AreEqual(field.DeclaredReturnType, clonedField.DeclaredReturnType); - Assert.AreEqual(clonedField.TypeExpression.ToString(), clonedField.TypeExpression.ToString()); - Assert.AreEqual(field.Description, clonedField.Description); - Assert.AreEqual(field.Publish, clonedField.Publish); - Assert.AreEqual("[type]/BobType/field1", clonedField.Route.Path); - Assert.AreEqual(field.Mode, clonedField.Mode); - Assert.AreEqual(field.IsDeprecated, clonedField.IsDeprecated); - Assert.AreEqual(field.DeprecationReason, clonedField.DeprecationReason); - Assert.AreEqual(field.Complexity, clonedField.Complexity); - Assert.AreEqual(field.FieldSource, clonedField.FieldSource); - Assert.AreEqual(field.InternalName, clonedField.InternalName); - - Assert.IsFalse(object.ReferenceEquals(field.TypeExpression, clonedField.TypeExpression)); - Assert.IsTrue(object.ReferenceEquals(field.Resolver, clonedField.Resolver)); - Assert.IsFalse(object.ReferenceEquals(field.AppliedDirectives, clonedField.AppliedDirectives)); - Assert.IsFalse(object.ReferenceEquals(field.SecurityGroups, clonedField.SecurityGroups)); - Assert.IsFalse(object.ReferenceEquals(field.Arguments, clonedField.Arguments)); - - Assert.AreEqual(field.AppliedDirectives.Count, clonedField.AppliedDirectives.Count); - Assert.AreEqual(field.SecurityGroups.Count(), clonedField.SecurityGroups.Count()); - Assert.AreEqual(field.Arguments.Count, clonedField.Arguments.Count); - - foreach (var arg in field.Arguments) - { - var foundArg = clonedField.Arguments.FindArgument(arg.Name); - Assert.IsNotNull(foundArg); - } - } - - [Test] - public void PropertyField_PropertyCheck() - { - var originalParent = new Mock(); - originalParent.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/JohnType")); - originalParent.Setup(x => x.Name).Returns("JohnType"); - - var resolver = new Mock(); - var polices = new List(); - polices.Add(AppliedSecurityPolicyGroup.FromAttributeCollection(typeof(GraphFieldCloningTests))); - - var appliedDirectives = new AppliedDirectiveCollection(); - appliedDirectives.Add(new AppliedDirective("someDirective", 3)); - - var field = new PropertyGraphField( - "field1", - GraphTypeExpression.FromDeclaration("[Int]"), - new SchemaItemPath("[type]/JohnType/field1"), - "Prop1", - typeof(TwoPropertyObject), - typeof(List), - FieldResolutionMode.PerSourceItem, - resolver.Object, - polices, - appliedDirectives); - - field.AssignParent(originalParent.Object); - - field.Arguments.AddArgument(new GraphFieldArgument( - field, - "arg1", GraphTypeExpression.FromDeclaration("String"), field.Route.CreateChild("arg1"), - "arg1", - "arg1", typeof(string), false)); @@ -156,10 +76,8 @@ public void PropertyField_PropertyCheck() var clonedParent = new Mock(); clonedParent.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/BobType")); clonedParent.Setup(x => x.Name).Returns("BobType"); - var clonedField = field.Clone(clonedParent.Object) as PropertyGraphField; + var clonedField = field.Clone(clonedParent.Object); - Assert.IsNotNull(clonedField); - Assert.AreEqual(field.InternalName, clonedField.InternalName); Assert.AreEqual(field.Name, clonedField.Name); Assert.AreEqual(field.ObjectType, clonedField.ObjectType); Assert.AreEqual(field.DeclaredReturnType, clonedField.DeclaredReturnType); @@ -172,6 +90,7 @@ public void PropertyField_PropertyCheck() Assert.AreEqual(field.DeprecationReason, clonedField.DeprecationReason); Assert.AreEqual(field.Complexity, clonedField.Complexity); Assert.AreEqual(field.FieldSource, clonedField.FieldSource); + Assert.AreEqual(field.InternalName, clonedField.InternalName); Assert.IsFalse(object.ReferenceEquals(field.TypeExpression, clonedField.TypeExpression)); Assert.IsTrue(object.ReferenceEquals(field.Resolver, clonedField.Resolver)); From 456a55a507b8505966303fac14056f64905924d0 Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Sun, 23 Jul 2023 09:47:04 -0700 Subject: [PATCH 46/63] WIP, included support for [Union] attribute on GraphFieldTemplateBase. --- .../Attributes/MutationAttribute.cs | 12 +- .../Attributes/MutationRootAttribute.cs | 12 +- .../Attributes/QueryAttribute.cs | 12 +- .../Attributes/QueryRootAttribute.cs | 12 +- .../Attributes/UnionAttribute.cs | 82 +++++ ...hemaItemDefinitionExtensions_Directives.cs | 37 ++- ...ItemDefinitionExtensions_ResolvedFields.cs | 19 ++ ...ItemDefinitionExtensions_TypeExtensions.cs | 19 ++ .../IGraphQLResolvableSchemaItemDefinition.cs | 9 +- .../RuntimeDirectiveActionDefinition.cs | 7 +- .../RuntimeResolvedFieldDefinition.cs | 13 +- .../RuntimeTypeExtensionDefinition.cs | 10 +- .../TypeTemplates/GraphFieldTemplateBase.cs | 311 ++++++++++++------ .../GraphTypeExtensionFieldTemplate.cs | 22 +- .../RuntimeGraphDirectiveTemplate.cs | 9 + .../MappedDirectiveTemplateTests.cs | 16 + .../MappedTypeExtensionTemplateTests.cs | 15 + .../ResolvedFieldTemplateTests.cs | 13 + .../ActionMethodTemplateTests.cs | 34 +- .../ActionResultReturnTypeController.cs | 2 +- .../InterfaceReturnTypeController.cs | 2 +- .../RuntimeControllerActionTemplateTests.cs | 66 ++++ 22 files changed, 592 insertions(+), 142 deletions(-) create mode 100644 src/graphql-aspnet/Attributes/UnionAttribute.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/RuntimeControllerActionTemplateTests.cs diff --git a/src/graphql-aspnet/Attributes/MutationAttribute.cs b/src/graphql-aspnet/Attributes/MutationAttribute.cs index 3e199d712..dfc895a4c 100644 --- a/src/graphql-aspnet/Attributes/MutationAttribute.cs +++ b/src/graphql-aspnet/Attributes/MutationAttribute.cs @@ -36,7 +36,17 @@ public MutationAttribute() ///
/// The template naming scheme to use to generate a graph field from this method. public MutationAttribute(string template) - : this(template, null) + : this(template, null as Type) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The template naming scheme to use to generate a graph field from this method. + /// Name of the union type. + public MutationAttribute(string template, string unionTypeName) + : this(template, unionTypeName, null, null) { } diff --git a/src/graphql-aspnet/Attributes/MutationRootAttribute.cs b/src/graphql-aspnet/Attributes/MutationRootAttribute.cs index 9cebba929..1f6e76d5e 100644 --- a/src/graphql-aspnet/Attributes/MutationRootAttribute.cs +++ b/src/graphql-aspnet/Attributes/MutationRootAttribute.cs @@ -35,7 +35,17 @@ public MutationRootAttribute() ///
/// The template naming scheme to use to generate a graph field from this method. public MutationRootAttribute(string template) - : this(template, null) + : this(template, null as Type) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The template naming scheme to use to generate a graph field from this method. + /// Name of the union type. + public MutationRootAttribute(string template, string unionTypeName) + : this(template, unionTypeName, null, null) { } diff --git a/src/graphql-aspnet/Attributes/QueryAttribute.cs b/src/graphql-aspnet/Attributes/QueryAttribute.cs index 0e2ff7aa8..a6b0f34d7 100644 --- a/src/graphql-aspnet/Attributes/QueryAttribute.cs +++ b/src/graphql-aspnet/Attributes/QueryAttribute.cs @@ -36,7 +36,17 @@ public QueryAttribute() ///
/// The template naming scheme to use to generate a graph field from this method. public QueryAttribute(string template) - : this(template, null) + : this(template, null as Type) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The template naming scheme to use to generate a graph field from this method. + /// Name of the union type. + public QueryAttribute(string template, string unionTypeName) + : this(template, unionTypeName, null, null) { } diff --git a/src/graphql-aspnet/Attributes/QueryRootAttribute.cs b/src/graphql-aspnet/Attributes/QueryRootAttribute.cs index fe6d73102..85aa7cc4c 100644 --- a/src/graphql-aspnet/Attributes/QueryRootAttribute.cs +++ b/src/graphql-aspnet/Attributes/QueryRootAttribute.cs @@ -35,7 +35,17 @@ public QueryRootAttribute() /// /// The template naming scheme to use to generate a graph field from this method. public QueryRootAttribute(string template) - : this(template, null) + : this(template, null as Type) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The template naming scheme to use to generate a graph field from this method. + /// Name of the union type. + public QueryRootAttribute(string template, string unionTypeName) + : this(template, unionTypeName, null, null) { } diff --git a/src/graphql-aspnet/Attributes/UnionAttribute.cs b/src/graphql-aspnet/Attributes/UnionAttribute.cs new file mode 100644 index 000000000..c8bfe491b --- /dev/null +++ b/src/graphql-aspnet/Attributes/UnionAttribute.cs @@ -0,0 +1,82 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Attributes +{ + using System; + using System.Collections.Generic; + using GraphQL.AspNet.Interfaces.Controllers; + using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Schemas.TypeSystem; + + /// + /// An attribute that, when applied to an action method, field or property + /// declares that the field is to return one of multiple possible types. + /// + /// + /// Fields applying this attribute should return a or + /// for maximum compatiability. + /// + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property)] + public class UnionAttribute : GraphAttributeBase + { + /// + /// Initializes a new instance of the class. + /// + /// The name of the union as it should appear in the schema. + /// The first member type to include in the union. + /// The second member type to include in the union. + /// Additional member types to include in the union. + /// + /// All Unions must declare at least two member types that will be included in the union. + /// + public UnionAttribute(string unionName, Type firstUnionMemberType, Type secondUnionMemberType, params Type[] otherUnionMembers) + { + this.UnionProxyType = null; + this.UnionName = unionName?.Trim(); + + var list = new List(2 + otherUnionMembers.Length); + list.Add(firstUnionMemberType); + list.Add(secondUnionMemberType); + list.AddRange(otherUnionMembers); + this.UnionMemberTypes = list; + } + + /// + /// Initializes a new instance of the class. + /// + /// A type that inherits from or implements which + /// declares all required information about the referenced union. + public UnionAttribute(Type unionProxyType) + { + this.UnionProxyType = unionProxyType; + this.UnionName = null; + this.UnionProxyType = null; + } + + /// + /// Gets a type that implements inherits from or + /// that declares all required information about the referenced union. + /// + /// The union proxy type to reference when building the schema references for this field. + public Type UnionProxyType { get; } + + /// + /// Gets the name of the new union to create within the schema. This union name must be a valid graph name. + /// + /// The name of the union as it will appear in the schema. + public string UnionName { get; } + + /// + /// Gets the concrete types of the objects that may be returned by this field. + /// + /// All union member types to be included in this union. + public IReadOnlyList UnionMemberTypes { get; } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Directives.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Directives.cs index faca9cb93..cf8509d61 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Directives.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Directives.cs @@ -32,7 +32,7 @@ public static partial class GraphQLRuntimeSchemaItemDefinitionExtensions /// The directive being built. /// The name of the policy to assign via this requirement. /// A comma-seperated list of roles to assign via this requirement. - /// IGraphQLFieldBuilder. + /// IGraphQLRuntimeDirectiveDefinition. public static IGraphQLRuntimeDirectiveDefinition RequireAuthorization( this IGraphQLRuntimeDirectiveDefinition directiveTemplate, string policyName = null, @@ -60,7 +60,7 @@ public static IGraphQLRuntimeDirectiveDefinition RequireAuthorization( /// /// /// The directive being built. - /// IGraphQLFieldBuilder. + /// IGraphQLRuntimeDirectiveDefinition. public static IGraphQLRuntimeDirectiveDefinition AllowAnonymous(this IGraphQLRuntimeDirectiveDefinition directiveTemplate) { Validation.ThrowIfNull(directiveTemplate, nameof(directiveTemplate)); @@ -73,7 +73,7 @@ public static IGraphQLRuntimeDirectiveDefinition AllowAnonymous(this IGraphQLRun /// schema item more than once. /// /// The directive template. - /// IGraphQLDirectiveTemplate. + /// IGraphQLRuntimeDirectiveDefinition. public static IGraphQLRuntimeDirectiveDefinition IsRepeatable(this IGraphQLRuntimeDirectiveDefinition directiveTemplate) { var repeatable = new RepeatableAttribute(); @@ -91,7 +91,7 @@ public static IGraphQLRuntimeDirectiveDefinition IsRepeatable(this IGraphQLRunti /// The directive template to alter. /// The bitwise set of locations where this /// directive can be applied. - /// IGraphQLDirectiveTemplate. + /// IGraphQLRuntimeDirectiveDefinition. public static IGraphQLRuntimeDirectiveDefinition RestrictLocations( this IGraphQLRuntimeDirectiveDefinition directiveTemplate, DirectiveLocation locations) @@ -116,7 +116,7 @@ public static IGraphQLRuntimeDirectiveDefinition RestrictLocations( /// The directive being built. /// The delegate to assign as the resolver. This method will be /// parsed to determine input arguments for the field on the target schema. - /// IGraphQLFieldBuilder. + /// IGraphQLRuntimeDirectiveDefinition. public static IGraphQLRuntimeDirectiveDefinition AddResolver(this IGraphQLRuntimeDirectiveDefinition directiveTemplate, Delegate resolverMethod) { directiveTemplate.Resolver = resolverMethod; @@ -136,7 +136,7 @@ public static IGraphQLRuntimeDirectiveDefinition AddResolver(this IGraphQLRuntim /// The directive being built. /// The delegate to assign as the resolver. This method will be /// parsed to determine input arguments for the directive on the target schema. - /// IGraphQLFieldBuilder. + /// IGraphQLRuntimeDirectiveDefinition. public static IGraphQLRuntimeDirectiveDefinition AddResolver(this IGraphQLRuntimeDirectiveDefinition directiveTemplate, Delegate resolverMethod) { directiveTemplate.Resolver = resolverMethod; @@ -144,12 +144,31 @@ public static IGraphQLRuntimeDirectiveDefinition AddResolver(this I return directiveTemplate; } + /// + /// Assigns a custom value to the internal name of this directive. This value will be used in error + /// messages and log entries instead of an anonymous method name. This can significantly increase readability + /// while trying to debug an issue. + /// + /// + /// This value does NOT affect the directive name as it would appear in a schema. It only effects the internal + /// name used in log messages and exception text. + /// + /// The directive being built. + /// The value to use as the internal name for this field definition when its + /// added to the schema. + /// IGraphQLRuntimeDirectiveDefinition. + public static IGraphQLRuntimeDirectiveDefinition WithName(this IGraphQLRuntimeDirectiveDefinition directiveTemplate, string internalName) + { + directiveTemplate.InternalName = internalName; + return directiveTemplate; + } + /// /// Maps a new directive into the target schema. /// /// The schema options where the directive will be created. /// Name of the directive (e.g. '@myDirective'). - /// IGraphQLDirectiveTemplate. + /// IGraphQLRuntimeDirectiveDefinition. public static IGraphQLRuntimeDirectiveDefinition MapDirective(this SchemaOptions schemaOptions, string directiveName) { return MapDirectiveInternal(schemaOptions, directiveName); @@ -161,7 +180,7 @@ public static IGraphQLRuntimeDirectiveDefinition MapDirective(this SchemaOptions /// The schema options where the directive will be created. /// Name of the directive (e.g. '@myDirective'). /// The resolver that will be executed when the directive is invoked. - /// IGraphQLDirectiveTemplate. + /// IGraphQLRuntimeDirectiveDefinition. public static IGraphQLRuntimeDirectiveDefinition MapDirective(this SchemaOptions schemaOptions, string directiveName, Delegate resolverMethod) { Validation.ThrowIfNull(resolverMethod, nameof(resolverMethod)); @@ -175,7 +194,7 @@ public static IGraphQLRuntimeDirectiveDefinition MapDirective(this SchemaOptions /// /// The builder representing the schema being constructed. /// Name of the directive (e.g. '@myDirective'). - /// IGraphQLDirectiveTemplate. + /// IGraphQLRuntimeDirectiveDefinition. public static IGraphQLRuntimeDirectiveDefinition MapDirective(this ISchemaBuilder schemaBuilder, string directiveName) { Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_ResolvedFields.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_ResolvedFields.cs index fe80302c3..533c118ae 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_ResolvedFields.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_ResolvedFields.cs @@ -116,5 +116,24 @@ public static IGraphQLRuntimeResolvedFieldDefinition AddPossibleTypes(this IGrap fieldBuilder.AddAttribute(possibleTypes); return fieldBuilder; } + + /// + /// Assigns a custom value to the internal name of this field. This value will be used in error + /// messages and log entries instead of anonymous method name. This can significantly increase readability + /// while trying to debug an issue. + /// + /// + /// This value does NOT affect the field name as it would appear in a schema. It only effects the internal + /// name used in log messages and exception text. + /// + /// The field being built. + /// The value to use as the internal name for this field definition when its + /// added to the schema. + /// IGraphQLFieldBuilder. + public static IGraphQLRuntimeResolvedFieldDefinition WithName(this IGraphQLRuntimeResolvedFieldDefinition fieldBuilder, string internalName) + { + fieldBuilder.InternalName = internalName; + return fieldBuilder; + } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_TypeExtensions.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_TypeExtensions.cs index bf9e24144..bab8bd179 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_TypeExtensions.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_TypeExtensions.cs @@ -216,5 +216,24 @@ public static IGraphQLRuntimeTypeExtensionDefinition AddPossibleTypes(this IGrap fieldBuilder.AddAttribute(possibleTypes); return fieldBuilder; } + + /// + /// Assigns a custom value to the internal name of this type exension. This value will be used in error + /// messages and log entries instead of an anonymous method name. This can significantly increase readability + /// while trying to debug an issue. + /// + /// + /// This value does NOT affect the field name as it would appear in a schema. It only effects the internal + /// name used in log messages and exception text. + /// + /// The type exension field being built. + /// The value to use as the internal name for this field definition when its + /// added to the schema. + /// IGraphQLFieldBuilder. + public static IGraphQLRuntimeTypeExtensionDefinition WithName(this IGraphQLRuntimeTypeExtensionDefinition fieldBuilder, string internalName) + { + fieldBuilder.InternalName = internalName; + return fieldBuilder; + } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLResolvableSchemaItemDefinition.cs b/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLResolvableSchemaItemDefinition.cs index 88b1be02b..a6e487254 100644 --- a/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLResolvableSchemaItemDefinition.cs +++ b/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLResolvableSchemaItemDefinition.cs @@ -26,9 +26,16 @@ public interface IGraphQLResolvableSchemaItemDefinition : IGraphQLRuntimeSchemaI /// /// Gets or sets the explicitly declared return type of this schema item. Can be - /// null if the returns a valid concrete type. + /// null if the returns a valid concrete type. May also be a + /// type that implements for items that return a union of values. /// /// The data type this schema item will return. Type ReturnType { get; set; } + + /// + /// Gets or sets the internal name that will be applied this item in the schema. + /// + /// The internal name to apply to this schema item when its created. + string InternalName { get; set; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeDirectiveActionDefinition.cs b/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeDirectiveActionDefinition.cs index 507299a4a..2c908cdb7 100644 --- a/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeDirectiveActionDefinition.cs +++ b/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeDirectiveActionDefinition.cs @@ -45,7 +45,9 @@ protected override Attribute CreatePrimaryAttribute() if (this.AppendedAttributes.OfType().Any()) return null; - return new DirectiveLocationsAttribute(DirectiveLocation.AllExecutionLocations | DirectiveLocation.AllTypeSystemLocations); + return new DirectiveLocationsAttribute(DirectiveLocation.AllExecutionLocations | DirectiveLocation.AllTypeSystemLocations) + { + }; } /// @@ -53,5 +55,8 @@ protected override Attribute CreatePrimaryAttribute() /// public Type ReturnType { get; set; } + + /// + public string InternalName { get; set; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeResolvedFieldDefinition.cs b/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeResolvedFieldDefinition.cs index 5f4f5f489..35698c5ed 100644 --- a/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeResolvedFieldDefinition.cs +++ b/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeResolvedFieldDefinition.cs @@ -90,10 +90,16 @@ protected override Attribute CreatePrimaryAttribute() switch (collection) { case SchemaItemCollections.Query: - return new QueryRootAttribute(path, this.ReturnType); + return new QueryRootAttribute(path, this.ReturnType) + { + InternalName = this.InternalName, + }; case SchemaItemCollections.Mutation: - return new MutationRootAttribute(path, this.ReturnType); + return new MutationRootAttribute(path, this.ReturnType) + { + InternalName = this.InternalName, + }; } return null; @@ -104,5 +110,8 @@ protected override Attribute CreatePrimaryAttribute() /// public Type ReturnType { get; set; } + + /// + public string InternalName { get; set; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeTypeExtensionDefinition.cs b/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeTypeExtensionDefinition.cs index 982ddfca7..2741e6cb5 100644 --- a/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeTypeExtensionDefinition.cs +++ b/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeTypeExtensionDefinition.cs @@ -58,10 +58,16 @@ protected override Attribute CreatePrimaryAttribute() switch (this.ExecutionMode) { case FieldResolutionMode.PerSourceItem: - return new TypeExtensionAttribute(this.TargetType, _fieldName, this.ReturnType); + return new TypeExtensionAttribute(this.TargetType, _fieldName, this.ReturnType) + { + InternalName = this.InternalName, + }; case FieldResolutionMode.Batch: - return new BatchTypeExtensionAttribute(this.TargetType, _fieldName, this.ReturnType); + return new BatchTypeExtensionAttribute(this.TargetType, _fieldName, this.ReturnType) + { + InternalName = this.InternalName, + }; default: throw new NotSupportedException( diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphFieldTemplateBase.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphFieldTemplateBase.cs index 01767e076..e74115c3a 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphFieldTemplateBase.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphFieldTemplateBase.cs @@ -37,6 +37,7 @@ public abstract class GraphFieldTemplateBase : SchemaItemTemplateBase, IGraphFie private GraphFieldAttribute _fieldDeclaration; private bool _invalidTypeExpression; private bool _returnsActionResult; + private bool _duplicateUnionDeclarationDetected; /// /// Initializes a new instance of the class. @@ -49,23 +50,52 @@ protected GraphFieldTemplateBase(IGraphTypeTemplate parent, ICustomAttributeProv { this.Parent = Validation.ThrowIfNullOrReturn(parent, nameof(parent)); _securityPolicies = AppliedSecurityPolicyGroup.Empty; + this.PossibleObjectTypes = new List(); } /// protected override void ParseTemplateDefinition() { + Type StripTasks(Type type) + { + return GraphValidation.EliminateWrappersFromCoreType( + type, + eliminateEnumerables: false, + eliminateTask: true, + eliminateNullableT: false); + } + base.ParseTemplateDefinition(); _fieldDeclaration = this.AttributeProvider.SingleAttributeOfTypeOrDefault(); // ------------------------------------ - // Common Metadata + // Build up a list of possible return types and, if applicable, + // position the declared return type of the resolver to be at the 0th index. + // ------------------------------------ + var potentialReturnTypes = this.GatherAllPossibleReturnedDataTypes() + .Select(x => StripTasks(x)) + .ToList(); + + // extract type info from the return type of the field + // ensure its listed first if it needs to be + var rootDeclaredType = StripTasks(this.DeclaredReturnType); + if (!Validation.IsCastable(rootDeclaredType)) + potentialReturnTypes.Insert(0, rootDeclaredType); + + // remove duplicates and trim to only valid types + potentialReturnTypes = potentialReturnTypes + .Distinct() + .Where(x => GraphValidation.IsValidGraphType(x)) + .ToList(); + + // ------------------------------------ + // Extract Common Metadata // ------------------------------------ this.Route = this.GenerateFieldPath(); this.Mode = _fieldDeclaration?.ExecutionMode ?? FieldResolutionMode.PerSourceItem; this.Complexity = _fieldDeclaration?.Complexity; this.Description = this.AttributeProvider.SingleAttributeOfTypeOrDefault()?.Description; - if (_fieldDeclaration?.TypeExpression == null) { this.DeclaredTypeWrappers = null; @@ -74,96 +104,72 @@ protected override void ParseTemplateDefinition() { var expression = GraphTypeExpression.FromDeclaration(_fieldDeclaration.TypeExpression); if (!expression.IsValid) - { _invalidTypeExpression = true; - } else - { this.DeclaredTypeWrappers = expression.Wrappers; - } } - var objectType = GraphValidation.EliminateWrappersFromCoreType(this.DeclaredReturnType); - var typeExpression = GraphTypeExpression.FromType(this.DeclaredReturnType, this.DeclaredTypeWrappers); - typeExpression = typeExpression.CloneTo(Constants.Other.DEFAULT_TYPE_EXPRESSION_TYPE_NAME); - // ------------------------------------ - // Gather Possible Types and/or union definition + // Build out the union definition if one was supplied // ------------------------------------ - this.BuildUnionProxyInstance(); - if (this.UnionProxy != null) - { - this.PossibleTypes = new List(this.UnionProxy.Types); - } - else - { - this.PossibleTypes = new List(); - - // the possible types attribte is optional but expects that the concrete types are added - // to the schema else where lest a runtime exception occurs of a missing graph type. - var typesAttrib = this.AttributeProvider.SingleAttributeOfTypeOrDefault(); - if (typesAttrib != null) - { - foreach (var type in typesAttrib.PossibleTypes) - this.PossibleTypes.Add(type); - } - - // add any types declared on the primary field declaration - if (_fieldDeclaration != null) - { - foreach (var type in _fieldDeclaration.Types) - { - var strippedType = GraphValidation.EliminateWrappersFromCoreType(type); - if (strippedType != null) - { - this.PossibleTypes.Add(strippedType); - } - } - } - - if (objectType != null && !Validation.IsCastable(objectType) && GraphValidation.IsValidGraphType(objectType)) - { - this.PossibleTypes.Insert(0, objectType); - } - } - - this.PossibleTypes = this.PossibleTypes.Distinct().ToList(); + this.UnionProxy = this.BuildUnionProxyInstance(potentialReturnTypes); // ------------------------------------ - // Adjust the action result to the actual return type this field returns + // Calculate the correct type expression and expected return type // ------------------------------------ + // + // first calculate the initial expression from what is returned by the resolver + // based on the resolver's declarations + var objectType = GraphValidation.EliminateWrappersFromCoreType(this.DeclaredReturnType); + var typeExpression = GraphTypeExpression + .FromType(this.DeclaredReturnType, this.DeclaredTypeWrappers) + .CloneTo(Constants.Other.DEFAULT_TYPE_EXPRESSION_TYPE_NAME); + + // adjust the object type and type expression + // if this field returns an action result if (Validation.IsCastable(objectType)) { _returnsActionResult = true; if (this.UnionProxy != null) { - // if a union was decalred preserve whatever modifer elements - // were decalred but alter the return type to object (a known common element among all members of the union) + // if a union was declared preserve whatever modifer elements + // were declared but alter the return type to "object" + // (a known common element among all members of the union) objectType = typeof(object); + + // clear out the "possible types" that could be returned and + // limit this field to just those of the union (they are already part of the union anyways) + potentialReturnTypes.Clear(); + potentialReturnTypes.AddRange(this.UnionProxy.Types); } - else if (_fieldDeclaration != null && _fieldDeclaration.Types.Count > 0) - { - objectType = _fieldDeclaration.Types[0]; - typeExpression = GraphTypeExpression.FromType(objectType, this.DeclaredTypeWrappers) - .CloneTo(GraphTypeNames.ParseName(objectType, this.Parent.Kind)); - objectType = GraphValidation.EliminateWrappersFromCoreType(objectType); - } - else if (this.PossibleTypes.Count > 0) + else if (potentialReturnTypes.Count > 0) { - objectType = this.PossibleTypes[0]; - typeExpression = GraphTypeExpression.FromType(objectType, this.DeclaredTypeWrappers) - .CloneTo(GraphTypeNames.ParseName(objectType, this.Parent.Kind)); + // the first type in the list will be the primary return type + // when this field is not returning a union + // extract its type expression AND object type to be the primary for the field + objectType = potentialReturnTypes[0]; + typeExpression = GraphTypeExpression + .FromType(objectType, this.DeclaredTypeWrappers) + .CloneTo(Constants.Other.DEFAULT_TYPE_EXPRESSION_TYPE_NAME); + objectType = GraphValidation.EliminateWrappersFromCoreType(objectType); } else { - objectType = typeof(object); + // ths is an error state that will be picked up during validation + objectType = null; } } this.ObjectType = objectType; this.TypeExpression = typeExpression; + // done with type expression, set the final list of potential object types + // to the core types of each return type. + this.PossibleObjectTypes = potentialReturnTypes + .Select(x => GraphValidation.EliminateWrappersFromCoreType(x)) + .ToList(); + // ------------------------------------ // Async Requirements // ------------------------------------ @@ -206,6 +212,13 @@ public override void ValidateOrThrow() } } + if (_duplicateUnionDeclarationDetected) + { + throw new GraphTypeDeclarationException( + $"The field '{this.InternalName}' attempted to define a union multiple times. A union can only be " + + $"defined once per field. Double check the field's applied attributes."); + } + if (this.UnionProxy != null) { GraphValidation.EnsureGraphNameOrThrow($"{this.InternalName}[{nameof(GraphFieldAttribute)}][{nameof(IGraphUnionProxy)}]", this.UnionProxy.Name); @@ -216,11 +229,29 @@ public override void ValidateOrThrow() "but that type includes 0 possible types in the union. Unions require 1 or more possible types. Add additional types" + "or remove the union."); } + + // union methods MUST return a graph action result + var unwrappedReturnType = GraphValidation.EliminateWrappersFromCoreType(this.DeclaredReturnType); + if (!Validation.IsCastable(unwrappedReturnType)) + { + throw new GraphTypeDeclarationException( + $"The field '{this.InternalName}' declares union type of '{this.UnionProxy.Name}'. " + + $"A fields returning a union must return a {nameof(IGraphActionResult)} from the method or property resolver."); + } + } + else if (this.ObjectType == null || this.ObjectType == typeof(object)) + { + // this field is not a union but it also has not declared a proper return type. + // this can happen if the field returns a graph action result and does not declare a return type. + throw new GraphTypeDeclarationException( + $"The field '{this.InternalName}' declared no possible return types either as part of its specification or as the " + + "declared return type for the field. GraphQL requires the type information be known " + + $"to setup the schema and client tooling properly. If this field returns a '{nameof(IGraphActionResult)}' you must " + + "provide a graph field declaration attribute and add at least one type; be that a concrete type, an interface or a union."); } - // ensure the object type returned by the graph field is set correctly - var enforceUnionRules = this.UnionProxy != null; - if (this.PossibleTypes.Count == 0) + // regardless of being a union or not there must always at least one possible return type + if (this.PossibleObjectTypes.Count == 0) { throw new GraphTypeDeclarationException( $"The field '{this.InternalName}' declared no possible return types either as part of its specification or as the " + @@ -230,35 +261,31 @@ public override void ValidateOrThrow() } // validate each type in the list for "correctness" - // Possible Types must conform to the rules of those required by sub type declarations of unions and interfaces + // Possible Types must conform to the rules of those required by sub-type declarations of unions and interfaces // interfaces: https://graphql.github.io/graphql-spec/October2021/#sec-Interfaces // unions: https://graphql.github.io/graphql-spec/October2021/#sec-Unions - foreach (var type in this.PossibleTypes) + var enforceUnionRules = this.UnionProxy != null; + foreach (var type in this.PossibleObjectTypes) { if (enforceUnionRules) { - if (type.IsEnum) - { - throw new GraphTypeDeclarationException( - $"The field '{this.InternalName}' declares a union with a possible type of '{type.FriendlyName()}' " + - "but that type is an enum. Only concrete, non-abstract classes may be used. Value types, such as structs or enumerations, are not allowed."); - } - if (GraphValidation.MustBeLeafType(type)) { throw new GraphTypeDeclarationException( $"The field '{this.InternalName}' declares union with a possible type of '{type.FriendlyName()}' " + - "but that type is a scalar. Scalars cannot be included in a field's possible type collection, only object types can."); + "but that type is a leaf value (i.e. a defined scalar or enum). Scalars and enums cannot be included in a field's possible type collection, only object types can."); } if (type.IsInterface) { throw new GraphTypeDeclarationException( - $"The field '{this.InternalName}' declares union with a possible type of '{type.FriendlyName()}' " + + $"The field '{this.InternalName}' declares union with a possible type of '{type.FriendlyName()}' " + "but that type is an interface. Interfaces cannot be included in a field's possible type collection, only object types can."); } } + // the possible types returned by this field must never include any of the pre-defined + // invalid types foreach (var invalidFieldType in Constants.InvalidFieldTemplateTypes) { if (Validation.IsCastable(type, invalidFieldType)) @@ -272,12 +299,13 @@ public override void ValidateOrThrow() // to ensure an object isn't arbitrarly returned as null and lost // ensure that the any possible type returned from this field is returnable AS the type this field declares // as its return type. In doing this we know that, potentially, an object returned by this - // field "could" cast to the return type and allow field execution to continue. + // field "could" cast itself to the expected return type and allow field execution to continue. // // This is a helpful developer safety check, not a complete guarantee as concrete types for interface - // declarations are not required at this stage + // declarations are not required at this stage. // - // batch processed fields are not subject to this restriction + // batch processed fields and those that return a IGrahpActionResult + // are not subject to this restriction or check if (!_returnsActionResult && this.Mode == FieldResolutionMode.PerSourceItem && !Validation.IsCastable(type, this.ObjectType)) { throw new GraphTypeDeclarationException( @@ -331,7 +359,7 @@ private void ValidateBatchMethodSignatureOrThrow() } var declaredType = GraphValidation.EliminateWrappersFromCoreType(this.DeclaredReturnType); - if (declaredType == typeof(IGraphActionResult)) + if (Validation.IsCastable(declaredType)) return; // when a batch method doesn't return an action result, indicating the developer @@ -353,8 +381,10 @@ private void ValidateBatchMethodSignatureOrThrow() // each member of the union must be castable to 'K' in order for the runtime to properly seperate // and process the batch results var dictionaryValue = GraphValidation.EliminateWrappersFromCoreType(declaredType.GetValueTypeOfDictionary()); - foreach (var type in this.PossibleTypes) + foreach (var type in this.PossibleObjectTypes) { + var s = dictionaryValue.FriendlyName(); + var t = type.FriendlyName(); if (!Validation.IsCastable(type, dictionaryValue)) { throw new GraphTypeDeclarationException( @@ -378,9 +408,9 @@ public override IEnumerable RetrieveRequiredTypes() var list = new List(); list.AddRange(base.RetrieveRequiredTypes()); - if (this.PossibleTypes != null) + if (this.PossibleObjectTypes != null) { - var dependentTypes = this.PossibleTypes + var dependentTypes = this.PossibleObjectTypes .Select(x => new DependentType(x, GraphValidation.ResolveTypeKind(x, this.OwnerTypeKind))); list.AddRange(dependentTypes); } @@ -395,31 +425,104 @@ public override IEnumerable RetrieveRequiredTypes() } /// - /// Retrieves proxy instance defined on this attribute that is used to generate the metadata. + /// Gathers a list, of all possible data types returned by this field. This list should be unfiltered and + /// and contain any decorations as they are declared. Do NOT remove wrappers such as Task{T}, IEnumerable{T} or + /// Nullable{T}. /// - private void BuildUnionProxyInstance() + /// IEnumerable<Type>. + protected virtual IEnumerable GatherAllPossibleReturnedDataTypes() { + // extract types from [GraphField] var fieldAttribute = this.AttributeProvider.SingleAttributeOfTypeOrDefault(); - if (fieldAttribute == null) - return; + if (fieldAttribute?.Types != null) + { + foreach (var type in fieldAttribute.Types) + yield return type; + } - IGraphUnionProxy proxy = null; + // extract types from [Union] + var unionAttribute = this.AttributeProvider.SingleAttributeOfTypeOrDefault(); + if (unionAttribute != null) + { + if (unionAttribute.UnionProxyType != null) + yield return unionAttribute.UnionProxyType; + + if (unionAttribute.UnionMemberTypes != null) + { + foreach (var type in unionAttribute.UnionMemberTypes) + yield return type; + } + } - if (fieldAttribute.Types.Count == 1) + // extract types from [PossibleTypes] + var possibleTypesAttribute = this.AttributeProvider.SingleAttributeOfTypeOrDefault(); + if (possibleTypesAttribute?.PossibleTypes != null) { - var proxyType = fieldAttribute.Types.FirstOrDefault(); - if (proxyType != null) - proxy = GlobalTypes.CreateUnionProxyFromType(proxyType); + foreach (var type in possibleTypesAttribute.PossibleTypes) + yield return type; } + } + + /// + /// Attempts to create a union proxy instance from all the attribute declarations on this field. + /// This proxy will be used to create a union graph type for the field on a schema. If this field does + /// not return a union this method should return null. + /// + /// IGraphUnionProxy. + private IGraphUnionProxy BuildUnionProxyInstance(List potentialReturnTypes) + { + string unionTypeName = null; + var unionDeclaredOnFieldAttribute = false; + var unionAttributeDeclared = false; + + // extract union name from [GraphField] + var fieldAttribute = this.AttributeProvider.SingleAttributeOfTypeOrDefault(); + if (fieldAttribute != null) + { + unionTypeName = fieldAttribute.UnionTypeName; + unionDeclaredOnFieldAttribute = fieldAttribute.UnionTypeName != null; + } + + // extract union name from [Union] + var unionAttribute = this.AttributeProvider.SingleAttributeOfTypeOrDefault(); + if (unionAttribute != null) + { + unionAttributeDeclared = true; + unionTypeName = unionAttribute.UnionName; + } + + // while there are multiple ways to declare a union, each field + // can only accept 1. + if (unionDeclaredOnFieldAttribute && unionAttributeDeclared) + { + _duplicateUnionDeclarationDetected = true; + return null; + } + + // if the only type declared is a reference to a union proxy instnatiate it and use its + // definition for the union + Type unionProxyType = null; + if (potentialReturnTypes.Count == 1 && Validation.IsCastable(potentialReturnTypes[0])) + unionProxyType = potentialReturnTypes[0]; + + IGraphUnionProxy proxy = null; + if (unionProxyType != null) + proxy = GlobalTypes.CreateUnionProxyFromType(unionProxyType); // when no proxy type is declared attempt to construct the proxy from types supplied // if and only if a name was supplied for the union - if (proxy == null && !string.IsNullOrWhiteSpace(fieldAttribute.UnionTypeName)) + // + // if it happens that two or more union proxies were declared + // then validation will pick up the issue as a union proxy is not a valid return type + if (proxy == null && !string.IsNullOrWhiteSpace(unionTypeName)) { - proxy = new GraphUnionProxy(fieldAttribute.UnionTypeName, fieldAttribute.UnionTypeName, fieldAttribute.Types); + proxy = new GraphUnionProxy( + unionTypeName, + unionTypeName, + potentialReturnTypes); } - this.UnionProxy = proxy; + return proxy; } /// @@ -461,16 +564,18 @@ private void BuildUnionProxyInstance() /// public virtual IGraphUnionProxy UnionProxy { get; protected set; } - /// - /// Gets the possible types that can be returned by this field. - /// - /// The possible types. - protected List PossibleTypes { get; private set; } - /// public MetaGraphTypes[] DeclaredTypeWrappers { get; private set; } /// public float? Complexity { get; set; } + + /// + /// Gets the possible concrete data types that can be returned by this field. + /// This list represents the core .NET types that will represent the various graph types. It should not include + /// decorators such as IEnumerable{t} or Nullable{T}. + /// + /// The potential types of data returnable by this instance. + protected List PossibleObjectTypes { get; private set; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphTypeExtensionFieldTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphTypeExtensionFieldTemplate.cs index 94da70514..136391a4c 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphTypeExtensionFieldTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphTypeExtensionFieldTemplate.cs @@ -10,9 +10,11 @@ namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates { using System; + using System.Collections.Generic; using System.Linq; using System.Reflection; using GraphQL.AspNet.Attributes; + using GraphQL.AspNet.Common; using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Execution; using GraphQL.AspNet.Execution.Exceptions; @@ -70,18 +72,22 @@ protected override void ParseTemplateDefinition() base.ParseTemplateDefinition(); + // rebuild the returned object type and the type expression of the field + // to account for the extra values required when dealing with an explictly + // declared batch extension var returnType = GraphValidation.EliminateWrappersFromCoreType(this.DeclaredReturnType); - if (returnType != typeof(IGraphActionResult)) + if (!Validation.IsCastable(returnType) && _typeAttrib.ExecutionMode == FieldResolutionMode.Batch) { // inspect the return type, if its a valid dictionary extract the return type from the value // and set the type modifiers and method type based on the value of each dictionary entry - if (_typeAttrib.ExecutionMode == FieldResolutionMode.Batch) - { - returnType = returnType.GetValueTypeOfDictionary(); - this.ObjectType = GraphValidation.EliminateWrappersFromCoreType(returnType); - this.TypeExpression = GraphTypeExpression.FromType(returnType, this.DeclaredTypeWrappers); - this.PossibleTypes.Insert(0, this.ObjectType); - } + returnType = returnType.GetValueTypeOfDictionary(); + var wrappers = GraphTypeExpression.FromType(returnType).Wrappers; + this.ObjectType = GraphValidation.EliminateWrappersFromCoreType(returnType); + this.TypeExpression = GraphTypeExpression + .FromType(returnType, this.DeclaredTypeWrappers ?? wrappers) + .CloneTo(Constants.Other.DEFAULT_TYPE_EXPRESSION_TYPE_NAME); + + this.PossibleObjectTypes.Insert(0, this.ObjectType); } } diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/RuntimeGraphDirectiveTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/RuntimeGraphDirectiveTemplate.cs index c829310ff..6ebb83104 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/RuntimeGraphDirectiveTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/RuntimeGraphDirectiveTemplate.cs @@ -43,6 +43,15 @@ public RuntimeGraphDirectiveTemplate(IGraphQLRuntimeDirectiveDefinition directiv } } + /// + protected override void ParseTemplateDefinition() + { + base.ParseTemplateDefinition(); + + if (!string.IsNullOrWhiteSpace(_directiveDefinition?.InternalName)) + this.InternalName = _directiveDefinition.InternalName; + } + /// protected override IEnumerable GatherPossibleDirectiveExecutionMethods() { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedDirectiveTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedDirectiveTemplateTests.cs index 256c9b275..ac31708d4 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedDirectiveTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedDirectiveTemplateTests.cs @@ -47,6 +47,22 @@ public void MapDirective_ByOptions_AddsDirectiveToOptions() Assert.AreEqual(DirectiveLocation.AllExecutionLocations | DirectiveLocation.AllTypeSystemLocations, locationAttib.Locations); } + [Test] + public void MapDirective_WhenNameApplied_NameIsAttchedToFieldDeclaration() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var builderMock = new Mock(); + builderMock.Setup(x => x.Options).Returns(options); + + var directive = builderMock.Object + .MapDirective("@myDirective") + .WithName("internalDirectiveName"); + + Assert.AreEqual("internalDirectiveName", directive.InternalName); + } + [Test] public void MapDirective_ByBuilder_AddsDirectiveToOptions() { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedTypeExtensionTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedTypeExtensionTemplateTests.cs index 3c490ceef..e380ab025 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedTypeExtensionTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedTypeExtensionTemplateTests.cs @@ -47,6 +47,21 @@ public void MapTypeExtension_ByOptions_AddsTypeExtensionToOptions() Assert.IsNotNull(typeExtensionAttrib); } + [Test] + public void MapTypeExtension_WithName_AddsInternalName() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var builderMock = new Mock(); + builderMock.Setup(x => x.Options).Returns(options); + + var typeExt = options.MapField("myField") + .WithName("internalFieldName"); + + Assert.AreEqual("internalFieldName", typeExt.InternalName); + } + [Test] public void MapTypeExtension_ByBuilder_AddsTypeExtensionToOptions() { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/ResolvedFieldTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/ResolvedFieldTemplateTests.cs index 1bb2ff69d..72b070dd1 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/ResolvedFieldTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/ResolvedFieldTemplateTests.cs @@ -35,6 +35,19 @@ public void ResolvedField_WhenAllowAnonymousAdded_AddsAnonymousAttribute() Assert.IsNotNull(field.Attributes.FirstOrDefault(x => x is AllowAnonymousAttribute)); } + [Test] + public void ResolvedField_WhenNameApplied_NameIsAttchedToFieldDeclaration() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options + .MapQuery("/path1/path2", (string a) => 1) + .WithName("theName"); + + Assert.AreEqual("theName", field.InternalName); + } + [Test] public void ResolvedField_WhenRequireAuthAdded_AddsAuthAttribute() { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionMethodTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionMethodTemplateTests.cs index 5d4fbba09..b4f5f0e5f 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionMethodTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionMethodTemplateTests.cs @@ -38,7 +38,6 @@ private ControllerActionGraphFieldTemplate CreateActionTemplate var methodInfo = typeof(TControllerType).GetMethod(actionName); var action = new ControllerActionGraphFieldTemplate(mockController.Object, methodInfo); action.Parse(); - action.ValidateOrThrow(); return action; } @@ -68,6 +67,7 @@ public void ActionTemplate_Parse_BasicPropertySets() public void ActionTemplate_Parse_MethodMarkedAsOperationIsAssignedARootPath() { var action = this.CreateActionTemplate(nameof(ContainerController.RootMethod)); + action.ValidateOrThrow(); Assert.AreEqual(SchemaItemCollections.Query, action.Route.RootCollection); Assert.AreEqual(0, action.Arguments.Count); @@ -79,6 +79,7 @@ public void ActionTemplate_Parse_MethodMarkedAsOperationIsAssignedARootPath() public void ActionTemplate_Parse_WithValidDeclaredUnion_ParsesCorrectly() { var action = this.CreateActionTemplate(nameof(UnionTestController.TwoTypeUnion)); + action.ValidateOrThrow(); Assert.AreEqual(SchemaItemCollections.Query, action.Route.RootCollection); Assert.IsNotNull(action.UnionProxy); @@ -95,6 +96,7 @@ public void ActionTemplate_Parse_WithValidDeclaredUnion_ParsesCorrectly() public void ActionTemplate_Parse_WithValidDeclaredUnionViaProxy_UsesProxy() { var action = this.CreateActionTemplate(nameof(UnionTestController.UnionViaProxy)); + action.ValidateOrThrow(); Assert.AreEqual(SchemaItemCollections.Query, action.Route.RootCollection); Assert.IsNotNull(action.UnionProxy); @@ -109,7 +111,8 @@ public void ActionTemplate_Parse_ThrowsException(string methodName) { Assert.Throws(() => { - this.CreateActionTemplate(methodName); + var template = this.CreateActionTemplate(methodName); + template.ValidateOrThrow(); }); } @@ -119,15 +122,17 @@ public void ActionTemplate_NegativeComplexityValue_ThrowsException() Assert.Throws(() => { var action = this.CreateActionTemplate(nameof(ComplexityValueCheckController.ReturnsAnInt)); + action.ValidateOrThrow(); }); } [Test] - public void ActionTemplate_ReturnTypeOfActionResult_ThrowsException() + public void ActionTemplate_ReturnTypeOfActionResult_WithoutDeclaredReturnType_ThrowsException() { Assert.Throws(() => { - this.CreateActionTemplate(nameof(ActionResultReturnTypeController.ActionResultMethod)); + var action = this.CreateActionTemplate(nameof(ActionResultReturnTypeController.ActionResultMethod)); + action.ValidateOrThrow(); }); } @@ -135,14 +140,16 @@ public void ActionTemplate_ReturnTypeOfActionResult_ThrowsException() public void ActionTemplate_ReturnTypeOfActionResult_WithDeclaredDataType_RendersCorrectly() { var action = this.CreateActionTemplate(nameof(ActionResultReturnTypeController.ActionResultMethodWithDeclaredReturnType)); + action.ValidateOrThrow(); Assert.AreEqual(typeof(TwoPropertyObject), action.ObjectType); } [Test] - public void ActionTemplate_ReturnTypeOfActionResult_WithDeclaredListDataType_RendersOptionsCorrectly() + public void ActionTemplate_ReturnTypeOfActionResult_WithDeclaredListDataType_RendersObjectTypeCorrectly() { var action = this.CreateActionTemplate(nameof(ActionResultReturnTypeController.ActionResultMethodWithListReturnType)); + action.ValidateOrThrow(); Assert.AreEqual(typeof(TwoPropertyObject), action.ObjectType); Assert.IsTrue(action.TypeExpression.IsListOfItems); @@ -167,17 +174,16 @@ public void ActionTemplate_ReturnTypeOfActionResult_WithDeclaredDataType_ThatHas action.ValidateOrThrow(); Assert.AreEqual(typeof(CustomNamedItem), action.ObjectType); - Assert.AreEqual("AnAwesomeName", action.TypeExpression.TypeName); + Assert.AreEqual("Type", action.TypeExpression.TypeName); } [Test] - public void ActionTemplate_ReturnTypeOfActionResult_WithDeclaredDataType_DiffersFromMethodReturn_ThrowsException() + public void ActionTemplate_WithDeclaredDataType_ThatDiffersFromMethodReturn_ThrowsException() { - Assert.Throws(() => + var ex = Assert.Throws(() => { var action = this.CreateActionTemplate( - nameof(ActionResultReturnTypeController - .ActionResultMethodWithDeclaredReturnTypeAndMethodReturnType)); + nameof(ActionResultReturnTypeController.MethodWithDeclaredReturnTypeAndMethodReturnType)); action.ValidateOrThrow(); }); } @@ -186,6 +192,7 @@ public void ActionTemplate_ReturnTypeOfActionResult_WithDeclaredDataType_Differs public void ActionTemplate_ReturnTypeOfInterface_WithPossibleTypesAttribute_RetrieveDependentTypes_ReturnsAllTypes() { var action = this.CreateActionTemplate(nameof(InterfaceReturnTypeController.RetrieveData)); + action.ValidateOrThrow(); var types = action.RetrieveRequiredTypes(); Assert.IsNotNull(types); @@ -200,6 +207,7 @@ public void ActionTemplate_ReturnTypeOfInterface_WithPossibleTypesAttribute_Retr public void ActionTemplate_ReturnTypeOfInterface_WithoutPossibleTypesAttribute_DoesntFail_ReturnsOnlyInterface() { var action = this.CreateActionTemplate(nameof(InterfaceReturnTypeController.RetrieveDataNoAttributeDeclared)); + action.ValidateOrThrow(); var types = action.RetrieveRequiredTypes(); Assert.IsNotNull(types); @@ -214,6 +222,7 @@ public void ActionTemplate_ReturnTypeOfInterface_WithPossibleTypesAttribute_ButT Assert.Throws(() => { var action = this.CreateActionTemplate(nameof(InterfaceReturnTypeController.RetrieveDataInvalidPossibleType)); + action.ValidateOrThrow(); }); } @@ -223,6 +232,7 @@ public void ActionTemplate_ReturnTypeOfInterface_WithPossibleTypesAttribute_ButT Assert.Throws(() => { var action = this.CreateActionTemplate(nameof(InterfaceReturnTypeController.RetrieveDataPossibleTypeIsInterface)); + action.ValidateOrThrow(); }); } @@ -232,6 +242,7 @@ public void ActionTemplate_ReturnTypeOfInterface_WithPossibleTypesAttribute_ButT Assert.Throws(() => { var action = this.CreateActionTemplate(nameof(InterfaceReturnTypeController.RetrieveDataPossibleTypeIsScalar)); + action.ValidateOrThrow(); }); } @@ -241,6 +252,7 @@ public void ActionTemplate_ReturnTypeOfInterface_WithPossibleTypesAttribute_ButT Assert.Throws(() => { var action = this.CreateActionTemplate(nameof(InterfaceReturnTypeController.RetrieveDataPossibleTypeIsAStruct)); + action.ValidateOrThrow(); }); } @@ -248,6 +260,7 @@ public void ActionTemplate_ReturnTypeOfInterface_WithPossibleTypesAttribute_ButT public void ActionTemplate_ArrayOnInputParameter_RendersFine() { var action = this.CreateActionTemplate(nameof(ArrayInputMethodController.AddData)); + action.ValidateOrThrow(); var types = action.RetrieveRequiredTypes(); Assert.IsNotNull(types); @@ -263,6 +276,7 @@ public void ActionTemplate_ArrayOnInputParameter_RendersFine() public void Parse_AssignedDirective_IsTemplatized() { var action = this.CreateActionTemplate(nameof(ActionMethodWithDirectiveController.Execute)); + action.ValidateOrThrow(); Assert.AreEqual(1, action.AppliedDirectives.Count()); diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/ActionResultReturnTypeController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/ActionResultReturnTypeController.cs index 3edff47f7..5d41c28ea 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/ActionResultReturnTypeController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/ActionResultReturnTypeController.cs @@ -43,7 +43,7 @@ public IGraphActionResult ActionResultMethodWithListReturnTypeAndOptions() } [Query("path4", typeof(TwoPropertyObject))] - public TwoPropertyObjectV2 ActionResultMethodWithDeclaredReturnTypeAndMethodReturnType() + public TwoPropertyObjectV2 MethodWithDeclaredReturnTypeAndMethodReturnType() { return null; } diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/InterfaceReturnTypeController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/InterfaceReturnTypeController.cs index 9a0800199..2bc7d1280 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/InterfaceReturnTypeController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/InterfaceReturnTypeController.cs @@ -20,7 +20,7 @@ public struct MyStruct public int Data1 { get; } } - [Query] + [Query("field")] [PossibleTypes(typeof(TestItemA), typeof(TestItemB))] public ITestItem RetrieveData() { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/RuntimeControllerActionTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/RuntimeControllerActionTemplateTests.cs new file mode 100644 index 000000000..73f98e354 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/RuntimeControllerActionTemplateTests.cs @@ -0,0 +1,66 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates +{ + using System; + using System.Linq; + using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + using GraphQL.AspNet.Tests.Common.Interfaces; + using Microsoft.Extensions.DependencyInjection; + using NUnit.Framework; + using NUnit.Framework.Constraints; + + [TestFixture] + public class RuntimeControllerActionTemplateTests + { + [Test] + public void MapQuery_PossibleTypesCheck() + { + var options = new SchemaOptions(new ServiceCollection()); + var field = options.MapQuery("fieldName", (int a) => null as ISinglePropertyObject) + .AddPossibleTypes(typeof(TwoPropertyObjectV3), typeof(TwoPropertyObject)); + + var template = new RuntimeGraphControllerTemplate(field); + template.Parse(); + template.ValidateOrThrow(); + + Assert.AreEqual(1, template.Actions.Count()); + + var fieldTemplate = template.Actions.First(); + Assert.AreEqual("fieldName", fieldTemplate.Name); + Assert.AreEqual(0, fieldTemplate.AppliedDirectives.Count()); + + var requiredTypes = fieldTemplate.RetrieveRequiredTypes().ToList(); + Assert.AreEqual(4, requiredTypes.Count); + Assert.IsNotNull(requiredTypes.SingleOrDefault(x => x.Type == typeof(int))); + Assert.IsNotNull(requiredTypes.SingleOrDefault(x => x.Type == typeof(ISinglePropertyObject))); + Assert.IsNotNull(requiredTypes.SingleOrDefault(x => x.Type == typeof(TwoPropertyObjectV3))); + Assert.IsNotNull(requiredTypes.SingleOrDefault(x => x.Type == typeof(TwoPropertyObject))); + } + + [Test] + public void MapQuery_InternalNameCheck() + { + var options = new SchemaOptions(new ServiceCollection()); + var field = options.MapQuery("fieldName", (int a) => 0) + .WithName("internalFieldName"); + + var template = new RuntimeGraphControllerTemplate(field); + template.Parse(); + template.ValidateOrThrow(); + + Assert.AreEqual(1, template.Actions.Count()); + Assert.AreEqual("internalFieldName", template.Actions.First().InternalName); + } + } +} \ No newline at end of file From 0022b12d8cc4e7cfcd7e478d3f0e5fcc2402de06 Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Sun, 23 Jul 2023 15:07:49 -0700 Subject: [PATCH 47/63] WIP, internal name tests and type maker fixes --- ...ItemDefinitionExtensions_ResolvedFields.cs | 9 ++-- .../Generation/TypeMakers/DirectiveMaker.cs | 1 + .../TypeMakers/EnumGraphTypeMaker.cs | 3 +- .../TypeMakers/InputObjectGraphTypeMaker.cs | 1 + .../TypeMakers/InterfaceGraphTypeMaker.cs | 1 + .../TypeTemplates/GraphFieldTemplateBase.cs | 4 +- .../TypeTemplates/UnionGraphTypeTemplate.cs | 4 +- .../Schemas/TypeSystem/Directive.cs | 6 +-- .../Schemas/TypeSystem/EnumGraphType.cs | 17 +++++-- .../Schemas/TypeSystem/EnumValue.cs | 6 +-- .../Schemas/TypeSystem/GraphUnionProxy.cs | 2 +- .../TypeSystem/InputObjectGraphType.cs | 4 +- .../Schemas/TypeSystem/InterfaceGraphType.cs | 4 +- .../Introspection_DirectiveLocationType.cs | 5 +- .../Introspection_TypeKindType.cs | 5 +- .../Schemas/GeneralSchemaTests.cs | 46 +++++++++++++++++ .../TypeMakers/DirectiveTypeMakerTests.cs | 18 +++++++ .../TypeMakers/EnumGraphTypeMakerTests.cs | 27 ++++++++++ .../TypeMakers/FieldMaker_InputFieldTests.cs | 16 ++++++ .../FieldMaker_StandardFieldTests.cs | 49 +++++++++++++++++++ .../InputObjectGraphTypeMakerTests.cs | 10 ++++ .../TypeMakers/InterfaceTypeMakerTests.cs | 15 ++++++ .../TypeMakers/ObjectGraphTypeMakerTests.cs | 13 +++++ .../TestData/ControllerWithInternalNames.cs | 30 ++++++++++++ .../TestData/DirectiveWithInternalName.cs | 26 ++++++++++ .../TestData/EnumWithInternalNames.cs | 20 ++++++++ .../TestData/IInterfaceWithInternalName.cs | 19 +++++++ .../InputTestObjectWithInternalName.cs | 20 ++++++++ .../TestData/ObjectWithInternalName.cs | 26 ++++++++++ .../TestData/UnionWithInternalName.cs | 22 +++++++++ .../TestData/UnionWithNoInternalName.cs | 22 +++++++++ .../TypeMakers/UnionTypeMakerTests.cs | 22 +++++++++ .../ActionMethodTemplateTests.cs | 9 ++++ .../ActionMethodWithInternalNameController.cs | 23 +++++++++ .../TypeTemplates/ArgumentTemplateTests.cs | 7 +++ .../TypeTemplates/DirectiveTemplateTests.cs | 10 ++++ .../DirectiveWithInternalName.cs | 26 ++++++++++ .../EnumGraphTypeTemplateTests.cs | 21 ++++++++ .../EnumTestData/EnumWithInternalName.cs | 20 ++++++++ .../EnumWithInternalNameOnOption.cs | 19 +++++++ .../ExtensionMethodController.cs | 6 +++ .../TypeTemplates/InputObjectTemplateTests.cs | 10 ++++ .../InterfaceGraphTypeTemplateTests.cs | 10 ++++ .../IInterfaceWIthInternalName.cs | 23 +++++++++ .../MethodGraphFieldTemplateTests.cs | 13 +++++ .../MethodTestData/MethodClass.cs | 6 +++ .../ObjectGraphTypeTemplateTests.cs | 10 ++++ .../InputObjectWithInternalName.cs | 20 ++++++++ .../ObjectTypeTests/ObjectWithInternalName.cs | 19 +++++++ .../ParameterTestData/ParameterTestClass.cs | 1 + .../PropertyGraphFieldTemplateTests.cs | 21 ++++++++ .../PropertyWithInternalName.cs | 19 +++++++ .../TypeExtensionFieldTemplateTests.cs | 9 ++++ .../UnionGraphTypeTemplateTests.cs | 20 +++++--- .../UnionTestData/UnionWithInternalName.cs | 26 ++++++++++ .../UnionTestData/UnionWithNoInternalName.cs | 26 ++++++++++ .../graphql-aspnet-tests.csproj | 4 ++ 57 files changed, 819 insertions(+), 32 deletions(-) create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/GeneralSchemaTests.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ControllerWithInternalNames.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/DirectiveWithInternalName.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/EnumWithInternalNames.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/IInterfaceWithInternalName.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/InputTestObjectWithInternalName.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ObjectWithInternalName.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/UnionWithInternalName.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/UnionWithNoInternalName.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/ActionMethodWithInternalNameController.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTestData/DirectiveWithInternalName.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumWithInternalName.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumWithInternalNameOnOption.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceTestData/IInterfaceWIthInternalName.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/InputObjectWithInternalName.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ObjectWithInternalName.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyTestData/PropertyWithInternalName.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/UnionTestData/UnionWithInternalName.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/UnionTestData/UnionWithNoInternalName.cs diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_ResolvedFields.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_ResolvedFields.cs index 533c118ae..2df6cfe02 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_ResolvedFields.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_ResolvedFields.cs @@ -102,7 +102,8 @@ public static IGraphQLRuntimeResolvedFieldDefinition AddResolver(th /// on a controller's action method. /// /// - /// This method can be called multiple times. Any new types will be appended to the field. + /// This method can be called multiple times. Any new types will be appended to the field. All types added + /// must be coercable to the declared return type of the assigned resolver for this field. /// /// The field being built. /// The first possible type that might be returned by this @@ -118,9 +119,9 @@ public static IGraphQLRuntimeResolvedFieldDefinition AddPossibleTypes(this IGrap } /// - /// Assigns a custom value to the internal name of this field. This value will be used in error - /// messages and log entries instead of anonymous method name. This can significantly increase readability - /// while trying to debug an issue. + /// Assigns a custom internal name to this field. This value will be used in error + /// messages and log entries instead of an anonymous method name. This can significantly increase readability + /// while trying to debug an issue. This value has no bearing on the runtime use of this field. It is cosmetic only. /// /// /// This value does NOT affect the field name as it would appear in a schema. It only effects the internal diff --git a/src/graphql-aspnet/Schemas/Generation/TypeMakers/DirectiveMaker.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/DirectiveMaker.cs index 0f2a4bfea..9fb4b9068 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeMakers/DirectiveMaker.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/DirectiveMaker.cs @@ -55,6 +55,7 @@ public virtual GraphTypeCreationResult CreateGraphType(IGraphTypeTemplate typeTe var directive = new Directive( formatter.FormatFieldName(template.Name), + template.InternalName, template.Locations, template.ObjectType, template.Route, diff --git a/src/graphql-aspnet/Schemas/Generation/TypeMakers/EnumGraphTypeMaker.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/EnumGraphTypeMaker.cs index 5af3071cb..42445c2a6 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeMakers/EnumGraphTypeMaker.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/EnumGraphTypeMaker.cs @@ -50,6 +50,7 @@ public virtual GraphTypeCreationResult CreateGraphType(IGraphTypeTemplate typeTe var graphType = new EnumGraphType( _config.DeclarationOptions.GraphNamingFormatter.FormatGraphTypeName(template.Name), + template.InternalName, template.ObjectType, template.Route, enumDirectives) @@ -77,11 +78,11 @@ public virtual GraphTypeCreationResult CreateGraphType(IGraphTypeTemplate typeTe var valueOption = new EnumValue( graphType, _config.DeclarationOptions.GraphNamingFormatter.FormatEnumValueName(value.Name), + value.InternalName, value.Description, value.Route, value.Value, value.DeclaredLabel, - value.InternalName, valueDirectives); graphType.AddOption(valueOption); diff --git a/src/graphql-aspnet/Schemas/Generation/TypeMakers/InputObjectGraphTypeMaker.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/InputObjectGraphTypeMaker.cs index cf58e42cc..801951a6f 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeMakers/InputObjectGraphTypeMaker.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/InputObjectGraphTypeMaker.cs @@ -54,6 +54,7 @@ public virtual GraphTypeCreationResult CreateGraphType(IGraphTypeTemplate typeTe var inputObjectType = new InputObjectGraphType( formatter.FormatGraphTypeName(template.Name), + template.InternalName, template.ObjectType, template.Route, directives) diff --git a/src/graphql-aspnet/Schemas/Generation/TypeMakers/InterfaceGraphTypeMaker.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/InterfaceGraphTypeMaker.cs index a5cb9c5dc..6555b5cbf 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeMakers/InterfaceGraphTypeMaker.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/InterfaceGraphTypeMaker.cs @@ -53,6 +53,7 @@ public virtual GraphTypeCreationResult CreateGraphType(IGraphTypeTemplate typeTe var interfaceType = new InterfaceGraphType( formatter.FormatGraphTypeName(template.Name), + template.InternalName, template.ObjectType, template.Route, directives) diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphFieldTemplateBase.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphFieldTemplateBase.cs index e74115c3a..e8940f538 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphFieldTemplateBase.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphFieldTemplateBase.cs @@ -56,6 +56,8 @@ protected GraphFieldTemplateBase(IGraphTypeTemplate parent, ICustomAttributeProv /// protected override void ParseTemplateDefinition() { + base.ParseTemplateDefinition(); + Type StripTasks(Type type) { return GraphValidation.EliminateWrappersFromCoreType( @@ -65,8 +67,6 @@ Type StripTasks(Type type) eliminateNullableT: false); } - base.ParseTemplateDefinition(); - _fieldDeclaration = this.AttributeProvider.SingleAttributeOfTypeOrDefault(); // ------------------------------------ diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/UnionGraphTypeTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/UnionGraphTypeTemplate.cs index 79cd7a571..8d0d7b48a 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/UnionGraphTypeTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/UnionGraphTypeTemplate.cs @@ -51,8 +51,10 @@ protected override void ParseTemplateDefinition() if (_instance != null) { this.Route = new SchemaItemPath(SchemaItemPath.Join(SchemaItemCollections.Types, _instance.Name)); - this.InternalName = _instance.Name; + this.InternalName = _instance.InternalName; } + + this.InternalName = this.InternalName ?? _proxyType.FriendlyName(); } } catch diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Directive.cs b/src/graphql-aspnet/Schemas/TypeSystem/Directive.cs index 4278f19cb..46f82dfc9 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Directive.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Directive.cs @@ -12,9 +12,7 @@ namespace GraphQL.AspNet.Schemas.TypeSystem using System; using System.Collections.Generic; using System.Diagnostics; - using System.Linq; using GraphQL.AspNet.Common; - using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Interfaces.Execution; using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Schemas.Structural; @@ -31,6 +29,7 @@ public class Directive : IDirective /// Initializes a new instance of the class. /// /// The name of the directive as it appears in the schema. + /// The internal name of the directive as defined in the source code. /// The locations where this directive is valid. /// The concrete type of the directive. /// The route path that identifies this directive. @@ -41,6 +40,7 @@ public class Directive : IDirective /// that must be passed before this directive can be invoked. public Directive( string name, + string internalName, DirectiveLocation locations, Type directiveType, SchemaItemPath route, @@ -55,7 +55,7 @@ public Directive( this.Publish = true; this.Route = Validation.ThrowIfNullOrReturn(route, nameof(route)); this.ObjectType = Validation.ThrowIfNullOrReturn(directiveType, nameof(directiveType)); - this.InternalName = this.ObjectType.FriendlyName(); + this.InternalName = Validation.ThrowIfNullWhiteSpaceOrReturn(internalName, nameof(internalName)); this.AppliedDirectives = new AppliedDirectiveCollection(this); this.IsRepeatable = isRepeatable; diff --git a/src/graphql-aspnet/Schemas/TypeSystem/EnumGraphType.cs b/src/graphql-aspnet/Schemas/TypeSystem/EnumGraphType.cs index 6fd7315d3..5513a0bcb 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/EnumGraphType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/EnumGraphType.cs @@ -31,11 +31,17 @@ public class EnumGraphType : IEnumGraphType /// Initializes a new instance of the class. /// /// The name to assign to this enumeration in the graph. + /// The internal name of this graph type as its assigned in source code. /// Type of the enum. /// The route path that identifies this enum type. /// The directives to apply to this enum type. - public EnumGraphType(string name, Type enumType, SchemaItemPath route, IAppliedDirectiveCollection directives = null) - : this(name, enumType, route, new EnumLeafValueResolver(enumType), directives) + public EnumGraphType( + string name, + string internalName, + Type enumType, + SchemaItemPath route, + IAppliedDirectiveCollection directives = null) + : this(name, internalName, enumType, route, new EnumLeafValueResolver(enumType), directives) { } @@ -43,23 +49,26 @@ public EnumGraphType(string name, Type enumType, SchemaItemPath route, IAppliedD /// Initializes a new instance of the class. /// /// The name to assign to this enumeration in the graph. + /// The internal name of this graph type as its assigned in source code. /// Type of the enum. /// The route path that identifies this enum type. /// The resolver. /// The directives to apply to this enum type. public EnumGraphType( string name, + string internalName, Type enumType, SchemaItemPath route, ILeafValueResolver resolver, IAppliedDirectiveCollection directives = null) { - this.Name = Validation.ThrowIfNullEmptyOrReturn(name, nameof(name)); + this.Name = Validation.ThrowIfNullWhiteSpaceOrReturn(name, nameof(name)); + this.InternalName = Validation.ThrowIfNullWhiteSpaceOrReturn(internalName, nameof(internalName)); + this.ObjectType = Validation.ThrowIfNullOrReturn(enumType, nameof(enumType)); this.Route = Validation.ThrowIfNullOrReturn(route, nameof(route)); this.SourceResolver = Validation.ThrowIfNullOrReturn(resolver, nameof(resolver)); - this.InternalName = this.ObjectType.FriendlyName(); this.Publish = true; this.AppliedDirectives = directives?.Clone(this) ?? new AppliedDirectiveCollection(this); diff --git a/src/graphql-aspnet/Schemas/TypeSystem/EnumValue.cs b/src/graphql-aspnet/Schemas/TypeSystem/EnumValue.cs index c71225730..119295311 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/EnumValue.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/EnumValue.cs @@ -26,22 +26,22 @@ public class EnumValue : IEnumValue /// /// The parent enum graph type that owns this value. /// The value. + /// The internal name assigned to this enum value. Typically the same as + /// but can be customized by the developer for reporting purposes. /// The description. /// The route path that uniquely identifies this enum option. /// The value of the enum as its declared in .NET. /// A string representation of label declared on the enum value in .NET. - /// The internal name assigned to this enum value. Typically the same as - /// but can be customized by the developer for reporting purposes. /// The set of directives to execute /// against this option when it is added to the schema. public EnumValue( IEnumGraphType parent, string name, + string internalName, string description, SchemaItemPath route, object internalValue, string declaredLabel, - string internalName, IAppliedDirectiveCollection directives = null) { this.Parent = Validation.ThrowIfNullOrReturn(parent, nameof(parent)); diff --git a/src/graphql-aspnet/Schemas/TypeSystem/GraphUnionProxy.cs b/src/graphql-aspnet/Schemas/TypeSystem/GraphUnionProxy.cs index b88365628..c9edd43ff 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/GraphUnionProxy.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/GraphUnionProxy.cs @@ -100,7 +100,7 @@ public virtual Type MapType(Type runtimeObjectType) public virtual string Name { get; set; } /// - public string InternalName { get; } + public string InternalName { get; set; } /// public virtual string Description { get; set; } diff --git a/src/graphql-aspnet/Schemas/TypeSystem/InputObjectGraphType.cs b/src/graphql-aspnet/Schemas/TypeSystem/InputObjectGraphType.cs index 8500732e7..ce20c9635 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/InputObjectGraphType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/InputObjectGraphType.cs @@ -29,19 +29,21 @@ public class InputObjectGraphType : IInputObjectGraphType /// Initializes a new instance of the class. /// /// The name of the graph type. + /// The internal name assigned to this graph type in source code. /// Type of the object. /// The route path that identifies this object in the schema. /// The directives to apply to this input /// object when its added to a schema. public InputObjectGraphType( string name, + string internalName, Type objectType, SchemaItemPath route, IAppliedDirectiveCollection directives = null) { this.Name = Validation.ThrowIfNullWhiteSpaceOrReturn(name, nameof(name)); this.ObjectType = Validation.ThrowIfNullOrReturn(objectType, nameof(objectType)); - this.InternalName = this.ObjectType.FriendlyName(); + this.InternalName = Validation.ThrowIfNullWhiteSpaceOrReturn(internalName, nameof(internalName)); this.Route = Validation.ThrowIfNullOrReturn(route, nameof(route)); this.AppliedDirectives = directives?.Clone(this) ?? new AppliedDirectiveCollection(this); this.Publish = true; diff --git a/src/graphql-aspnet/Schemas/TypeSystem/InterfaceGraphType.cs b/src/graphql-aspnet/Schemas/TypeSystem/InterfaceGraphType.cs index 7fd4bb213..b95815fe9 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/InterfaceGraphType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/InterfaceGraphType.cs @@ -30,12 +30,14 @@ public class InterfaceGraphType : IInterfaceGraphType /// Initializes a new instance of the class. /// /// The name of the interface as it will appear in the schema. + /// The internal name of the interface as defined in source code. /// The concrete type representing this interface. /// The route path that identifies this interface. /// The directives to apply to this type /// when its added to a schema. public InterfaceGraphType( string name, + string internalName, Type concreteType, SchemaItemPath route, IAppliedDirectiveCollection directives = null) @@ -43,7 +45,7 @@ public InterfaceGraphType( this.Name = Validation.ThrowIfNullOrReturn(name, nameof(name)); this.Route = Validation.ThrowIfNullOrReturn(route, nameof(route)); this.ObjectType = Validation.ThrowIfNullOrReturn(concreteType, nameof(concreteType)); - this.InternalName = this.ObjectType.FriendlyName(); + this.InternalName = Validation.ThrowIfNullWhiteSpaceOrReturn(internalName, nameof(internalName)); this.InterfaceNames = new HashSet(); _fieldSet = new GraphFieldCollection(this); diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_DirectiveLocationType.cs b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_DirectiveLocationType.cs index f9371da01..8ff11eb91 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_DirectiveLocationType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_DirectiveLocationType.cs @@ -30,6 +30,7 @@ internal class Introspection_DirectiveLocationType : EnumGraphType, IInternalSch public Introspection_DirectiveLocationType() : base( Constants.ReservedNames.DIRECTIVE_LOCATION_ENUM, + nameof(Introspection_DirectiveLocationType), typeof(DirectiveLocation), new GraphIntrospectionFieldPath(Constants.ReservedNames.DIRECTIVE_LOCATION_ENUM)) { @@ -44,11 +45,11 @@ public Introspection_DirectiveLocationType() var option = new EnumValue( this, name, + name, description, this.Route.CreateChild(name), value, - fi.Name, - name); + fi.Name); this.AddOption(option); } diff --git a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_TypeKindType.cs b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_TypeKindType.cs index 2f0eb5f90..6456a2605 100644 --- a/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_TypeKindType.cs +++ b/src/graphql-aspnet/Schemas/TypeSystem/Introspection/Introspection_TypeKindType.cs @@ -30,6 +30,7 @@ internal class Introspection_TypeKindType : EnumGraphType, IInternalSchemaItem public Introspection_TypeKindType() : base( Constants.ReservedNames.TYPE_KIND_ENUM, + nameof(Introspection_TypeKindType), typeof(TypeKind), new GraphIntrospectionFieldPath(Constants.ReservedNames.TYPE_KIND_ENUM)) { @@ -44,11 +45,11 @@ public Introspection_TypeKindType() var option = new EnumValue( this, name, + name, description, this.Route.CreateChild(name), value, - fi.Name, - name); + fi.Name); this.AddOption(option); } diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/GeneralSchemaTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/GeneralSchemaTests.cs new file mode 100644 index 000000000..0e4c524ba --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/GeneralSchemaTests.cs @@ -0,0 +1,46 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas +{ + using System.Globalization; + using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + using GraphQL.AspNet.Tests.Framework; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData; + using NUnit.Framework; + + [TestFixture] + public class GeneralSchemaTests + { + [Test] + public void InternalName_OnControllerAction_IsRendered() + { + var schema = new TestServerBuilder() + .AddController() + .Build().Schema; + + var field = schema.Operations[GraphOperationType.Query].Fields.FindField("actionField"); + Assert.AreEqual("ActionWithInternalName", field.InternalName); + } + + [Test] + public void InternalName_OnTypeExension_IsRendered() + { + var schema = new TestServerBuilder() + .AddController() + .Build().Schema; + + var twoProp = schema.KnownTypes.FindGraphType(typeof(TwoPropertyObject)) as IObjectGraphType; + var field = twoProp.Fields.FindField("field1"); + Assert.AreEqual("TypeExtensionInternalName", field.InternalName); + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/DirectiveTypeMakerTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/DirectiveTypeMakerTests.cs index 3952b9989..e9252dc7f 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/DirectiveTypeMakerTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/DirectiveTypeMakerTests.cs @@ -183,5 +183,23 @@ public void ArgInclusionCheck(SchemaArgumentBindingRules bindingRule, Type direc else Assert.AreEqual(0, directive.Arguments.Count); } + + [Test] + public void Directive_InternalName_PropertyCheck() + { + var builder = new TestServerBuilder(); + var server = builder.Build(); + + var factory = server.CreateMakerFactory(); + + var template = new GraphDirectiveTemplate(typeof(DirectiveWithInternalName)); + template.Parse(); + template.ValidateOrThrow(); + + var typeMaker = new DirectiveMaker(server.Schema, new GraphArgumentMaker(server.Schema)); + var directive = typeMaker.CreateGraphType(template).GraphType as IDirective; + + Assert.AreEqual("DirectiveInternalName_33", directive.InternalName); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/EnumGraphTypeMakerTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/EnumGraphTypeMakerTests.cs index 83027e83e..8fe357084 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/EnumGraphTypeMakerTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/EnumGraphTypeMakerTests.cs @@ -189,5 +189,32 @@ public void EnumValueIsKeyword_AndFormattingMatchesKeyword_ThrowsException(Type Assert.Fail($"Expected {nameof(GraphTypeDeclarationException)} exception"); } + + [Test] + public void EnumType_InternalNameCheck() + { + var schema = new GraphSchema(); + + var maker = new EnumGraphTypeMaker(schema.Configuration); + var template = GraphQLTemplateHelper.CreateGraphTypeTemplate(typeof(EnumWithInternalNames), TypeKind.ENUM) as IGraphTypeTemplate; + + var graphType = maker.CreateGraphType(template).GraphType as IEnumGraphType; + + Assert.AreEqual("EnumInternalName", graphType.InternalName); + } + + [Test] + public void EnumValue_InternalNameCheck() + { + var schema = new GraphSchema(); + + var maker = new EnumGraphTypeMaker(schema.Configuration); + var template = GraphQLTemplateHelper.CreateGraphTypeTemplate(typeof(EnumWithInternalNames), TypeKind.ENUM) as IGraphTypeTemplate; + + var graphType = maker.CreateGraphType(template).GraphType as IEnumGraphType; + var value = graphType.Values.Single().Value; + + Assert.AreEqual("Value1InternalName", value.InternalName); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/FieldMaker_InputFieldTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/FieldMaker_InputFieldTests.cs index b036ef0c8..5f46e2f5f 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/FieldMaker_InputFieldTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/FieldMaker_InputFieldTests.cs @@ -223,5 +223,21 @@ public void Parse_NotRequiredNullableGraphIdPropertyCheck() Assert.AreEqual(0, graphField.AppliedDirectives.Count); } + + [Test] + public void Parse_InternalName_PropertyCheck() + { + var server = new TestServerBuilder().Build(); + var template = GraphQLTemplateHelper.CreateInputObjectTemplate(); + + var fieldTemplate = template + .FieldTemplates + .Values + .Single(x => x.Name == nameof(InputTestObjectWithInternalName.Prop1)); + + var graphField = new GraphFieldMaker(server.Schema, new GraphArgumentMaker(server.Schema)).CreateField(fieldTemplate).Field; + + Assert.AreEqual("Prop1InternalName", graphField.InternalName); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/FieldMaker_StandardFieldTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/FieldMaker_StandardFieldTests.cs index f720be41a..37c1cb0fc 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/FieldMaker_StandardFieldTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/FieldMaker_StandardFieldTests.cs @@ -22,6 +22,7 @@ namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers using GraphQL.AspNet.Tests.CommonHelpers; using GraphQL.AspNet.Tests.Framework; using GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData; + using Microsoft.AspNetCore.Hosting.Server; using Moq; using NUnit.Framework; @@ -330,5 +331,53 @@ public void Arguments_ArgumentBindingRuleTests(SchemaArgumentBindingRules bindin else Assert.AreEqual(0, field.Arguments.Count); } + + [Test] + public void InternalName_OnPropField_IsRendered() + { + var server = new TestServerBuilder().Build(); + + var obj = new Mock(); + obj.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/Item0")); + obj.Setup(x => x.InternalName).Returns("LongItem0"); + obj.Setup(x => x.InternalName).Returns("Item0"); + obj.Setup(x => x.ObjectType).Returns(typeof(ObjectWithInternalName)); + + var parent = obj.Object; + var methodInfo = typeof(ObjectWithInternalName).GetProperty("Prop1"); + var template = new PropertyGraphFieldTemplate(parent, methodInfo, TypeKind.OBJECT); + template.Parse(); + template.ValidateOrThrow(); + + var maker = new GraphFieldMaker(server.Schema, new GraphArgumentMaker(server.Schema)); + var field = maker.CreateField(template).Field; + + Assert.AreEqual("PropInternalName", field.InternalName); + Assert.AreEqual("[type]/Item0/Prop1", field.Route.Path); + } + + [Test] + public void InternalName_OnMethodField_IsRendered() + { + var server = new TestServerBuilder().Build(); + + var obj = new Mock(); + obj.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/Item0")); + obj.Setup(x => x.InternalName).Returns("LongItem0"); + obj.Setup(x => x.InternalName).Returns("Item0"); + obj.Setup(x => x.ObjectType).Returns(typeof(ObjectWithInternalName)); + + var parent = obj.Object; + var methodInfo = typeof(ObjectWithInternalName).GetMethod("Method1"); + var template = new MethodGraphFieldTemplate(parent, methodInfo, TypeKind.OBJECT); + template.Parse(); + template.ValidateOrThrow(); + + var maker = new GraphFieldMaker(server.Schema, new GraphArgumentMaker(server.Schema)); + var field = maker.CreateField(template).Field; + + Assert.AreEqual("MethodInternalName", field.InternalName); + Assert.AreEqual("[type]/Item0/Method1", field.Route.Path); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/InputObjectGraphTypeMakerTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/InputObjectGraphTypeMakerTests.cs index 1872a2d7c..7e96afdba 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/InputObjectGraphTypeMakerTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/InputObjectGraphTypeMakerTests.cs @@ -209,5 +209,15 @@ public void InputObject_CreateGraphType_DirectivesAreApplied() Assert.AreEqual(typeof(DirectiveWithArgs), appliedDirective.DirectiveType); CollectionAssert.AreEqual(new object[] { 44, "input arg" }, appliedDirective.ArgumentValues); } + + [Test] + public void InputObject_WithInternalName_HasInternalNameSet() + { + // config says properties DO require declaration, override on type says it does not + var result = this.MakeGraphType(typeof(InputTestObjectWithInternalName), TypeKind.INPUT_OBJECT); + var inputType = result.GraphType as IInputObjectGraphType; + + Assert.AreEqual("InputObjectInternalName", inputType.InternalName); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/InterfaceTypeMakerTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/InterfaceTypeMakerTests.cs index 49b1cb7c1..0709c2b6d 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/InterfaceTypeMakerTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/InterfaceTypeMakerTests.cs @@ -135,5 +135,20 @@ public void CreateGraphType_WhenMethodOnBaseInterfaceIsExplicitlyDeclared_IsNotI Assert.IsTrue(objectType.Fields.Any(x => string.Equals(x.Name, nameof(InterfaceThatInheritsDeclaredMethodField.PropFieldOnInterface), System.StringComparison.OrdinalIgnoreCase))); Assert.IsTrue(objectType.Fields.Any(x => string.Equals(x.Name, Constants.ReservedNames.TYPENAME_FIELD))); } + + [Test] + public void InternalName_OnInterfaceGraphType_IsRendered() + { + var result = this.MakeGraphType( + typeof(IInterfaceWithInternalName), + TypeKind.INTERFACE, + TemplateDeclarationRequirements.None); + + var objectType = result.GraphType as IInterfaceGraphType; + + // inherited and declared method field should not be counted + Assert.IsNotNull(objectType); + Assert.AreEqual("Interface_Internal_Name", objectType.InternalName); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/ObjectGraphTypeMakerTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/ObjectGraphTypeMakerTests.cs index 2360395fd..107ec5f09 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/ObjectGraphTypeMakerTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/ObjectGraphTypeMakerTests.cs @@ -285,5 +285,18 @@ public void CreateGraphType_AsObject_WhenMethodOnBaseObjectIsExplicitlyDeclared_ Assert.IsTrue(objectType.Fields.Any(x => string.Equals(x.Name, nameof(ObjectWithUndeclaredMethodField.FieldOnBaseObject), System.StringComparison.OrdinalIgnoreCase))); Assert.IsTrue(objectType.Fields.Any(x => string.Equals(x.Name, Constants.ReservedNames.TYPENAME_FIELD))); } + + [Test] + public void InternalName_OnObjectGraphType_IsRendered() + { + var result = this.MakeGraphType( + typeof(ObjectWithInternalName), + TypeKind.OBJECT, + TemplateDeclarationRequirements.None); + + var objectType = result.GraphType as IObjectGraphType; + + Assert.AreEqual("Object_Internal_Name", objectType.InternalName); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ControllerWithInternalNames.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ControllerWithInternalNames.cs new file mode 100644 index 000000000..a6de7fadc --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ControllerWithInternalNames.cs @@ -0,0 +1,30 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData +{ + using GraphQL.AspNet.Attributes; + using GraphQL.AspNet.Controllers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + + public class ControllerWithInternalNames : GraphController + { + [QueryRoot(InternalName = "ActionWithInternalName")] + public TwoPropertyObject ActionField() + { + return null; + } + + [TypeExtension(typeof(TwoPropertyObject), "field1", InternalName = "TypeExtensionInternalName")] + public int TypeExpressionField() + { + return 0; + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/DirectiveWithInternalName.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/DirectiveWithInternalName.cs new file mode 100644 index 000000000..612c50806 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/DirectiveWithInternalName.cs @@ -0,0 +1,26 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData +{ + using GraphQL.AspNet.Attributes; + using GraphQL.AspNet.Directives; + using GraphQL.AspNet.Interfaces.Controllers; + using GraphQL.AspNet.Schemas.TypeSystem; + + [GraphType(InternalName = "DirectiveInternalName_33")] + public class DirectiveWithInternalName : GraphDirective + { + [DirectiveLocations(DirectiveLocation.AllTypeSystemLocations)] + public IGraphActionResult Execute() + { + return null; + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/EnumWithInternalNames.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/EnumWithInternalNames.cs new file mode 100644 index 000000000..42822e986 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/EnumWithInternalNames.cs @@ -0,0 +1,20 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData +{ + using GraphQL.AspNet.Attributes; + + [GraphType(InternalName = "EnumInternalName")] + public enum EnumWithInternalNames + { + [GraphEnumValue(InternalName = "Value1InternalName")] + Value1, + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/IInterfaceWithInternalName.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/IInterfaceWithInternalName.cs new file mode 100644 index 000000000..4bf9c20fe --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/IInterfaceWithInternalName.cs @@ -0,0 +1,19 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData +{ + using GraphQL.AspNet.Attributes; + + [GraphType(InternalName = "Interface_Internal_Name")] + public interface IInterfaceWithInternalName + { + int Prop1 { get; set; } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/InputTestObjectWithInternalName.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/InputTestObjectWithInternalName.cs new file mode 100644 index 000000000..46fcd7190 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/InputTestObjectWithInternalName.cs @@ -0,0 +1,20 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData +{ + using GraphQL.AspNet.Attributes; + + [GraphType(InternalName = "InputObjectInternalName")] + public class InputTestObjectWithInternalName + { + [GraphField(InternalName = "Prop1InternalName")] + public int Prop1 { get; set; } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ObjectWithInternalName.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ObjectWithInternalName.cs new file mode 100644 index 000000000..8362f4181 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/ObjectWithInternalName.cs @@ -0,0 +1,26 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData +{ + using GraphQL.AspNet.Attributes; + + [GraphType(InternalName = "Object_Internal_Name")] + public class ObjectWithInternalName + { + [GraphField(InternalName = "PropInternalName")] + public int Prop1 { get; set; } + + [GraphField(InternalName = "MethodInternalName")] + public int Method1() + { + return 0; + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/UnionWithInternalName.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/UnionWithInternalName.cs new file mode 100644 index 000000000..a2318a5cf --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/UnionWithInternalName.cs @@ -0,0 +1,22 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData +{ + using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + + public class UnionWithInternalName : GraphUnionProxy + { + public UnionWithInternalName() + : base("TestUnion", "TestUnionInternalName", typeof(TwoPropertyObject)) + { + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/UnionWithNoInternalName.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/UnionWithNoInternalName.cs new file mode 100644 index 000000000..0bcc3a328 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/TestData/UnionWithNoInternalName.cs @@ -0,0 +1,22 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData +{ + using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + + public class UnionWithNoInternalName : GraphUnionProxy + { + public UnionWithNoInternalName() + : base("TestUnion", typeof(TwoPropertyObject)) + { + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/UnionTypeMakerTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/UnionTypeMakerTests.cs index de9e9cf6a..b44188dbd 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/UnionTypeMakerTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/UnionTypeMakerTests.cs @@ -90,5 +90,27 @@ public void NullProxy_YieldsNullGraphType() var unionType = maker.CreateUnionFromProxy(null); Assert.IsNull(unionType); } + + [Test] + public void Proxy_WithCustomInternalName_IsSetToSaidName() + { + var schema = new GraphSchema(); + schema.SetNoAlterationConfiguration(); + var maker = new UnionGraphTypeMaker(schema.Configuration); + + var unionType = maker.CreateUnionFromProxy(new UnionWithInternalName()).GraphType as IUnionGraphType; + Assert.AreEqual("TestUnionInternalName", unionType.InternalName); + } + + [Test] + public void Proxy_WithNoInternalName_IsSetToProxyName() + { + var schema = new GraphSchema(); + schema.SetNoAlterationConfiguration(); + var maker = new UnionGraphTypeMaker(schema.Configuration); + + var unionType = maker.CreateUnionFromProxy(new UnionWithNoInternalName()).GraphType as IUnionGraphType; + Assert.AreEqual("UnionWithNoInternalName", unionType.InternalName); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionMethodTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionMethodTemplateTests.cs index b4f5f0e5f..3d99a9d06 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionMethodTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionMethodTemplateTests.cs @@ -284,5 +284,14 @@ public void Parse_AssignedDirective_IsTemplatized() Assert.AreEqual(typeof(DirectiveWithArgs), appliedDirective.DirectiveType); Assert.AreEqual(new object[] { 202, "controller action arg" }, appliedDirective.Arguments); } + + [Test] + public void Parse_InternalName_IsAssignedCorrectly() + { + var action = this.CreateActionTemplate(nameof(ActionMethodWithInternalNameController.Execute)); + action.ValidateOrThrow(); + + Assert.AreEqual("Internal_Action_Name_37", action.InternalName); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/ActionMethodWithInternalNameController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/ActionMethodWithInternalNameController.cs new file mode 100644 index 000000000..0e6f7d67f --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ActionTestData/ActionMethodWithInternalNameController.cs @@ -0,0 +1,23 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ActionTestData +{ + using GraphQL.AspNet.Attributes; + using GraphQL.AspNet.Controllers; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.DirectiveTestData; + + public class ActionMethodWithInternalNameController : GraphController + { + [Query(InternalName = "Internal_Action_Name_37")] + public int Execute() + { + return 0; + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ArgumentTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ArgumentTemplateTests.cs index 9afed820a..097434b45 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ArgumentTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ArgumentTemplateTests.cs @@ -335,5 +335,12 @@ public void ArgumentTypeAttributedasGraphSkip_ThrowsException() var template = this.ExtractParameterTemplate("typeHasGraphSkip", out var paramInfo); }); } + + [Test] + public void InternalName_IsSetCorrectly() + { + var template = this.ExtractParameterTemplate("internalNameObject", out var paramInfo); + Assert.AreEqual("customInternalName_38", template.InternalName); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTemplateTests.cs index a9dc92ba1..9978094fb 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTemplateTests.cs @@ -125,5 +125,15 @@ public void SecurityPolicices_AreParsedCorrectly() Assert.IsFalse(template.SecurityPolicies.ElementAt(1).IsNamedPolicy); CollectionAssert.AreEquivalent(new string[] { "CustomRole1", "CustomRole2" }, template.SecurityPolicies.ElementAt(1).AllowedRoles); } + + [Test] + public void InternalName_WhenSuppliedOnGraphType_IsExtractedCorrectly() + { + var template = new GraphDirectiveTemplate(typeof(DirectiveWithInternalName)); + template.Parse(); + template.ValidateOrThrow(); + + Assert.AreEqual("MyInternalNameDirective", template.InternalName); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTestData/DirectiveWithInternalName.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTestData/DirectiveWithInternalName.cs new file mode 100644 index 000000000..d4ff38c92 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/DirectiveTestData/DirectiveWithInternalName.cs @@ -0,0 +1,26 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.DirectiveTestData +{ + using GraphQL.AspNet.Attributes; + using GraphQL.AspNet.Directives; + using GraphQL.AspNet.Interfaces.Controllers; + using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + + [GraphType(InternalName = "MyInternalNameDirective")] + public class DirectiveWithInternalName : GraphDirective + { + [DirectiveLocations(DirectiveLocation.FIELD)] + public IGraphActionResult Execute(TwoPropertyObject obj) + { + return null; + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumGraphTypeTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumGraphTypeTemplateTests.cs index 42ad517c5..62cc3cf84 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumGraphTypeTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumGraphTypeTemplateTests.cs @@ -235,5 +235,26 @@ public void Parse_EnumOption_AssignedDirective_IsTemplatized() Assert.AreEqual(typeof(DirectiveWithArgs), appliedDirective.DirectiveType); Assert.AreEqual(new object[] { 89, "enum option arg" }, appliedDirective.Arguments); } + + [Test] + public void Parse_InternalName_WhenSupplied_IsRendered() + { + var template = new EnumGraphTypeTemplate(typeof(EnumWithInternalName)); + template.Parse(); + template.ValidateOrThrow(); + + Assert.AreEqual("InternalName_Enum_21", template.InternalName); + } + + [Test] + public void Parse_InternalName_OnValue_WhenSupplied_IsRendered() + { + var template = new EnumGraphTypeTemplate(typeof(EnumWithInternalNameOnOption)); + template.Parse(); + template.ValidateOrThrow(); + + var option = template.Values.Single(); + Assert.AreEqual("Value1_InternalName", option.InternalName); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumWithInternalName.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumWithInternalName.cs new file mode 100644 index 000000000..07ac7a2cd --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumWithInternalName.cs @@ -0,0 +1,20 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.EnumTestData +{ + using GraphQL.AspNet.Attributes; + + [GraphType(InternalName = "InternalName_Enum_21")] + public enum EnumWithInternalName + { + Value1, + Value2, + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumWithInternalNameOnOption.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumWithInternalNameOnOption.cs new file mode 100644 index 000000000..1f24feb72 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/EnumTestData/EnumWithInternalNameOnOption.cs @@ -0,0 +1,19 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.EnumTestData +{ + using GraphQL.AspNet.Attributes; + + public enum EnumWithInternalNameOnOption + { + [GraphEnumValue(InternalName = "Value1_InternalName")] + Value1, + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ExtensionMethodTestData/ExtensionMethodController.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ExtensionMethodTestData/ExtensionMethodController.cs index 172774e92..88db90bf0 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ExtensionMethodTestData/ExtensionMethodController.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ExtensionMethodTestData/ExtensionMethodController.cs @@ -73,6 +73,12 @@ public IDictionary> CustomValidReturnType(IEnumerab return null; } + [BatchTypeExtension(typeof(TwoPropertyObject), "Property3", InternalName = "BatchInternalName")] + public IDictionary> CustomeInternalName(IEnumerable sourceData, int arg1) + { + return null; + } + [BatchTypeExtension(typeof(TwoPropertyObject), "Property3", typeof(List))] public IDictionary> MismatchedPropertyDeclarations(IEnumerable sourceData, int arg1) { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InputObjectTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InputObjectTemplateTests.cs index 57876f4a1..ab33c193f 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InputObjectTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InputObjectTemplateTests.cs @@ -374,5 +374,15 @@ public void Parse_DuplicatePropertyPaths_ThrowsException() template.ValidateOrThrow(); }); } + + [Test] + public void Parse_InternalName_WhenSupplied_IsRendered() + { + var template = new InputObjectGraphTypeTemplate(typeof(InputObjectWithInternalName)); + template.Parse(); + template.ValidateOrThrow(); + + Assert.AreEqual("InputObjectWithName_33", template.InternalName); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceGraphTypeTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceGraphTypeTemplateTests.cs index 8ab2c5281..ac26016ae 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceGraphTypeTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceGraphTypeTemplateTests.cs @@ -108,5 +108,15 @@ public void Parse_InheritedDeclaredMethodField_IsNotIncluded() Assert.AreEqual(1, Enumerable.Count(template.DeclaredInterfaces)); Assert.IsTrue(Enumerable.Contains(template.DeclaredInterfaces, typeof(InterfaceWithDeclaredInterfaceField))); } + + [Test] + public void Parse_InternalName_WhenSuppliedOnGraphType_IsExtractedCorrectly() + { + var template = new InterfaceGraphTypeTemplate(typeof(IInterfaceWIthInternalName)); + template.Parse(); + template.ValidateOrThrow(); + + Assert.AreEqual("MyInterface_32", template.InternalName); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceTestData/IInterfaceWIthInternalName.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceTestData/IInterfaceWIthInternalName.cs new file mode 100644 index 000000000..07a9d0661 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceTestData/IInterfaceWIthInternalName.cs @@ -0,0 +1,23 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.InterfaceTestData +{ + using GraphQL.AspNet.Attributes; + + [GraphType(InternalName = "MyInterface_32")] + public interface IInterfaceWIthInternalName + { + [GraphField] + string Property1 { get; } + + [GraphField] + string Property2 { get; } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplateTests.cs index 4de4de40a..17dbfa0e6 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplateTests.cs @@ -218,5 +218,18 @@ public void InvalidTypeExpression_ThrowsException() this.CreateMethodTemplate(nameof(MethodClass.InvalidTypeExpression)); }); } + + [Test] + public void InternalName_IsSetCorrectly() + { + var obj = new Mock(); + obj.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/Item0")); + obj.Setup(x => x.InternalName).Returns("Item0"); + + var parent = obj.Object; + var template = this.CreateMethodTemplate(nameof(MethodClass.MethodWithInternalName)); + + Assert.AreEqual("Method_InternalName_21", template.InternalName); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/MethodTestData/MethodClass.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/MethodTestData/MethodClass.cs index e05b714f8..a2d57dabe 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/MethodTestData/MethodClass.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/MethodTestData/MethodClass.cs @@ -161,5 +161,11 @@ public TwoPropertyObject InvalidTypeExpression() { return null; } + + [GraphField(InternalName = "Method_InternalName_21")] + public Task MethodWithInternalName() + { + return Task.FromResult(new TwoPropertyObject()); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectGraphTypeTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectGraphTypeTemplateTests.cs index 6945b6601..b9b87d2bd 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectGraphTypeTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectGraphTypeTemplateTests.cs @@ -403,5 +403,15 @@ public void Parse_StaticMethodsWithProperGraphFieldDeclarations_AreSkipped() Assert.IsNotNull(template.FieldTemplates.Values.SingleOrDefault(x => x.Route.Name == nameof(ObjectWithStatics.InstanceProperty))); Assert.IsNotNull(template.FieldTemplates.Values.SingleOrDefault(x => x.Route.Name == nameof(ObjectWithStatics.InstanceMethod))); } + + [Test] + public void Parse_InternalName_WhenSuppliedOnGraphType_IsExtractedCorrectly() + { + var template = new ObjectGraphTypeTemplate(typeof(ObjectWithInternalName)); + template.Parse(); + template.ValidateOrThrow(); + + Assert.AreEqual("MyObjectWithInternalName_33", template.InternalName); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/InputObjectWithInternalName.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/InputObjectWithInternalName.cs new file mode 100644 index 000000000..95dc3bc19 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/InputObjectWithInternalName.cs @@ -0,0 +1,20 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests +{ + using System.Threading.Tasks; + using GraphQL.AspNet.Attributes; + + [GraphType(InternalName = "InputObjectWithName_33")] + public class InputObjectWithInternalName + { + public int Id { get; set; } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ObjectWithInternalName.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ObjectWithInternalName.cs new file mode 100644 index 000000000..576a074b6 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ObjectWithInternalName.cs @@ -0,0 +1,19 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ObjectTypeTests +{ + using GraphQL.AspNet.Attributes; + + [GraphType(InternalName = "MyObjectWithInternalName_33")] + public class ObjectWithInternalName + { + public int Property1 { get; } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ParameterTestData/ParameterTestClass.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ParameterTestData/ParameterTestClass.cs index d1b2c52a5..b723363bc 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ParameterTestData/ParameterTestClass.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ParameterTestData/ParameterTestClass.cs @@ -53,6 +53,7 @@ public int TestMethod( [FromGraphQL] TwoPropertyObject justFromGraphQLDeclaration, [FromServices] TwoPropertyObject justFromServicesDeclaration, [FromGraphQL] [FromServices] TwoPropertyObject doubleDeclaredObject, + [FromGraphQL(InternalName = "customInternalName_38")] int internalNameObject, Person defaultValueObjectArg = null, string defaultValueStringArg = null, string defaultValueStringArgWithValue = "abc", diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyGraphFieldTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyGraphFieldTemplateTests.cs index bd2ecd212..013aa5060 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyGraphFieldTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyGraphFieldTemplateTests.cs @@ -253,5 +253,26 @@ public void InvalidTypeExpression_ThrowsException() template.ValidateOrThrow(); }); } + + [Test] + public void Parse_InternalName_IsSetCorrectly() + { + var obj = new Mock(); + obj.Setup(x => x.Route).Returns(new SchemaItemPath("[type]/Item0")); + obj.Setup(x => x.InternalName).Returns("Item0"); + + var expectedTypeExpression = new GraphTypeExpression( + typeof(KeyValuePair).FriendlyGraphTypeName(), + MetaGraphTypes.IsList, + MetaGraphTypes.IsNotNull); // structs can't be null + + var parent = obj.Object; + var propInfo = typeof(PropertyWithInternalName).GetProperty(nameof(PropertyWithInternalName.Prop1)); + + var template = new PropertyGraphFieldTemplate(parent, propInfo, TypeKind.OBJECT); + template.Parse(); + template.ValidateOrThrow(); + Assert.AreEqual("prop_Field_223", template.InternalName); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyTestData/PropertyWithInternalName.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyTestData/PropertyWithInternalName.cs new file mode 100644 index 000000000..09dba2896 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/PropertyTestData/PropertyWithInternalName.cs @@ -0,0 +1,19 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.PropertyTestData +{ + using GraphQL.AspNet.Attributes; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.DirectiveTestData; + + public class PropertyWithInternalName + { + [GraphField(InternalName = "prop_Field_223")] + public int Prop1 { get; set; } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/TypeExtensionFieldTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/TypeExtensionFieldTemplateTests.cs index 6c8cfdc55..ea76e68a9 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/TypeExtensionFieldTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/TypeExtensionFieldTemplateTests.cs @@ -248,5 +248,14 @@ public void BatchExtension_ExtendingAnEnum_ThrowsException() this.CreateExtensionTemplate(nameof(ExtensionMethodController.EnumBatchExtensionFails)); }); } + + [Test] + public void ValidBatchExtension_WithCustomInternalName_PropertyCheck() + { + var methodInfo = typeof(ExtensionMethodController).GetMethod(nameof(ExtensionMethodController.CustomeInternalName)); + var template = this.CreateExtensionTemplate(nameof(ExtensionMethodController.CustomeInternalName)); + + Assert.AreEqual("BatchInternalName", template.InternalName); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/UnionGraphTypeTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/UnionGraphTypeTemplateTests.cs index 113444904..423be86a8 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/UnionGraphTypeTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/UnionGraphTypeTemplateTests.cs @@ -38,17 +38,23 @@ public void NotAProxy_ThrowsException() [Test] public void ValidateProxy_ParsesCorrectly() { - var instance = new UnionGraphTypeTemplate(typeof(ValidTestUnion)); + var instance = new UnionGraphTypeTemplate(typeof(UnionWithInternalName)); instance.Parse(); instance.ValidateOrThrow(); - Assert.AreEqual(TypeKind.UNION, instance.Kind); - Assert.AreEqual("ValidUnion", instance.Name); - Assert.AreEqual("My Union Desc", instance.Description); - Assert.AreEqual("ValidUnion", instance.InternalName); // should use union name when supplied - Assert.AreEqual(typeof(ValidTestUnion), instance.ProxyType); - Assert.IsTrue(instance.Publish); + Assert.AreEqual("My Union Internal Name", instance.InternalName); + } + + [Test] + public void ValidateProxy_NoInternalName_FallsBackToProxyName() + { + var instance = new UnionGraphTypeTemplate(typeof(UnionWithNoInternalName)); + + instance.Parse(); + instance.ValidateOrThrow(); + + Assert.AreEqual(nameof(UnionWithNoInternalName), instance.InternalName); } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/UnionTestData/UnionWithInternalName.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/UnionTestData/UnionWithInternalName.cs new file mode 100644 index 000000000..13ce1f0ee --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/UnionTestData/UnionWithInternalName.cs @@ -0,0 +1,26 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.UnionTestData +{ + using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + + public class UnionWithInternalName : GraphUnionProxy + { + public UnionWithInternalName() + { + this.Name = "ValidUnion"; + this.Description = "My Union Desc"; + this.InternalName = "My Union Internal Name"; + this.Types.Add(typeof(TwoPropertyObject)); + this.Types.Add(typeof(TwoPropertyObjectV2)); + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/UnionTestData/UnionWithNoInternalName.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/UnionTestData/UnionWithNoInternalName.cs new file mode 100644 index 000000000..bcc8e17fa --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/UnionTestData/UnionWithNoInternalName.cs @@ -0,0 +1,26 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.UnionTestData +{ + using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + + public class UnionWithNoInternalName : GraphUnionProxy + { + public UnionWithNoInternalName() + { + this.Name = "ValidUnion"; + this.Description = "My Union Desc"; + this.InternalName = null; + this.Types.Add(typeof(TwoPropertyObject)); + this.Types.Add(typeof(TwoPropertyObjectV2)); + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/graphql-aspnet-tests.csproj b/src/unit-tests/graphql-aspnet-tests/graphql-aspnet-tests.csproj index a026d01d2..dd74c524c 100644 --- a/src/unit-tests/graphql-aspnet-tests/graphql-aspnet-tests.csproj +++ b/src/unit-tests/graphql-aspnet-tests/graphql-aspnet-tests.csproj @@ -63,5 +63,9 @@ + + + + From 8de7b4cec3084a009891d7a16834270a22ee5310 Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Sun, 23 Jul 2023 17:18:10 -0700 Subject: [PATCH 48/63] WIP --- .../graphql-aspnet-tests/graphql-aspnet-tests.csproj | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/unit-tests/graphql-aspnet-tests/graphql-aspnet-tests.csproj b/src/unit-tests/graphql-aspnet-tests/graphql-aspnet-tests.csproj index dd74c524c..a026d01d2 100644 --- a/src/unit-tests/graphql-aspnet-tests/graphql-aspnet-tests.csproj +++ b/src/unit-tests/graphql-aspnet-tests/graphql-aspnet-tests.csproj @@ -63,9 +63,5 @@ - - - - From 6848a9e7256808f7adea73f147060893dbb37212 Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Mon, 24 Jul 2023 16:17:43 -0700 Subject: [PATCH 49/63] WIP, added union support to runtme apis --- .../Attributes/PossibleTypesAttribute.cs | 4 +- .../Attributes/UnionAttribute.cs | 24 +- ...chemaItemDefinitionExtensions_Mutations.cs | 160 +++++++++--- ...eSchemaItemDefinitionExtensions_Queries.cs | 157 +++++++++--- ...ItemDefinitionExtensions_ResolvedFields.cs | 73 +++++- ...ItemDefinitionExtensions_TypeExtensions.cs | 239 +++++++++++++----- .../IGraphQLRuntimeSchemaItemDefinition.cs | 6 + .../BaseRuntimeControllerActionDefinition.cs | 7 + .../TypeTemplates/GraphFieldTemplateBase.cs | 3 - src/styles.ruleset | 211 ++++++++-------- src/styles.ruleset.original | 138 ++++++++++ .../Execution/RuntimeTypeExtensionTests.cs | 20 +- .../MappedMutationTemplateTests.cs | 39 +++ .../MappedQueryTemplateTests.cs | 40 +++ .../MappedTypeExtensionTemplateTests.cs | 59 ++++- .../TypeMakers/ObjectGraphTypeMakerTests.cs | 2 - .../Schemas/RuntimeFieldsGeneralTests.cs | 87 +++++++ 17 files changed, 990 insertions(+), 279 deletions(-) create mode 100644 src/styles.ruleset.original create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/RuntimeFieldsGeneralTests.cs diff --git a/src/graphql-aspnet/Attributes/PossibleTypesAttribute.cs b/src/graphql-aspnet/Attributes/PossibleTypesAttribute.cs index edce03ab0..98771b55d 100644 --- a/src/graphql-aspnet/Attributes/PossibleTypesAttribute.cs +++ b/src/graphql-aspnet/Attributes/PossibleTypesAttribute.cs @@ -32,13 +32,13 @@ public class PossibleTypesAttribute : Attribute /// Any additional possible types. public PossibleTypesAttribute(Type firstPossibleType, params Type[] additionalPossibleTypes) { - this.PossibleTypes = firstPossibleType.AsEnumerable().Concat(additionalPossibleTypes).Where(x => x != null).ToArray(); + this.PossibleTypes = firstPossibleType.AsEnumerable().Concat(additionalPossibleTypes).Where(x => x != null).ToList(); } /// /// Gets the possible types this field may return under its declared interface. /// /// The possible types. - public IReadOnlyList PossibleTypes { get; } + public IList PossibleTypes { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Attributes/UnionAttribute.cs b/src/graphql-aspnet/Attributes/UnionAttribute.cs index c8bfe491b..c6d1e372a 100644 --- a/src/graphql-aspnet/Attributes/UnionAttribute.cs +++ b/src/graphql-aspnet/Attributes/UnionAttribute.cs @@ -11,6 +11,7 @@ namespace GraphQL.AspNet.Attributes { using System; using System.Collections.Generic; + using System.Linq; using GraphQL.AspNet.Interfaces.Controllers; using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Schemas.TypeSystem; @@ -38,7 +39,6 @@ public class UnionAttribute : GraphAttributeBase /// public UnionAttribute(string unionName, Type firstUnionMemberType, Type secondUnionMemberType, params Type[] otherUnionMembers) { - this.UnionProxyType = null; this.UnionName = unionName?.Trim(); var list = new List(2 + otherUnionMembers.Length); @@ -55,28 +55,30 @@ public UnionAttribute(string unionName, Type firstUnionMemberType, Type secondUn /// declares all required information about the referenced union. public UnionAttribute(Type unionProxyType) { - this.UnionProxyType = unionProxyType; this.UnionName = null; - this.UnionProxyType = null; + if (unionProxyType != null) + this.UnionMemberTypes = new List() { unionProxyType }; } /// - /// Gets a type that implements inherits from or - /// that declares all required information about the referenced union. + /// Initializes a new instance of the class. /// - /// The union proxy type to reference when building the schema references for this field. - public Type UnionProxyType { get; } + /// The name to assign to this union. + public UnionAttribute(string unionName) + { + this.UnionName = unionName; + } /// - /// Gets the name of the new union to create within the schema. This union name must be a valid graph name. + /// Gets or sets the name of the new union to create within the schema. This union name must be a valid graph name. /// /// The name of the union as it will appear in the schema. - public string UnionName { get; } + public string UnionName { get; set; } /// - /// Gets the concrete types of the objects that may be returned by this field. + /// Gets or sets the concrete types of the objects that may be returned by this field. /// /// All union member types to be included in this union. - public IReadOnlyList UnionMemberTypes { get; } + public IList UnionMemberTypes { get; set; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Mutations.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Mutations.cs index 289787be6..599cc709b 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Mutations.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Mutations.cs @@ -10,6 +10,8 @@ namespace GraphQL.AspNet.Configuration { using System; + using System.Linq; + using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Common; using GraphQL.AspNet.Interfaces.Configuration; using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; @@ -20,6 +22,87 @@ namespace GraphQL.AspNet.Configuration /// public static partial class GraphQLRuntimeSchemaItemDefinitionExtensions { + /// + /// Creates a new, explicitly resolvable field in the mutation root object with the given path. This field cannot be + /// further extended or nested with other fields via the Mapping API. + /// + /// The builder representing the schema where this field + /// will be created. + /// The template path string for his field. (e.g. /path1/path2/path3) + /// IGraphQLFieldTemplate. + public static IGraphQLRuntimeResolvedFieldDefinition MapMutation(this ISchemaBuilder schemaBuilder, string template) + { + Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); + + return MapMutation( + schemaBuilder.Options, + template, + null, // unionName + null as Delegate); + } + + /// + /// Creates a new field in the mutation object with the given path. This field can act as a + /// grouping field of other resolvable fields or be converted to an explicitly resolvable field itself. + /// + /// The builder representing the schema where this field + /// will be created. + /// The template path string for his field. (e.g. /path1/path2/path3) + /// The resolver method to execute when this + /// field is requested. + /// IGraphQLFieldTemplate. + public static IGraphQLRuntimeResolvedFieldDefinition MapMutation(this ISchemaBuilder schemaBuilder, string template, Delegate resolverMethod) + { + Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); + return MapMutation( + schemaBuilder.Options, + template, + null, // unionName + resolverMethod); + } + + /// + /// Creates a new, explicitly resolvable field in the mutation root object with the given path. This field cannot be + /// further extended or nested with other fields via the Mapping API. + /// + /// The builder representing the schema where this field + /// will be created. + /// The template path string for his field. (e.g. /path1/path2/path3) + /// Provide a name and this field will be declared to return a union. Use to declare union members. + /// IGraphQLFieldTemplate. + public static IGraphQLRuntimeResolvedFieldDefinition MapMutation(this ISchemaBuilder schemaBuilder, string template, string unionName) + { + Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); + + return MapMutation( + schemaBuilder.Options, + template, + unionName, // unionName + null as Delegate); + } + + /// + /// Creates a new field in the mutation object with the given path. This field can act as a + /// grouping field of other resolvable fields or be converted to an explicitly resolvable field itself. + /// + /// The builder representing the schema where this field + /// will be created. + /// The template path string for his field. (e.g. /path1/path2/path3) + /// Provide a name and this field will be declared to return a union. Use to declare union members. + /// The resolver method to execute when this + /// field is requested. + /// IGraphQLFieldTemplate. + public static IGraphQLRuntimeResolvedFieldDefinition MapMutation(this ISchemaBuilder schemaBuilder, string template, string unionName, Delegate resolverMethod) + { + Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); + + return MapMutation( + schemaBuilder.Options, + template, + unionName, + resolverMethod); + } + /// /// Creates a new field in the mutation root object with the given path. This field can act as a /// grouping field of other resolvable fields or be converted to an explicitly resolvable field itself. @@ -30,16 +113,15 @@ public static partial class GraphQLRuntimeSchemaItemDefinitionExtensions /// IGraphQLFieldTemplate. public static IGraphQLRuntimeResolvedFieldDefinition MapMutation(this SchemaOptions schemaOptions, string template) { - var field = MapGraphQLFieldInternal( + return MapMutation( schemaOptions, - GraphOperationType.Mutation, - template); - - return field.AddResolver(null); + template, + null, // unionName + null as Delegate); } /// - /// Creates a new, explicitly resolvable field in the mutation root object with the given path. This field cannot be + /// Creates a new, explicitly resolvable field in the Mutation root object with the given path. This field cannot be /// further extended or nested with other fields via the Mapping API. /// /// The options representing the schema where this field @@ -50,55 +132,65 @@ public static IGraphQLRuntimeResolvedFieldDefinition MapMutation(this SchemaOpti /// IGraphQLResolvedFieldTemplate. public static IGraphQLRuntimeResolvedFieldDefinition MapMutation(this SchemaOptions schemaOptions, string template, Delegate resolverMethod) { - Validation.ThrowIfNull(resolverMethod, nameof(resolverMethod)); - - var field = MapGraphQLFieldInternal( + return MapMutation( schemaOptions, - GraphOperationType.Mutation, - template); - - return field.AddResolver(resolverMethod); + template, + null, // unionName + resolverMethod); } /// - /// Creates a new, explicitly resolvable field in the mutation root object with the given path. This field cannot be - /// further extended or nested with other fields via the Mapping API. + /// Creates a new field in the Mutation root object with the given path. This field can act as a + /// grouping field of other resolvable fields or be converted to an explicitly resolvable field itself. /// - /// The builder representing the schema where this field + /// The options representing the schema where this field /// will be created. /// The template path string for his field. (e.g. /path1/path2/path3) + /// Provide a name and this field will be declared to return a union. Use to declare union members. /// IGraphQLFieldTemplate. - public static IGraphQLRuntimeResolvedFieldDefinition MapMutation(this ISchemaBuilder schemaBuilder, string template) + public static IGraphQLRuntimeResolvedFieldDefinition MapMutation(this SchemaOptions schemaOptions, string template, string unionName) { - Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); - - var field = MapGraphQLFieldInternal( - schemaBuilder.Options, - GraphOperationType.Mutation, - template); - - return field.AddResolver(null); + return MapMutation( + schemaOptions, + template, + unionName, // unionName + null as Delegate); } /// - /// Creates a new field in the mutation root object with the given path. This field can act as a - /// grouping field of other resolvable fields or be converted to an explicitly resolvable field itself. + /// Creates a new, explicitly resolvable field in the Mutation root object with the given path. This field cannot be + /// further extended or nested with other fields via the Mapping API. /// - /// The builder representing the schema where this field + /// The options representing the schema where this field /// will be created. /// The template path string for his field. (e.g. /path1/path2/path3) - /// The resolver method to execute when this field is requested. - /// IGraphQLFieldTemplate. - public static IGraphQLRuntimeResolvedFieldDefinition MapMutation(this ISchemaBuilder schemaBuilder, string template, Delegate resolverMethod) + /// Provide a name and this field will be declared to return a union. Use to declare union members. + /// The resolver method to execute when + /// this field is requested by a caller. + /// IGraphQLResolvedFieldTemplate. + public static IGraphQLRuntimeResolvedFieldDefinition MapMutation(this SchemaOptions schemaOptions, string template, string unionName, Delegate resolverMethod) { - Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); - Validation.ThrowIfNull(resolverMethod, nameof(resolverMethod)); + Validation.ThrowIfNull(schemaOptions, nameof(schemaOptions)); var field = MapGraphQLFieldInternal( - schemaBuilder.Options, + schemaOptions, GraphOperationType.Mutation, template); + if (!string.IsNullOrWhiteSpace(unionName)) + { + var unionAttrib = field.Attributes.OfType().SingleOrDefault(); + if (unionAttrib != null) + { + unionAttrib.UnionName = unionName.Trim(); + unionAttrib.UnionMemberTypes.Clear(); + } + else + { + field.AddAttribute(new UnionAttribute(unionName.Trim())); + } + } + return field.AddResolver(resolverMethod); } } diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Queries.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Queries.cs index 9eadf56fe..9a2ce4a4a 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Queries.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Queries.cs @@ -10,6 +10,8 @@ namespace GraphQL.AspNet.Configuration { using System; + using System.Linq; + using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Common; using GraphQL.AspNet.Interfaces.Configuration; using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; @@ -21,43 +23,42 @@ namespace GraphQL.AspNet.Configuration public static partial class GraphQLRuntimeSchemaItemDefinitionExtensions { /// - /// Creates a new field in the query root object with the given path. This field can act as a - /// grouping field of other resolvable fields or be converted to an explicitly resolvable field itself. + /// Creates a new, explicitly resolvable field in the query root object with the given path. This field cannot be + /// further extended or nested with other fields via the Mapping API. /// - /// The options representing the schema where this field + /// The builder representing the schema where this field /// will be created. /// The template path string for his field. (e.g. /path1/path2/path3) /// IGraphQLFieldTemplate. - public static IGraphQLRuntimeResolvedFieldDefinition MapQuery(this SchemaOptions schemaOptions, string template) + public static IGraphQLRuntimeResolvedFieldDefinition MapQuery(this ISchemaBuilder schemaBuilder, string template) { - var field = MapGraphQLFieldInternal( - schemaOptions, - GraphOperationType.Query, - template); + Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); - return field.AddResolver(null); + return MapQuery( + schemaBuilder.Options, + template, + null, // unionName + null as Delegate); } /// - /// Creates a new, explicitly resolvable field in the query root object with the given path. This field cannot be - /// further extended or nested with other fields via the Mapping API. + /// Creates a new field in the query object with the given path. This field can act as a + /// grouping field of other resolvable fields or be converted to an explicitly resolvable field itself. /// - /// The options representing the schema where this field + /// The builder representing the schema where this field /// will be created. /// The template path string for his field. (e.g. /path1/path2/path3) - /// The resolver method to execute when - /// this field is requested by a caller. - /// IGraphQLResolvedFieldTemplate. - public static IGraphQLRuntimeResolvedFieldDefinition MapQuery(this SchemaOptions schemaOptions, string template, Delegate resolverMethod) + /// The resolver method to execute when this + /// field is requested. + /// IGraphQLFieldTemplate. + public static IGraphQLRuntimeResolvedFieldDefinition MapQuery(this ISchemaBuilder schemaBuilder, string template, Delegate resolverMethod) { - Validation.ThrowIfNull(resolverMethod, nameof(resolverMethod)); - - var field = MapGraphQLFieldInternal( - schemaOptions, - GraphOperationType.Query, - template); - - return field.AddResolver(resolverMethod); + Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); + return MapQuery( + schemaBuilder.Options, + template, + null, // unionName + resolverMethod); } /// @@ -67,17 +68,17 @@ public static IGraphQLRuntimeResolvedFieldDefinition MapQuery(this SchemaOptions /// The builder representing the schema where this field /// will be created. /// The template path string for his field. (e.g. /path1/path2/path3) + /// Provide a name and this field will be declared to return a union. Use to declare union members. /// IGraphQLFieldTemplate. - public static IGraphQLRuntimeResolvedFieldDefinition MapQuery(this ISchemaBuilder schemaBuilder, string template) + public static IGraphQLRuntimeResolvedFieldDefinition MapQuery(this ISchemaBuilder schemaBuilder, string template, string unionName) { Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); - var field = MapGraphQLFieldInternal( + return MapQuery( schemaBuilder.Options, - GraphOperationType.Query, - template); - - return field.AddResolver(null); + template, + unionName, // unionName + null as Delegate); } /// @@ -87,19 +88,109 @@ public static IGraphQLRuntimeResolvedFieldDefinition MapQuery(this ISchemaBuilde /// The builder representing the schema where this field /// will be created. /// The template path string for his field. (e.g. /path1/path2/path3) + /// Provide a name and this field will be declared to return a union. Use to declare union members. /// The resolver method to execute when this /// field is requested. /// IGraphQLFieldTemplate. - public static IGraphQLRuntimeResolvedFieldDefinition MapQuery(this ISchemaBuilder schemaBuilder, string template, Delegate resolverMethod) + public static IGraphQLRuntimeResolvedFieldDefinition MapQuery(this ISchemaBuilder schemaBuilder, string template, string unionName, Delegate resolverMethod) { Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); - Validation.ThrowIfNull(resolverMethod, nameof(resolverMethod)); - var field = MapGraphQLFieldInternal( + return MapQuery( schemaBuilder.Options, + template, + unionName, + resolverMethod); + } + + /// + /// Creates a new field in the query root object with the given path. This field can act as a + /// grouping field of other resolvable fields or be converted to an explicitly resolvable field itself. + /// + /// The options representing the schema where this field + /// will be created. + /// The template path string for his field. (e.g. /path1/path2/path3) + /// IGraphQLFieldTemplate. + public static IGraphQLRuntimeResolvedFieldDefinition MapQuery(this SchemaOptions schemaOptions, string template) + { + return MapQuery( + schemaOptions, + template, + null, // unionMethod + null as Delegate); + } + + /// + /// Creates a new, explicitly resolvable field in the query root object with the given path. This field cannot be + /// further extended or nested with other fields via the Mapping API. + /// + /// The options representing the schema where this field + /// will be created. + /// The template path string for his field. (e.g. /path1/path2/path3) + /// The resolver method to execute when + /// this field is requested by a caller. + /// IGraphQLResolvedFieldTemplate. + public static IGraphQLRuntimeResolvedFieldDefinition MapQuery(this SchemaOptions schemaOptions, string template, Delegate resolverMethod) + { + return MapQuery( + schemaOptions, + template, + null, // unionMethod + resolverMethod); + } + + /// + /// Creates a new field in the query root object with the given path. This field can act as a + /// grouping field of other resolvable fields or be converted to an explicitly resolvable field itself. + /// + /// The options representing the schema where this field + /// will be created. + /// The template path string for his field. (e.g. /path1/path2/path3) + /// Provide a name and this field will be declared to return a union. Use to declare union members. + /// IGraphQLFieldTemplate. + public static IGraphQLRuntimeResolvedFieldDefinition MapQuery(this SchemaOptions schemaOptions, string template, string unionName) + { + return MapQuery( + schemaOptions, + template, + unionName, // unionName + null as Delegate); + } + + /// + /// Creates a new, explicitly resolvable field in the query root object with the given path. This field cannot be + /// further extended or nested with other fields via the Mapping API. + /// + /// The options representing the schema where this field + /// will be created. + /// The template path string for his field. (e.g. /path1/path2/path3) + /// Provide a name and this field will be declared to return a union. Use to declare union members. + /// The resolver method to execute when + /// this field is requested by a caller. + /// IGraphQLResolvedFieldTemplate. + public static IGraphQLRuntimeResolvedFieldDefinition MapQuery(this SchemaOptions schemaOptions, string template, string unionName, Delegate resolverMethod) + { + Validation.ThrowIfNull(schemaOptions, nameof(schemaOptions)); + + var field = MapGraphQLFieldInternal( + schemaOptions, GraphOperationType.Query, template); + if (!string.IsNullOrWhiteSpace(unionName)) + { + var unionAttrib = field.Attributes.OfType().SingleOrDefault(); + if (unionAttrib != null) + { + unionAttrib.UnionName = unionName?.Trim(); + unionAttrib.UnionMemberTypes.Clear(); + } + else + { + field.AddAttribute(new UnionAttribute(unionName.Trim())); + } + } + return field.AddResolver(resolverMethod); } } diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_ResolvedFields.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_ResolvedFields.cs index 2df6cfe02..8e36e6c1c 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_ResolvedFields.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_ResolvedFields.cs @@ -10,6 +10,8 @@ namespace GraphQL.AspNet.Configuration { using System; + using System.Linq; + using System.Reflection; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Common; using GraphQL.AspNet.Interfaces.Controllers; @@ -46,7 +48,8 @@ public static IGraphQLRuntimeResolvedFieldDefinition RequireAuthorization( } /// - /// Indicates that the field should allow anonymous access. + /// Indicates that the field should allow anonymous access. This will override any potential authorization requirements setup via + /// the "MapGroup" methods if this field was created within a group. /// /// /// This is similar to adding the to a controller method @@ -60,6 +63,40 @@ public static IGraphQLRuntimeResolvedFieldDefinition AllowAnonymous(this IGraphQ return fieldBuilder; } + /// + /// Indicates this field will return a union and sets the resolver to be used when this field is requested at runtime. The provided + /// resolver should return a . + /// + /// The field being built. + /// Provide a name and this field will be declared to return a union. Use to declare union members. + /// The delegate to assign as the resolver. This method will be + /// parsed to determine input arguments for the field on the target schema. + /// IGraphQLFieldBuilder. + public static IGraphQLRuntimeResolvedFieldDefinition AddResolver( + this IGraphQLRuntimeResolvedFieldDefinition fieldBuilder, + string unionName, + Delegate resolverMethod) + { + fieldBuilder.Resolver = resolverMethod; + fieldBuilder.ReturnType = null; + + if (!string.IsNullOrWhiteSpace(unionName)) + { + var unionAttrib = fieldBuilder.Attributes.OfType().SingleOrDefault(); + if (unionAttrib != null) + { + unionAttrib.UnionName = unionName?.Trim(); + unionAttrib.UnionMemberTypes.Clear(); + } + else + { + fieldBuilder.AddAttribute(new UnionAttribute(unionName.Trim())); + } + } + + return fieldBuilder; + } + /// /// Sets the resolver to be used when this field is requested at runtime. /// @@ -75,6 +112,12 @@ public static IGraphQLRuntimeResolvedFieldDefinition AddResolver(this IGraphQLRu fieldBuilder.Resolver = resolverMethod; fieldBuilder.ReturnType = null; + // since the resolver was declared as non-union, remove any potential union setup that might have + // existed via a previous call. + var unionAttrib = fieldBuilder.Attributes.OfType().SingleOrDefault(); + if (unionAttrib != null) + fieldBuilder.RemoveAttribute(unionAttrib); + return fieldBuilder; } @@ -94,6 +137,14 @@ public static IGraphQLRuntimeResolvedFieldDefinition AddResolver(th { fieldBuilder.Resolver = resolverMethod; fieldBuilder.ReturnType = typeof(TReturnType); + + // since the resolver was declared as non-union, remove any potential union setup that might have + // existed via a previous call. if TReturnType is a union proxy it will be + // picked up automatically during templating + var unionAttrib = fieldBuilder.Attributes.OfType().SingleOrDefault(); + if (unionAttrib != null) + fieldBuilder.RemoveAttribute(unionAttrib); + return fieldBuilder; } @@ -103,7 +154,8 @@ public static IGraphQLRuntimeResolvedFieldDefinition AddResolver(th /// /// /// This method can be called multiple times. Any new types will be appended to the field. All types added - /// must be coercable to the declared return type of the assigned resolver for this field. + /// must be coercable to the declared return type of the assigned resolver for this field unless this field returns a union; in + /// which case the types will be added as union members. /// /// The field being built. /// The first possible type that might be returned by this @@ -118,6 +170,21 @@ public static IGraphQLRuntimeResolvedFieldDefinition AddPossibleTypes(this IGrap return fieldBuilder; } + /// + /// Clears all extra defined possible types this field may declare. This will not affect the core type defined by the resolver, if + /// a resolver has been defined for this field. + /// + /// The field builder. + /// IGraphQLRuntimeResolvedFieldDefinition. + public static IGraphQLRuntimeResolvedFieldDefinition ClearPossibleTypes(this IGraphQLRuntimeResolvedFieldDefinition fieldBuilder) + { + var attributes = fieldBuilder.Attributes.OfType().ToList(); + foreach (var att in attributes) + fieldBuilder.RemoveAttribute(att); + + return fieldBuilder; + } + /// /// Assigns a custom internal name to this field. This value will be used in error /// messages and log entries instead of an anonymous method name. This can significantly increase readability @@ -133,7 +200,7 @@ public static IGraphQLRuntimeResolvedFieldDefinition AddPossibleTypes(this IGrap /// IGraphQLFieldBuilder. public static IGraphQLRuntimeResolvedFieldDefinition WithName(this IGraphQLRuntimeResolvedFieldDefinition fieldBuilder, string internalName) { - fieldBuilder.InternalName = internalName; + fieldBuilder.InternalName = internalName?.Trim(); return fieldBuilder; } } diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_TypeExtensions.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_TypeExtensions.cs index bab8bd179..868db105a 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_TypeExtensions.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_TypeExtensions.cs @@ -11,6 +11,7 @@ namespace GraphQL.AspNet.Configuration { using System; using System.Collections.Generic; + using System.Linq; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Common; using GraphQL.AspNet.Execution; @@ -25,79 +26,62 @@ namespace GraphQL.AspNet.Configuration public static partial class GraphQLRuntimeSchemaItemDefinitionExtensions { /// - /// Adds policy-based authorization requirements to the field. + /// Registers a new type extension to a given OBJECT or INTERFACE type for the target schema. /// /// - /// This is similar to adding the to a controller method + /// + /// This method is synonymous with using the on + /// a controller action. + /// + /// + /// The supplied resolver must declare a parameter that is of the same type as . + /// /// - /// The field being built. - /// The name of the policy to assign via this requirement. - /// A comma-seperated list of roles to assign via this requirement. - /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeTypeExtensionDefinition RequireAuthorization( - this IGraphQLRuntimeTypeExtensionDefinition fieldBuilder, - string policyName = null, - string roles = null) + /// The concrete interface, class or struct to extend with a new field. + /// The schema builder to append the field to. + /// Name of the field to add to the . + /// The resolver method to be called when the field is requested. + /// IGraphQLResolvedFieldTemplate. + public static IGraphQLRuntimeTypeExtensionDefinition MapTypeExtension(this ISchemaBuilder builder, string fieldName, Delegate resolverMethod = null) { - Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); - - var attrib = new AuthorizeAttribute(); - attrib.Policy = policyName?.Trim(); - attrib.Roles = roles?.Trim(); - fieldBuilder.AddAttribute(attrib); - return fieldBuilder; - } + Validation.ThrowIfNull(builder, nameof(builder)); - /// - /// Indicates that the field should allow anonymous access. - /// - /// - /// This is similar to adding the to a controller method - /// - /// The field being built. - /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeTypeExtensionDefinition AllowAnonymous(this IGraphQLRuntimeTypeExtensionDefinition fieldBuilder) - { - Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); - fieldBuilder.AddAttribute(new AllowAnonymousAttribute()); - return fieldBuilder; + return MapTypeExtension( + builder.Options, + typeof(TOwnerType), + fieldName, + null, // unionName + resolverMethod); } /// - /// Sets the resolver to be used when this field is requested at runtime. + /// Registers a new type extension to a given OBJECT or INTERFACE type for the target schema. /// /// - /// If this method is called more than once the previously set resolver will be replaced. + /// + /// This method is synonymous with using the on + /// a controller action. + /// + /// + /// The supplied resolver must declare a parameter that is of the same type as . + /// /// - /// The field being built. - /// The delegate to assign as the resolver. This method will be - /// parsed to determine input arguments for the field on the target schema. - /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeTypeExtensionDefinition AddResolver(this IGraphQLRuntimeTypeExtensionDefinition fieldBuilder, Delegate resolverMethod) + /// The concrete interface, class or struct to extend with a new field. + /// The schema builder to append the field to. + /// Name of the field to add to the . + /// Provide a name and this field will be declared to return a union. Use to declare union members. + /// The resolver method to be called when the field is requested. + /// IGraphQLResolvedFieldTemplate. + public static IGraphQLRuntimeTypeExtensionDefinition MapTypeExtension(this ISchemaBuilder builder, string fieldName, string unionName, Delegate resolverMethod = null) { - fieldBuilder.Resolver = resolverMethod; - fieldBuilder.ReturnType = null; - - return fieldBuilder; - } + Validation.ThrowIfNull(builder, nameof(builder)); - /// - /// Sets the resolver to be used when this field is requested at runtime. - /// - /// - /// If this method is called more than once the previously set resolver will be replaced. - /// - /// The expected, primary return type of the field. Must be provided - /// if the supplied delegate returns an . - /// The field being built. - /// The delegate to assign as the resolver. This method will be - /// parsed to determine input arguments for the field on the target schema. - /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeTypeExtensionDefinition AddResolver(this IGraphQLRuntimeTypeExtensionDefinition fieldBuilder, Delegate resolverMethod) - { - fieldBuilder.Resolver = resolverMethod; - fieldBuilder.ReturnType = typeof(TReturnType); - return fieldBuilder; + return MapTypeExtension( + builder.Options, + typeof(TOwnerType), + fieldName, + unionName, + resolverMethod); } /// @@ -113,20 +97,45 @@ public static IGraphQLRuntimeTypeExtensionDefinition AddResolver(th /// /// /// The concrete interface, class or struct to extend with a new field. - /// The schema builder to append the field to. + /// The configuration options for the target schema. /// Name of the field to add to the . /// The resolver method to be called when the field is requested. /// IGraphQLResolvedFieldTemplate. - public static IGraphQLRuntimeTypeExtensionDefinition MapField(this ISchemaBuilder builder, string fieldName, Delegate resolverMethod = null) + public static IGraphQLRuntimeTypeExtensionDefinition MapTypeExtension(this SchemaOptions schemaOptions, string fieldName, Delegate resolverMethod = null) { - Validation.ThrowIfNull(builder, nameof(builder)); - - return builder.Options.MapField( + return MapTypeExtension( + schemaOptions, typeof(TOwnerType), fieldName, + null, // unionName resolverMethod); } + /// + /// Registers a new field to a given type on the target schema. + /// + /// + /// + /// The supplied resolver must declare a parameter that is of the same type as . + /// + /// + /// The configuration options for the target schema. + /// The concrete interface, class or struct to extend with a new field. + /// Name of the field to add to the . + /// The resolver method to be called when the field is requested. + /// IGraphQLResolvedFieldTemplate. + public static IGraphQLRuntimeTypeExtensionDefinition MapTypeExtension(this SchemaOptions schemaOptions, Type fieldOwnerType, string fieldName, Delegate resolverMethod = null) + { + var field = MapTypeExtension( + schemaOptions, + fieldOwnerType, + fieldName, + null, // unionName + resolverMethod); + + return field; + } + /// /// Registers a new type extension to a given OBJECT or INTERFACE type for the target schema. /// @@ -142,13 +151,16 @@ public static IGraphQLRuntimeTypeExtensionDefinition MapField(this I /// The concrete interface, class or struct to extend with a new field. /// The configuration options for the target schema. /// Name of the field to add to the . + /// Provide a name and this field will be declared to return a union. Use to declare union members. /// The resolver method to be called when the field is requested. /// IGraphQLResolvedFieldTemplate. - public static IGraphQLRuntimeTypeExtensionDefinition MapField(this SchemaOptions schemaOptions, string fieldName, Delegate resolverMethod = null) + public static IGraphQLRuntimeTypeExtensionDefinition MapTypeExtension(this SchemaOptions schemaOptions, string fieldName, string unionName, Delegate resolverMethod = null) { - return schemaOptions.MapField( + return MapTypeExtension( + schemaOptions, typeof(TOwnerType), fieldName, + unionName, resolverMethod); } @@ -163,9 +175,10 @@ public static IGraphQLRuntimeTypeExtensionDefinition MapField(this S /// The configuration options for the target schema. /// The concrete interface, class or struct to extend with a new field. /// Name of the field to add to the . + /// Provide a name and this field will be declared to return a union. Use to declare union members. /// The resolver method to be called when the field is requested. /// IGraphQLResolvedFieldTemplate. - public static IGraphQLRuntimeTypeExtensionDefinition MapField(this SchemaOptions schemaOptions, Type fieldOwnerType, string fieldName, Delegate resolverMethod = null) + public static IGraphQLRuntimeTypeExtensionDefinition MapTypeExtension(this SchemaOptions schemaOptions, Type fieldOwnerType, string fieldName, string unionName, Delegate resolverMethod = null) { var field = MapTypeExtensionInternal( schemaOptions, @@ -173,6 +186,20 @@ public static IGraphQLRuntimeTypeExtensionDefinition MapField(this SchemaOptions fieldName, FieldResolutionMode.PerSourceItem); + if (!string.IsNullOrWhiteSpace(unionName)) + { + var unionAttrib = field.Attributes.OfType().SingleOrDefault(); + if (unionAttrib != null) + { + unionAttrib.UnionName = unionName?.Trim(); + unionAttrib.UnionMemberTypes.Clear(); + } + else + { + field.AddAttribute(new UnionAttribute(unionName.Trim())); + } + } + if (resolverMethod != null) field = field.AddResolver(resolverMethod); @@ -235,5 +262,81 @@ public static IGraphQLRuntimeTypeExtensionDefinition WithName(this IGraphQLRunti fieldBuilder.InternalName = internalName; return fieldBuilder; } + + /// + /// Adds policy-based authorization requirements to the field. + /// + /// + /// This is similar to adding the to a controller method + /// + /// The field being built. + /// The name of the policy to assign via this requirement. + /// A comma-seperated list of roles to assign via this requirement. + /// IGraphQLFieldBuilder. + public static IGraphQLRuntimeTypeExtensionDefinition RequireAuthorization( + this IGraphQLRuntimeTypeExtensionDefinition fieldBuilder, + string policyName = null, + string roles = null) + { + Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); + + var attrib = new AuthorizeAttribute(); + attrib.Policy = policyName?.Trim(); + attrib.Roles = roles?.Trim(); + fieldBuilder.AddAttribute(attrib); + return fieldBuilder; + } + + /// + /// Indicates that the field should allow anonymous access. + /// + /// + /// This is similar to adding the to a controller method + /// + /// The field being built. + /// IGraphQLFieldBuilder. + public static IGraphQLRuntimeTypeExtensionDefinition AllowAnonymous(this IGraphQLRuntimeTypeExtensionDefinition fieldBuilder) + { + Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); + fieldBuilder.AddAttribute(new AllowAnonymousAttribute()); + return fieldBuilder; + } + + /// + /// Sets the resolver to be used when this field is requested at runtime. + /// + /// + /// If this method is called more than once the previously set resolver will be replaced. + /// + /// The field being built. + /// The delegate to assign as the resolver. This method will be + /// parsed to determine input arguments for the field on the target schema. + /// IGraphQLFieldBuilder. + public static IGraphQLRuntimeTypeExtensionDefinition AddResolver(this IGraphQLRuntimeTypeExtensionDefinition fieldBuilder, Delegate resolverMethod) + { + fieldBuilder.Resolver = resolverMethod; + fieldBuilder.ReturnType = null; + + return fieldBuilder; + } + + /// + /// Sets the resolver to be used when this field is requested at runtime. + /// + /// + /// If this method is called more than once the previously set resolver will be replaced. + /// + /// The expected, primary return type of the field. Must be provided + /// if the supplied delegate returns an . + /// The field being built. + /// The delegate to assign as the resolver. This method will be + /// parsed to determine input arguments for the field on the target schema. + /// IGraphQLFieldBuilder. + public static IGraphQLRuntimeTypeExtensionDefinition AddResolver(this IGraphQLRuntimeTypeExtensionDefinition fieldBuilder, Delegate resolverMethod) + { + fieldBuilder.Resolver = resolverMethod; + fieldBuilder.ReturnType = typeof(TReturnType); + return fieldBuilder; + } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeSchemaItemDefinition.cs b/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeSchemaItemDefinition.cs index 898162ed3..3d1a08356 100644 --- a/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeSchemaItemDefinition.cs +++ b/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeSchemaItemDefinition.cs @@ -26,6 +26,12 @@ public interface IGraphQLRuntimeSchemaItemDefinition /// The attribute to append. void AddAttribute(Attribute attrib); + /// + /// Removes the specified attribute from the collection. + /// + /// The attribute to remove. + void RemoveAttribute(Attribute attrib); + /// /// Gets the templated name that will be given to the item on the target schema. /// diff --git a/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/BaseRuntimeControllerActionDefinition.cs b/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/BaseRuntimeControllerActionDefinition.cs index 2fb421f94..e3b24266f 100644 --- a/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/BaseRuntimeControllerActionDefinition.cs +++ b/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/BaseRuntimeControllerActionDefinition.cs @@ -101,6 +101,13 @@ public virtual void AddAttribute(Attribute attrib) /// The primary attribute. protected abstract Attribute CreatePrimaryAttribute(); + /// + public void RemoveAttribute(Attribute attrib) + { + Validation.ThrowIfNull(attrib, nameof(attrib)); + this.AppendedAttributes.Remove(attrib); + } + /// public virtual IEnumerable Attributes { diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphFieldTemplateBase.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphFieldTemplateBase.cs index e8940f538..ff6fb3f24 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphFieldTemplateBase.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphFieldTemplateBase.cs @@ -444,9 +444,6 @@ protected virtual IEnumerable GatherAllPossibleReturnedDataTypes() var unionAttribute = this.AttributeProvider.SingleAttributeOfTypeOrDefault(); if (unionAttribute != null) { - if (unionAttribute.UnionProxyType != null) - yield return unionAttribute.UnionProxyType; - if (unionAttribute.UnionMemberTypes != null) { foreach (var type in unionAttribute.UnionMemberTypes) diff --git a/src/styles.ruleset b/src/styles.ruleset index 4084807a6..34a6cfa64 100644 --- a/src/styles.ruleset +++ b/src/styles.ruleset @@ -7,72 +7,72 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -80,59 +80,64 @@ - - - - - - - + + + + + + + + + + - - - + + + - - - - - + + + + + - - - - - + + + + + - + - + - - - - - - - - - - + + + + + + + + + + - - - + + + + + - - + + - + - - + + \ No newline at end of file diff --git a/src/styles.ruleset.original b/src/styles.ruleset.original new file mode 100644 index 000000000..4084807a6 --- /dev/null +++ b/src/styles.ruleset.original @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeTypeExtensionTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeTypeExtensionTests.cs index bbc51ebbc..da69f9c59 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeTypeExtensionTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeTypeExtensionTests.cs @@ -35,7 +35,7 @@ public async Task TypeExtension_OfObject_ResolvesDuringExecution() { o.AddController(); - o.MapField("Property3", (TwoPropertyObject source) => + o.MapTypeExtension("Property3", (TwoPropertyObject source) => { return $"{source.Property1}-{source.Property2}"; }); @@ -67,7 +67,7 @@ public void TypeExtension_OfObject_WithMetaNameField_ThrowsDeclarationException( { o.AddController(); - o.MapField("[Action]", (TwoPropertyObject source) => + o.MapTypeExtension("[Action]", (TwoPropertyObject source) => { return $"{source.Property1}-{source.Property2}"; }); @@ -90,7 +90,7 @@ public async Task TypeExtension_NoSourceParameterDeclared_ResolvesCorrectly() { o.AddController(); - o.MapField("property5", (int argument) => + o.MapTypeExtension("property5", (int argument) => { return argument; }); @@ -121,7 +121,7 @@ public async Task TypeExtension_OfStruct_ResolvesDuringExecution() { o.AddController(); - o.MapField("Property3", (TwoPropertyStruct source) => + o.MapTypeExtension("Property3", (TwoPropertyStruct source) => { return $"{source.Property1}-{source.Property2}"; }); @@ -153,7 +153,7 @@ public async Task BatchExtension_OfObject_ResolvesDuringExecution() { o.AddController(); - o.MapField("Property4") + o.MapTypeExtension("Property4") .WithBatchProcessing() .AddResolver((IEnumerable source) => { @@ -202,7 +202,7 @@ public async Task BatchExtension_OfStructs_ResolvesDuringExecution() { o.AddController(); - o.MapField("Property4") + o.MapTypeExtension("Property4") .WithBatchProcessing() .AddResolver((IEnumerable source) => { @@ -250,7 +250,7 @@ public async Task BatchExtension_OfObject_ThatUsesStartBatch_ResolvesDuringExecu { o.AddController(); - o.MapField("Property5") + o.MapTypeExtension("Property5") .WithBatchProcessing() .AddPossibleTypes(typeof(ChildObject)) .AddResolver((IEnumerable source) => @@ -310,7 +310,7 @@ public async Task Runtime_TypeExtension_WithSecurityParams_AndAllowedUser_Resolv { o.AddController(); - o.MapField("Property3", (TwoPropertyStruct source) => + o.MapTypeExtension("Property3", (TwoPropertyStruct source) => { return $"{source.Property1}-{source.Property2}"; }) @@ -349,7 +349,7 @@ public async Task Runtime_ExecutionDirective_WithSecurityParams_AndUnAuthenticat { o.AddController(); - o.MapField("Property3", (TwoPropertyStruct source) => + o.MapTypeExtension("Property3", (TwoPropertyStruct source) => { return $"{source.Property1}-{source.Property2}"; }) @@ -379,7 +379,7 @@ public async Task Runtime_ExecutionDirective_WithSecurityParams_AndUnAuthorizedU { o.AddController(); - o.MapField("Property3", (TwoPropertyStruct source) => + o.MapTypeExtension("Property3", (TwoPropertyStruct source) => { return $"{source.Property1}-{source.Property2}"; }) diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedMutationTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedMutationTemplateTests.cs index ef917d347..2dd33b746 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedMutationTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedMutationTemplateTests.cs @@ -65,5 +65,44 @@ public void MapMutation_FromBuilder_WithDelegate_DoesAddFieldToSchema() var mutationRootAttrib = field.Attributes.FirstOrDefault(x => x.GetType() == typeof(MutationRootAttribute)); Assert.IsNotNull(mutationRootAttrib); } + + [Test] + public void MapMutation_WithUnionNameSetToNull_AddsUnionNameToType() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var typeExt = options.MapMutation("myField", null, (string a) => 1); + + var attrib = typeExt.Attributes.OfType().SingleOrDefault(); + + Assert.IsNull(attrib); + } + + [Test] + public void MapMutation_WithUnionName0_AddsUnionNameToType() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var typeExt = options.MapMutation("myField", "myUnion", (string a) => 1); + + var attrib = typeExt.Attributes.OfType().SingleOrDefault(); + + Assert.AreEqual("myUnion", attrib.UnionName); + } + + [Test] + public void MapMutation_WithUnionName1_AddsUnionNameToType() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var typeExt = options.MapMutation("myField", "myUnion"); + + var attrib = typeExt.Attributes.OfType().SingleOrDefault(); + + Assert.AreEqual("myUnion", attrib.UnionName); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedQueryTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedQueryTemplateTests.cs index ad8e4ba6a..62715c45e 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedQueryTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedQueryTemplateTests.cs @@ -17,6 +17,7 @@ namespace GraphQL.AspNet.Tests.Schemas.Generation.RuntimeFieldDeclarations using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Tests.Framework; + using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.DependencyInjection; using Moq; using NUnit.Framework; @@ -66,5 +67,44 @@ public void MapQuery_FromBuilder_WithDelegate_DoesAddFieldToSchema() var queryRootAttrib = field.Attributes.FirstOrDefault(x => x.GetType() == typeof(QueryRootAttribute)); Assert.IsNotNull(queryRootAttrib); } + + [Test] + public void MapQuery_WithUnionNameSetToNull_AddsUnionNameToType() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var typeExt = options.MapQuery("myField", null, (string a) => 1); + + var attrib = typeExt.Attributes.OfType().SingleOrDefault(); + + Assert.IsNull(attrib); + } + + [Test] + public void MapQuery_WithUnionName0_AddsUnionNameToType() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var typeExt = options.MapQuery("myField", "myUnion", (string a) => 1); + + var attrib = typeExt.Attributes.OfType().SingleOrDefault(); + + Assert.AreEqual("myUnion", attrib.UnionName); + } + + [Test] + public void MapQuery_WithUnionName1_AddsUnionNameToType() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var typeExt = options.MapQuery("myField", "myUnion"); + + var attrib = typeExt.Attributes.OfType().SingleOrDefault(); + + Assert.AreEqual("myUnion", attrib.UnionName); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedTypeExtensionTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedTypeExtensionTemplateTests.cs index e380ab025..3b222f663 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedTypeExtensionTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedTypeExtensionTemplateTests.cs @@ -31,7 +31,7 @@ public void MapTypeExtension_ByOptions_AddsTypeExtensionToOptions() var services = new ServiceCollection(); var options = new SchemaOptions(services); - var typeExt = options.MapField("myField"); + var typeExt = options.MapTypeExtension("myField"); Assert.IsInstanceOf(typeof(IGraphQLRuntimeTypeExtensionDefinition), typeExt); Assert.AreEqual(1, options.RuntimeTemplates.Count()); @@ -56,7 +56,7 @@ public void MapTypeExtension_WithName_AddsInternalName() var builderMock = new Mock(); builderMock.Setup(x => x.Options).Returns(options); - var typeExt = options.MapField("myField") + var typeExt = options.MapTypeExtension("myField") .WithName("internalFieldName"); Assert.AreEqual("internalFieldName", typeExt.InternalName); @@ -71,7 +71,7 @@ public void MapTypeExtension_ByBuilder_AddsTypeExtensionToOptions() var builderMock = new Mock(); builderMock.Setup(x => x.Options).Returns(options); - var typeExt = options.MapField("myField"); + var typeExt = options.MapTypeExtension("myField"); Assert.IsInstanceOf(typeof(IGraphQLRuntimeTypeExtensionDefinition), typeExt); Assert.AreEqual(1, options.RuntimeTemplates.Count()); @@ -85,7 +85,7 @@ public void MapTypeExtension_ByOptions_WithResolver_AddsTypeExtensionToOptions() var services = new ServiceCollection(); var options = new SchemaOptions(services); - var typeExt = options.MapField("myField", (string a) => 1); + var typeExt = options.MapTypeExtension("myField", (string a) => 1); Assert.IsInstanceOf(typeof(IGraphQLRuntimeTypeExtensionDefinition), typeExt); Assert.AreEqual(1, options.RuntimeTemplates.Count()); @@ -104,7 +104,7 @@ public void MapTypeExtension_ByBuilder_WithResolver_AddsTypeExtensionToOptions() var builderMock = new Mock(); builderMock.Setup(x => x.Options).Returns(options); - var typeExt = options.MapField("myField", (string a) => 1); + var typeExt = options.MapTypeExtension("myField", (string a) => 1); Assert.IsInstanceOf(typeof(IGraphQLRuntimeTypeExtensionDefinition), typeExt); Assert.AreEqual(1, options.RuntimeTemplates.Count()); @@ -119,7 +119,7 @@ public void MappedTypeExtension_WhenAllowAnonymousAdded_AddsAnonymousAttribute() var services = new ServiceCollection(); var options = new SchemaOptions(services); - var typeExt = options.MapField("myField", (string a) => 1); + var typeExt = options.MapTypeExtension("myField", (string a) => 1); typeExt.AllowAnonymous(); @@ -133,7 +133,7 @@ public void MappedTypeExtension_WhenRequireAuthAdded_AddsAuthAttribute() var services = new ServiceCollection(); var options = new SchemaOptions(services); - var typeExt = options.MapField("myField", (string a) => 1); + var typeExt = options.MapTypeExtension("myField", (string a) => 1); typeExt.RequireAuthorization("policy1", "roles1"); @@ -150,7 +150,7 @@ public void MappedTypeExtension_WhenResolverIsChangedWithExplicitType_NewResolve var services = new ServiceCollection(); var options = new SchemaOptions(services); - var typeExt = options.MapField("myField", (string a) => 1); + var typeExt = options.MapTypeExtension("myField", (string a) => 1); Assert.AreEqual(typeof(int), typeExt.Resolver.Method.ReturnType); typeExt.AddResolver((string a) => "bob"); @@ -164,7 +164,7 @@ public void MappedTypeExtension_WithBatchProcessing_ChangesExecutionMode() var services = new ServiceCollection(); var options = new SchemaOptions(services); - var typeExt = options.MapField("myField", (string a) => 1); + var typeExt = options.MapTypeExtension("myField", (string a) => 1); Assert.AreEqual(FieldResolutionMode.PerSourceItem, typeExt.ExecutionMode); typeExt.WithBatchProcessing(); @@ -180,7 +180,7 @@ public void MappedTypeExtension_AddPossibleTypes_AddsAppropriateAttribute() var services = new ServiceCollection(); var options = new SchemaOptions(services); - var typeExt = options.MapField("myField", (string a) => 1); + var typeExt = options.MapTypeExtension("myField", (string a) => 1); typeExt.AddPossibleTypes(typeof(TwoPropertyObjectV2), typeof(TwoPropertyObjectV3)); Assert.AreEqual(2, typeExt.Attributes.Count()); @@ -190,5 +190,44 @@ public void MappedTypeExtension_AddPossibleTypes_AddsAppropriateAttribute() Assert.IsNotNull(attrib.PossibleTypes.FirstOrDefault(x => x == typeof(TwoPropertyObjectV2))); Assert.IsNotNull(attrib.PossibleTypes.FirstOrDefault(x => x == typeof(TwoPropertyObjectV3))); } + + [Test] + public void MappedTypeExtension_WithoutUnionName_AddsUnionNameToType() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var typeExt = options.MapTypeExtension("myField", null, (string a) => 1); + + var attrib = typeExt.Attributes.OfType().SingleOrDefault(); + + Assert.IsNull(attrib); + } + + [Test] + public void MappedTypeExtension_WithUnionName0_AddsUnionNameToType() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var typeExt = options.MapTypeExtension("myField", "myUnion", (string a) => 1); + + var attrib = typeExt.Attributes.OfType().SingleOrDefault(); + + Assert.AreEqual("myUnion", attrib.UnionName); + } + + [Test] + public void MappedTypeExtension_WithUnionName1_AddsUnionNameToType() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var typeExt = options.MapTypeExtension("myField", "myUnion"); + + var attrib = typeExt.Attributes.OfType().SingleOrDefault(); + + Assert.AreEqual("myUnion", attrib.UnionName); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/ObjectGraphTypeMakerTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/ObjectGraphTypeMakerTests.cs index 107ec5f09..83eda91ae 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/ObjectGraphTypeMakerTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/ObjectGraphTypeMakerTests.cs @@ -11,11 +11,9 @@ namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers { using System.Linq; using GraphQL.AspNet.Configuration; - using GraphQL.AspNet.Engine; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Schemas; - using GraphQL.AspNet.Schemas.Generation; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.CommonHelpers; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/RuntimeFieldsGeneralTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/RuntimeFieldsGeneralTests.cs new file mode 100644 index 000000000..7cba10b84 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/RuntimeFieldsGeneralTests.cs @@ -0,0 +1,87 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas +{ + using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Controllers.ActionResults; + using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + using GraphQL.AspNet.Tests.Framework; + using NUnit.Framework; + + [TestFixture] + public class RuntimeFieldsGeneralTests + { + [Test] + public void InternalName_OnQueryField_IssCarriedToSchema() + { + var server = new TestServerBuilder() + .AddGraphQL(o => + { + o.MapQuery("field1", () => 1) + .WithName("field1_internal_name"); + }) + .Build(); + + var operation = server.Schema.Operations[GraphOperationType.Query]; + var field = operation.Fields.FindField("field1"); + Assert.AreEqual("field1_internal_name", field.InternalName); + } + + [Test] + public void InternalName_OnMutationField_IssCarriedToSchema() + { + var server = new TestServerBuilder() + .AddGraphQL(o => + { + o.MapMutation("field1", () => 1) + .WithName("field1_internal_name"); + }) + .Build(); + + var operation = server.Schema.Operations[GraphOperationType.Mutation]; + var field = operation.Fields.FindField("field1"); + Assert.AreEqual("field1_internal_name", field.InternalName); + } + + [Test] + public void InternalName_OnTypeExension_IssCarriedToSchema() + { + var server = new TestServerBuilder() + .AddGraphQL(o => + { + o.AddType(); + o.MapTypeExtension("field1", () => 1) + .WithName("extension_field_Internal_Name"); + }) + .Build(); + + var obj = server.Schema.KnownTypes.FindGraphType(typeof(TwoPropertyObject)) as IObjectGraphType; + var field = obj.Fields.FindField("field1"); + Assert.AreEqual("extension_field_Internal_Name", field.InternalName); + } + + [Test] + public void InternalName_OnDirective_IsCarriedToSchema() + { + var server = new TestServerBuilder() + .AddGraphQL(o => + { + o.MapDirective("@myDirective", () => GraphActionResult.Ok()) + .WithName("directive_internal_name"); + }) + .Build(); + + var dir = server.Schema.KnownTypes.FindDirective("myDirective"); + Assert.AreEqual("directive_internal_name", dir.InternalName); + } + } +} \ No newline at end of file From d2762a331646ea911fdf2e3cc55b39af97d01a63 Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Mon, 24 Jul 2023 16:18:08 -0700 Subject: [PATCH 50/63] WIP --- src/styles.ruleset | 211 ++++++++++++++++++------------------ src/styles.ruleset.original | 138 ----------------------- 2 files changed, 103 insertions(+), 246 deletions(-) delete mode 100644 src/styles.ruleset.original diff --git a/src/styles.ruleset b/src/styles.ruleset index 34a6cfa64..4084807a6 100644 --- a/src/styles.ruleset +++ b/src/styles.ruleset @@ -7,72 +7,72 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -80,64 +80,59 @@ - - - - - - - - - - + + + + + + + - - - + + + - - - - - + + + + + - - - - - + + + + + - + - + - - - - - - - - - - + + + + + + + + + + - - - - - + + + - - + + - + - - + + \ No newline at end of file diff --git a/src/styles.ruleset.original b/src/styles.ruleset.original deleted file mode 100644 index 4084807a6..000000000 --- a/src/styles.ruleset.original +++ /dev/null @@ -1,138 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file From d37f6455f708cb8f4cca43fa8133ccce6422bb83 Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Mon, 24 Jul 2023 17:26:05 -0700 Subject: [PATCH 51/63] WIP, centralized minimal api overloads to reduce regressions --- .../Attributes/UnionAttribute.cs | 11 +- ...hemaItemDefinitionExtensions_Directives.cs | 95 ++++----- ...chemaItemDefinitionExtensions_Internals.cs | 31 --- ...chemaItemDefinitionExtensions_Mutations.cs | 57 +---- ...eSchemaItemDefinitionExtensions_Queries.cs | 58 +----- ...ItemDefinitionExtensions_ResolvedFields.cs | 197 ++++++++++-------- ...ItemDefinitionExtensions_TypeExtensions.cs | 174 ++++++++++++++-- ...aItemDefinitionExtensions_VirtualFields.cs | 92 +++++++- .../Execution/RuntimeDirectiveTests.cs | 22 +- .../MappedDirectiveTemplateTests.cs | 4 +- .../MappedMutationGroupTests.cs | 4 +- .../MappedMutationTemplateTests.cs | 13 -- .../MappedQueryGroupTests.cs | 4 +- .../MappedQueryTemplateTests.cs | 13 -- .../MappedTypeExtensionTemplateTests.cs | 11 +- .../ResolvedFieldTemplateTests.cs | 14 ++ 16 files changed, 462 insertions(+), 338 deletions(-) diff --git a/src/graphql-aspnet/Attributes/UnionAttribute.cs b/src/graphql-aspnet/Attributes/UnionAttribute.cs index c6d1e372a..c8bddae20 100644 --- a/src/graphql-aspnet/Attributes/UnionAttribute.cs +++ b/src/graphql-aspnet/Attributes/UnionAttribute.cs @@ -57,7 +57,7 @@ public UnionAttribute(Type unionProxyType) { this.UnionName = null; if (unionProxyType != null) - this.UnionMemberTypes = new List() { unionProxyType }; + this.UnionMemberTypes.Add(unionProxyType); } /// @@ -65,10 +65,19 @@ public UnionAttribute(Type unionProxyType) /// /// The name to assign to this union. public UnionAttribute(string unionName) + : this() { this.UnionName = unionName; } + /// + /// Prevents a default instance of the class from being created. + /// + private UnionAttribute() + { + this.UnionMemberTypes = new List(); + } + /// /// Gets or sets the name of the new union to create within the schema. This union name must be a valid graph name. /// diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Directives.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Directives.cs index cf8509d61..771c46963 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Directives.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Directives.cs @@ -10,11 +10,14 @@ namespace GraphQL.AspNet.Configuration { using System; + using System.Linq; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Common; + using GraphQL.AspNet.Execution.Parsing.Lexing.Tokens; using GraphQL.AspNet.Interfaces.Configuration; using GraphQL.AspNet.Interfaces.Controllers; using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; + using GraphQL.AspNet.Schemas.Generation.RuntimeSchemaItemDefinitions; using GraphQL.AspNet.Schemas.TypeSystem; using Microsoft.AspNetCore.Authorization; @@ -64,20 +67,29 @@ public static IGraphQLRuntimeDirectiveDefinition RequireAuthorization( public static IGraphQLRuntimeDirectiveDefinition AllowAnonymous(this IGraphQLRuntimeDirectiveDefinition directiveTemplate) { Validation.ThrowIfNull(directiveTemplate, nameof(directiveTemplate)); - directiveTemplate.AddAttribute(new AllowAnonymousAttribute()); + if (directiveTemplate.Attributes.Count(x => x is AllowAnonymousAttribute) == 0) + { + directiveTemplate.AddAttribute(new AllowAnonymousAttribute()); + } + return directiveTemplate; } /// - /// Marks this directive as being repeatable such that it can be applie to a single + /// Marks this directive as being repeatable such that it can be applied to a single /// schema item more than once. /// /// The directive template. /// IGraphQLRuntimeDirectiveDefinition. public static IGraphQLRuntimeDirectiveDefinition IsRepeatable(this IGraphQLRuntimeDirectiveDefinition directiveTemplate) { - var repeatable = new RepeatableAttribute(); - directiveTemplate.AddAttribute(repeatable); + Validation.ThrowIfNull(directiveTemplate, nameof(directiveTemplate)); + if (directiveTemplate.Attributes.Count(x => x is RepeatableAttribute) == 0) + { + var repeatable = new RepeatableAttribute(); + directiveTemplate.AddAttribute(repeatable); + } + return directiveTemplate; } @@ -96,6 +108,7 @@ public static IGraphQLRuntimeDirectiveDefinition RestrictLocations( this IGraphQLRuntimeDirectiveDefinition directiveTemplate, DirectiveLocation locations) { + Validation.ThrowIfNull(directiveTemplate, nameof(directiveTemplate)); var restrictions = new DirectiveLocationsAttribute(locations); directiveTemplate.AddAttribute(restrictions); @@ -119,31 +132,13 @@ public static IGraphQLRuntimeDirectiveDefinition RestrictLocations( /// IGraphQLRuntimeDirectiveDefinition. public static IGraphQLRuntimeDirectiveDefinition AddResolver(this IGraphQLRuntimeDirectiveDefinition directiveTemplate, Delegate resolverMethod) { + Validation.ThrowIfNull(directiveTemplate, nameof(directiveTemplate)); directiveTemplate.Resolver = resolverMethod; directiveTemplate.ReturnType = null; return directiveTemplate; } - /// - /// Sets the resolver to be used when this directive is requested at runtime. - /// - /// - /// If this method is called more than once the previously set resolver will be replaced. - /// - /// The expected, primary return type of the directive. Must be provided - /// if the supplied delegate returns an . - /// The directive being built. - /// The delegate to assign as the resolver. This method will be - /// parsed to determine input arguments for the directive on the target schema. - /// IGraphQLRuntimeDirectiveDefinition. - public static IGraphQLRuntimeDirectiveDefinition AddResolver(this IGraphQLRuntimeDirectiveDefinition directiveTemplate, Delegate resolverMethod) - { - directiveTemplate.Resolver = resolverMethod; - directiveTemplate.ReturnType = typeof(TReturnType); - return directiveTemplate; - } - /// /// Assigns a custom value to the internal name of this directive. This value will be used in error /// messages and log entries instead of an anonymous method name. This can significantly increase readability @@ -159,6 +154,7 @@ public static IGraphQLRuntimeDirectiveDefinition AddResolver(this I /// IGraphQLRuntimeDirectiveDefinition. public static IGraphQLRuntimeDirectiveDefinition WithName(this IGraphQLRuntimeDirectiveDefinition directiveTemplate, string internalName) { + Validation.ThrowIfNull(directiveTemplate, nameof(directiveTemplate)); directiveTemplate.InternalName = internalName; return directiveTemplate; } @@ -166,63 +162,60 @@ public static IGraphQLRuntimeDirectiveDefinition WithName(this IGraphQLRuntimeDi /// /// Maps a new directive into the target schema. /// - /// The schema options where the directive will be created. + /// The builder representing the schema being constructed. /// Name of the directive (e.g. '@myDirective'). /// IGraphQLRuntimeDirectiveDefinition. - public static IGraphQLRuntimeDirectiveDefinition MapDirective(this SchemaOptions schemaOptions, string directiveName) + public static IGraphQLRuntimeDirectiveDefinition MapDirective(this ISchemaBuilder schemaBuilder, string directiveName) { - return MapDirectiveInternal(schemaOptions, directiveName); + Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); + return MapDirective(schemaBuilder.Options, directiveName, null as Delegate); } /// /// Maps a new directive into the target schema. /// - /// The schema options where the directive will be created. + /// The builder representing the schema being constructed. /// Name of the directive (e.g. '@myDirective'). /// The resolver that will be executed when the directive is invoked. - /// IGraphQLRuntimeDirectiveDefinition. - public static IGraphQLRuntimeDirectiveDefinition MapDirective(this SchemaOptions schemaOptions, string directiveName, Delegate resolverMethod) + /// IGraphQLDirectiveTemplate. + public static IGraphQLRuntimeDirectiveDefinition MapDirective(this ISchemaBuilder schemaBuilder, string directiveName, Delegate resolverMethod) { - Validation.ThrowIfNull(resolverMethod, nameof(resolverMethod)); - - var directive = MapDirectiveInternal(schemaOptions, directiveName); - return directive.AddResolver(resolverMethod); + Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); + return MapDirective(schemaBuilder.Options, directiveName, resolverMethod); } /// /// Maps a new directive into the target schema. /// - /// The builder representing the schema being constructed. + /// The schema options where the directive will be created. /// Name of the directive (e.g. '@myDirective'). /// IGraphQLRuntimeDirectiveDefinition. - public static IGraphQLRuntimeDirectiveDefinition MapDirective(this ISchemaBuilder schemaBuilder, string directiveName) + public static IGraphQLRuntimeDirectiveDefinition MapDirective(this SchemaOptions schemaOptions, string directiveName) { - Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); - - var directive = MapDirectiveInternal( - schemaBuilder.Options, - directiveName); - - return directive; + return MapDirective(schemaOptions, directiveName, null as Delegate); } /// /// Maps a new directive into the target schema. /// - /// The builder representing the schema being constructed. + /// The schema options where the directive will be created. /// Name of the directive (e.g. '@myDirective'). /// The resolver that will be executed when the directive is invoked. - /// IGraphQLDirectiveTemplate. - public static IGraphQLRuntimeDirectiveDefinition MapDirective(this ISchemaBuilder schemaBuilder, string directiveName, Delegate resolverMethod) + /// IGraphQLRuntimeDirectiveDefinition. + public static IGraphQLRuntimeDirectiveDefinition MapDirective(this SchemaOptions schemaOptions, string directiveName, Delegate resolverMethod) { - Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); - Validation.ThrowIfNull(resolverMethod, nameof(resolverMethod)); + Validation.ThrowIfNull(schemaOptions, nameof(schemaOptions)); - var directive = MapDirectiveInternal( - schemaBuilder.Options, - directiveName); + while (directiveName != null && directiveName.StartsWith(TokenTypeNames.STRING_AT_SYMBOL)) + directiveName = directiveName.Substring(1); - return directive.AddResolver(resolverMethod); + var directive = new RuntimeDirectiveActionDefinition(schemaOptions, directiveName); + schemaOptions.AddRuntimeSchemaItem(directive); + + if (resolverMethod != null) + directive.AddResolver(resolverMethod); + + return directive; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Internals.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Internals.cs index 2efaf2bd8..60d33fdc2 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Internals.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Internals.cs @@ -56,36 +56,5 @@ private static IGraphQLRuntimeTypeExtensionDefinition MapTypeExtensionInternal( schemaOptions.AddRuntimeSchemaItem(field); return field; } - - private static IGraphQLRuntimeDirectiveDefinition MapDirectiveInternal( - this SchemaOptions schemaOptions, - string directiveName) - { - while (directiveName != null && directiveName.StartsWith(TokenTypeNames.STRING_AT_SYMBOL)) - directiveName = directiveName.Substring(1); - - var directive = new RuntimeDirectiveActionDefinition(schemaOptions, directiveName); - schemaOptions.AddRuntimeSchemaItem(directive); - return directive; - } - - /// - /// Convert a virtual field to a resolvable fields and assigns the given resolver. - /// - /// The field being built. - /// The delegate to assign as the resolver. This method will be - /// parsed to determine input arguments for the field on the target schema. - /// IGraphQLFieldBuilder. - private static IGraphQLRuntimeResolvedFieldDefinition AddResolver(this IGraphQLRuntimeFieldDefinition field, Delegate resolverMethod) - { - // convert the virtual field to a resolved field - var resolvedBuilder = RuntimeResolvedFieldDefinition.FromFieldTemplate(field); - resolvedBuilder.Options.AddRuntimeSchemaItem(resolvedBuilder); - - resolvedBuilder.Resolver = resolverMethod; - resolvedBuilder.ReturnType = null; - - return resolvedBuilder; - } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Mutations.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Mutations.cs index 599cc709b..5e75271b8 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Mutations.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Mutations.cs @@ -15,6 +15,7 @@ namespace GraphQL.AspNet.Configuration using GraphQL.AspNet.Common; using GraphQL.AspNet.Interfaces.Configuration; using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; + using GraphQL.AspNet.Schemas.Generation.RuntimeSchemaItemDefinitions; using GraphQL.AspNet.Schemas.TypeSystem; /// @@ -61,26 +62,6 @@ public static IGraphQLRuntimeResolvedFieldDefinition MapMutation(this ISchemaBui resolverMethod); } - /// - /// Creates a new, explicitly resolvable field in the mutation root object with the given path. This field cannot be - /// further extended or nested with other fields via the Mapping API. - /// - /// The builder representing the schema where this field - /// will be created. - /// The template path string for his field. (e.g. /path1/path2/path3) - /// Provide a name and this field will be declared to return a union. Use to declare union members. - /// IGraphQLFieldTemplate. - public static IGraphQLRuntimeResolvedFieldDefinition MapMutation(this ISchemaBuilder schemaBuilder, string template, string unionName) - { - Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); - - return MapMutation( - schemaBuilder.Options, - template, - unionName, // unionName - null as Delegate); - } - /// /// Creates a new field in the mutation object with the given path. This field can act as a /// grouping field of other resolvable fields or be converted to an explicitly resolvable field itself. @@ -139,24 +120,6 @@ public static IGraphQLRuntimeResolvedFieldDefinition MapMutation(this SchemaOpti resolverMethod); } - /// - /// Creates a new field in the Mutation root object with the given path. This field can act as a - /// grouping field of other resolvable fields or be converted to an explicitly resolvable field itself. - /// - /// The options representing the schema where this field - /// will be created. - /// The template path string for his field. (e.g. /path1/path2/path3) - /// Provide a name and this field will be declared to return a union. Use to declare union members. - /// IGraphQLFieldTemplate. - public static IGraphQLRuntimeResolvedFieldDefinition MapMutation(this SchemaOptions schemaOptions, string template, string unionName) - { - return MapMutation( - schemaOptions, - template, - unionName, // unionName - null as Delegate); - } - /// /// Creates a new, explicitly resolvable field in the Mutation root object with the given path. This field cannot be /// further extended or nested with other fields via the Mapping API. @@ -177,21 +140,13 @@ public static IGraphQLRuntimeResolvedFieldDefinition MapMutation(this SchemaOpti GraphOperationType.Mutation, template); + var resolvedField = RuntimeResolvedFieldDefinition.FromFieldTemplate(field); + schemaOptions.AddRuntimeSchemaItem(resolvedField); + if (!string.IsNullOrWhiteSpace(unionName)) - { - var unionAttrib = field.Attributes.OfType().SingleOrDefault(); - if (unionAttrib != null) - { - unionAttrib.UnionName = unionName.Trim(); - unionAttrib.UnionMemberTypes.Clear(); - } - else - { - field.AddAttribute(new UnionAttribute(unionName.Trim())); - } - } + resolvedField.AddAttribute(new UnionAttribute(unionName.Trim())); - return field.AddResolver(resolverMethod); + return resolvedField.AddResolver(unionName, resolverMethod); } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Queries.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Queries.cs index 9a2ce4a4a..f5302dda9 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Queries.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Queries.cs @@ -15,7 +15,9 @@ namespace GraphQL.AspNet.Configuration using GraphQL.AspNet.Common; using GraphQL.AspNet.Interfaces.Configuration; using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; + using GraphQL.AspNet.Schemas.Generation.RuntimeSchemaItemDefinitions; using GraphQL.AspNet.Schemas.TypeSystem; + using Microsoft.VisualBasic; /// /// Extension methods for configuring minimal API methods as fields on the graph. @@ -61,26 +63,6 @@ public static IGraphQLRuntimeResolvedFieldDefinition MapQuery(this ISchemaBuilde resolverMethod); } - /// - /// Creates a new, explicitly resolvable field in the query root object with the given path. This field cannot be - /// further extended or nested with other fields via the Mapping API. - /// - /// The builder representing the schema where this field - /// will be created. - /// The template path string for his field. (e.g. /path1/path2/path3) - /// Provide a name and this field will be declared to return a union. Use to declare union members. - /// IGraphQLFieldTemplate. - public static IGraphQLRuntimeResolvedFieldDefinition MapQuery(this ISchemaBuilder schemaBuilder, string template, string unionName) - { - Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); - - return MapQuery( - schemaBuilder.Options, - template, - unionName, // unionName - null as Delegate); - } - /// /// Creates a new field in the query object with the given path. This field can act as a /// grouping field of other resolvable fields or be converted to an explicitly resolvable field itself. @@ -139,24 +121,6 @@ public static IGraphQLRuntimeResolvedFieldDefinition MapQuery(this SchemaOptions resolverMethod); } - /// - /// Creates a new field in the query root object with the given path. This field can act as a - /// grouping field of other resolvable fields or be converted to an explicitly resolvable field itself. - /// - /// The options representing the schema where this field - /// will be created. - /// The template path string for his field. (e.g. /path1/path2/path3) - /// Provide a name and this field will be declared to return a union. Use to declare union members. - /// IGraphQLFieldTemplate. - public static IGraphQLRuntimeResolvedFieldDefinition MapQuery(this SchemaOptions schemaOptions, string template, string unionName) - { - return MapQuery( - schemaOptions, - template, - unionName, // unionName - null as Delegate); - } - /// /// Creates a new, explicitly resolvable field in the query root object with the given path. This field cannot be /// further extended or nested with other fields via the Mapping API. @@ -177,21 +141,13 @@ public static IGraphQLRuntimeResolvedFieldDefinition MapQuery(this SchemaOptions GraphOperationType.Query, template); + var resolvedField = RuntimeResolvedFieldDefinition.FromFieldTemplate(field); + schemaOptions.AddRuntimeSchemaItem(resolvedField); + if (!string.IsNullOrWhiteSpace(unionName)) - { - var unionAttrib = field.Attributes.OfType().SingleOrDefault(); - if (unionAttrib != null) - { - unionAttrib.UnionName = unionName?.Trim(); - unionAttrib.UnionMemberTypes.Clear(); - } - else - { - field.AddAttribute(new UnionAttribute(unionName.Trim())); - } - } + resolvedField.AddAttribute(new UnionAttribute(unionName.Trim())); - return field.AddResolver(resolverMethod); + return resolvedField.AddResolver(unionName, resolverMethod); } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_ResolvedFields.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_ResolvedFields.cs index 8e36e6c1c..a522a5b48 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_ResolvedFields.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_ResolvedFields.cs @@ -63,6 +63,62 @@ public static IGraphQLRuntimeResolvedFieldDefinition AllowAnonymous(this IGraphQ return fieldBuilder; } + /// + /// Adds a set of possible return types for this field. This is synonymous to using the + /// on a controller's action method. + /// + /// + /// This method can be called multiple times. Any new types will be appended to the field. All types added + /// must be coercable to the declared return type of the assigned resolver for this field unless this field returns a union; in + /// which case the types will be added as union members. + /// + /// The field being built. + /// The first possible type that might be returned by this + /// field. + /// Any number of additional possible types that + /// might be returned by this field. + /// IGraphQLFieldBuilder. + public static IGraphQLRuntimeResolvedFieldDefinition AddPossibleTypes(this IGraphQLRuntimeResolvedFieldDefinition fieldBuilder, Type firstPossibleType, params Type[] additionalPossibleTypes) + { + var possibleTypes = new PossibleTypesAttribute(firstPossibleType, additionalPossibleTypes); + fieldBuilder.AddAttribute(possibleTypes); + return fieldBuilder; + } + + /// + /// Clears all extra defined possible types this field may declare. This will not affect the core type defined by the resolver, if + /// a resolver has been defined for this field. + /// + /// The field builder. + /// IGraphQLRuntimeResolvedFieldDefinition. + public static IGraphQLRuntimeResolvedFieldDefinition ClearPossibleTypes(this IGraphQLRuntimeResolvedFieldDefinition fieldBuilder) + { + var attributes = fieldBuilder.Attributes.OfType().ToList(); + foreach (var att in attributes) + fieldBuilder.RemoveAttribute(att); + + return fieldBuilder; + } + + /// + /// Assigns a custom internal name to this field. This value will be used in error + /// messages and log entries instead of an anonymous method name. This can significantly increase readability + /// while trying to debug an issue. This value has no bearing on the runtime use of this field. It is cosmetic only. + /// + /// + /// This value does NOT affect the field name as it would appear in a schema. It only effects the internal + /// name used in log messages and exception text. + /// + /// The field being built. + /// The value to use as the internal name for this field definition when its + /// added to the schema. + /// IGraphQLFieldBuilder. + public static IGraphQLRuntimeResolvedFieldDefinition WithName(this IGraphQLRuntimeResolvedFieldDefinition fieldBuilder, string internalName) + { + fieldBuilder.InternalName = internalName?.Trim(); + return fieldBuilder; + } + /// /// Indicates this field will return a union and sets the resolver to be used when this field is requested at runtime. The provided /// resolver should return a . @@ -77,24 +133,11 @@ public static IGraphQLRuntimeResolvedFieldDefinition AddResolver( string unionName, Delegate resolverMethod) { - fieldBuilder.Resolver = resolverMethod; - fieldBuilder.ReturnType = null; - - if (!string.IsNullOrWhiteSpace(unionName)) - { - var unionAttrib = fieldBuilder.Attributes.OfType().SingleOrDefault(); - if (unionAttrib != null) - { - unionAttrib.UnionName = unionName?.Trim(); - unionAttrib.UnionMemberTypes.Clear(); - } - else - { - fieldBuilder.AddAttribute(new UnionAttribute(unionName.Trim())); - } - } - - return fieldBuilder; + return AddResolver( + fieldBuilder, + null as Type, // return Type + unionName, + resolverMethod); } /// @@ -103,22 +146,20 @@ public static IGraphQLRuntimeResolvedFieldDefinition AddResolver( /// /// If this method is called more than once the previously set resolver will be replaced. /// + /// The expected, primary return type of the field. Must be provided + /// if the supplied delegate returns an . /// The field being built. + /// Provide a name and this field will be declared to return a union. Use to declare union members. /// The delegate to assign as the resolver. This method will be /// parsed to determine input arguments for the field on the target schema. /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeResolvedFieldDefinition AddResolver(this IGraphQLRuntimeResolvedFieldDefinition fieldBuilder, Delegate resolverMethod) + public static IGraphQLRuntimeResolvedFieldDefinition AddResolver(this IGraphQLRuntimeResolvedFieldDefinition fieldBuilder, string unionName, Delegate resolverMethod) { - fieldBuilder.Resolver = resolverMethod; - fieldBuilder.ReturnType = null; - - // since the resolver was declared as non-union, remove any potential union setup that might have - // existed via a previous call. - var unionAttrib = fieldBuilder.Attributes.OfType().SingleOrDefault(); - if (unionAttrib != null) - fieldBuilder.RemoveAttribute(unionAttrib); - - return fieldBuilder; + return AddResolver( + fieldBuilder, + typeof(TReturnType), + unionName, + resolverMethod); } /// @@ -127,80 +168,68 @@ public static IGraphQLRuntimeResolvedFieldDefinition AddResolver(this IGraphQLRu /// /// If this method is called more than once the previously set resolver will be replaced. /// - /// The expected, primary return type of the field. Must be provided - /// if the supplied delegate returns an . /// The field being built. /// The delegate to assign as the resolver. This method will be /// parsed to determine input arguments for the field on the target schema. /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeResolvedFieldDefinition AddResolver(this IGraphQLRuntimeResolvedFieldDefinition fieldBuilder, Delegate resolverMethod) + public static IGraphQLRuntimeResolvedFieldDefinition AddResolver(this IGraphQLRuntimeResolvedFieldDefinition fieldBuilder, Delegate resolverMethod) { - fieldBuilder.Resolver = resolverMethod; - fieldBuilder.ReturnType = typeof(TReturnType); - - // since the resolver was declared as non-union, remove any potential union setup that might have - // existed via a previous call. if TReturnType is a union proxy it will be - // picked up automatically during templating - var unionAttrib = fieldBuilder.Attributes.OfType().SingleOrDefault(); - if (unionAttrib != null) - fieldBuilder.RemoveAttribute(unionAttrib); - - return fieldBuilder; + return AddResolver( + fieldBuilder, + null as Type, // return Type + null, // unionName + resolverMethod); } /// - /// Adds a set of possible return types for this field. This is synonymous to using the - /// on a controller's action method. + /// Sets the resolver to be used when this field is requested at runtime. /// /// - /// This method can be called multiple times. Any new types will be appended to the field. All types added - /// must be coercable to the declared return type of the assigned resolver for this field unless this field returns a union; in - /// which case the types will be added as union members. + /// If this method is called more than once the previously set resolver will be replaced. /// + /// The expected, primary return type of the field. Must be provided + /// if the supplied delegate returns an . /// The field being built. - /// The first possible type that might be returned by this - /// field. - /// Any number of additional possible types that - /// might be returned by this field. + /// The delegate to assign as the resolver. This method will be + /// parsed to determine input arguments for the field on the target schema. /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeResolvedFieldDefinition AddPossibleTypes(this IGraphQLRuntimeResolvedFieldDefinition fieldBuilder, Type firstPossibleType, params Type[] additionalPossibleTypes) + public static IGraphQLRuntimeResolvedFieldDefinition AddResolver(this IGraphQLRuntimeResolvedFieldDefinition fieldBuilder, Delegate resolverMethod) { - var possibleTypes = new PossibleTypesAttribute(firstPossibleType, additionalPossibleTypes); - fieldBuilder.AddAttribute(possibleTypes); - return fieldBuilder; + return AddResolver( + fieldBuilder, + typeof(TReturnType), + null, // unionName + resolverMethod); } - /// - /// Clears all extra defined possible types this field may declare. This will not affect the core type defined by the resolver, if - /// a resolver has been defined for this field. - /// - /// The field builder. - /// IGraphQLRuntimeResolvedFieldDefinition. - public static IGraphQLRuntimeResolvedFieldDefinition ClearPossibleTypes(this IGraphQLRuntimeResolvedFieldDefinition fieldBuilder) + private static IGraphQLRuntimeResolvedFieldDefinition AddResolver( + this IGraphQLRuntimeResolvedFieldDefinition fieldBuilder, + Type expectedReturnType, + string unionName, + Delegate resolverMethod) { - var attributes = fieldBuilder.Attributes.OfType().ToList(); - foreach (var att in attributes) - fieldBuilder.RemoveAttribute(att); + fieldBuilder.Resolver = resolverMethod; + fieldBuilder.ReturnType = expectedReturnType; - return fieldBuilder; - } + // since the resolver was declared as non-union, remove any potential union setup that might have + // existed via a previous call. if TReturnType is a union proxy it will be + // picked up automatically during templating + var unionAttrib = fieldBuilder.Attributes.OfType().SingleOrDefault(); + if (string.IsNullOrEmpty(unionName)) + { + if (unionAttrib != null) + fieldBuilder.RemoveAttribute(unionAttrib); + } + else if (unionAttrib != null) + { + unionAttrib.UnionName = unionName?.Trim(); + unionAttrib.UnionMemberTypes.Clear(); + } + else + { + fieldBuilder.AddAttribute(new UnionAttribute(unionName.Trim())); + } - /// - /// Assigns a custom internal name to this field. This value will be used in error - /// messages and log entries instead of an anonymous method name. This can significantly increase readability - /// while trying to debug an issue. This value has no bearing on the runtime use of this field. It is cosmetic only. - /// - /// - /// This value does NOT affect the field name as it would appear in a schema. It only effects the internal - /// name used in log messages and exception text. - /// - /// The field being built. - /// The value to use as the internal name for this field definition when its - /// added to the schema. - /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeResolvedFieldDefinition WithName(this IGraphQLRuntimeResolvedFieldDefinition fieldBuilder, string internalName) - { - fieldBuilder.InternalName = internalName?.Trim(); return fieldBuilder; } } diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_TypeExtensions.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_TypeExtensions.cs index 868db105a..e8c0ba38c 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_TypeExtensions.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_TypeExtensions.cs @@ -25,6 +25,34 @@ namespace GraphQL.AspNet.Configuration /// public static partial class GraphQLRuntimeSchemaItemDefinitionExtensions { + /// + /// Registers a new type extension to a given OBJECT or INTERFACE type for the target schema. + /// + /// + /// + /// This method is synonymous with using the on + /// a controller action. + /// + /// + /// The supplied resolver must declare a parameter that is of the same type as . + /// + /// + /// The concrete interface, class or struct to extend with a new field. + /// The schema builder to append the field to. + /// Name of the field to add to the . + /// IGraphQLResolvedFieldTemplate. + public static IGraphQLRuntimeTypeExtensionDefinition MapTypeExtension(this ISchemaBuilder builder, string fieldName) + { + Validation.ThrowIfNull(builder, nameof(builder)); + + return MapTypeExtension( + builder.Options, + typeof(TOwnerType), + fieldName, + null, // unionName + null as Delegate); + } + /// /// Registers a new type extension to a given OBJECT or INTERFACE type for the target schema. /// @@ -42,7 +70,7 @@ public static partial class GraphQLRuntimeSchemaItemDefinitionExtensions /// Name of the field to add to the . /// The resolver method to be called when the field is requested. /// IGraphQLResolvedFieldTemplate. - public static IGraphQLRuntimeTypeExtensionDefinition MapTypeExtension(this ISchemaBuilder builder, string fieldName, Delegate resolverMethod = null) + public static IGraphQLRuntimeTypeExtensionDefinition MapTypeExtension(this ISchemaBuilder builder, string fieldName, Delegate resolverMethod) { Validation.ThrowIfNull(builder, nameof(builder)); @@ -72,7 +100,7 @@ public static IGraphQLRuntimeTypeExtensionDefinition MapTypeExtensionProvide a name and this field will be declared to return a union. Use to declare union members. /// The resolver method to be called when the field is requested. /// IGraphQLResolvedFieldTemplate. - public static IGraphQLRuntimeTypeExtensionDefinition MapTypeExtension(this ISchemaBuilder builder, string fieldName, string unionName, Delegate resolverMethod = null) + public static IGraphQLRuntimeTypeExtensionDefinition MapTypeExtension(this ISchemaBuilder builder, string fieldName, string unionName, Delegate resolverMethod) { Validation.ThrowIfNull(builder, nameof(builder)); @@ -84,6 +112,32 @@ public static IGraphQLRuntimeTypeExtensionDefinition MapTypeExtension + /// Registers a new type extension to a given OBJECT or INTERFACE type for the target schema. + /// + /// + /// + /// This method is synonymous with using the on + /// a controller action. + /// + /// + /// The supplied resolver must declare a parameter that is of the same type as . + /// + /// + /// The concrete interface, class or struct to extend with a new field. + /// The configuration options for the target schema. + /// Name of the field to add to the . + /// IGraphQLResolvedFieldTemplate. + public static IGraphQLRuntimeTypeExtensionDefinition MapTypeExtension(this SchemaOptions schemaOptions, string fieldName) + { + return MapTypeExtension( + schemaOptions, + typeof(TOwnerType), + fieldName, + null, // unionName + null as Delegate); + } + /// /// Registers a new type extension to a given OBJECT or INTERFACE type for the target schema. /// @@ -101,7 +155,7 @@ public static IGraphQLRuntimeTypeExtensionDefinition MapTypeExtensionName of the field to add to the . /// The resolver method to be called when the field is requested. /// IGraphQLResolvedFieldTemplate. - public static IGraphQLRuntimeTypeExtensionDefinition MapTypeExtension(this SchemaOptions schemaOptions, string fieldName, Delegate resolverMethod = null) + public static IGraphQLRuntimeTypeExtensionDefinition MapTypeExtension(this SchemaOptions schemaOptions, string fieldName, Delegate resolverMethod) { return MapTypeExtension( schemaOptions, @@ -111,6 +165,30 @@ public static IGraphQLRuntimeTypeExtensionDefinition MapTypeExtension + /// Registers a new field to a given type on the target schema. + /// + /// + /// + /// The supplied resolver must declare a parameter that is of the same type as . + /// + /// + /// The configuration options for the target schema. + /// The concrete interface, class or struct to extend with a new field. + /// Name of the field to add to the . + /// IGraphQLResolvedFieldTemplate. + public static IGraphQLRuntimeTypeExtensionDefinition MapTypeExtension(this SchemaOptions schemaOptions, Type fieldOwnerType, string fieldName) + { + var field = MapTypeExtension( + schemaOptions, + fieldOwnerType, + fieldName, + null, // unionName + null as Delegate); + + return field; + } + /// /// Registers a new field to a given type on the target schema. /// @@ -124,7 +202,7 @@ public static IGraphQLRuntimeTypeExtensionDefinition MapTypeExtensionName of the field to add to the . /// The resolver method to be called when the field is requested. /// IGraphQLResolvedFieldTemplate. - public static IGraphQLRuntimeTypeExtensionDefinition MapTypeExtension(this SchemaOptions schemaOptions, Type fieldOwnerType, string fieldName, Delegate resolverMethod = null) + public static IGraphQLRuntimeTypeExtensionDefinition MapTypeExtension(this SchemaOptions schemaOptions, Type fieldOwnerType, string fieldName, Delegate resolverMethod) { var field = MapTypeExtension( schemaOptions, @@ -154,7 +232,7 @@ public static IGraphQLRuntimeTypeExtensionDefinition MapTypeExtension(this Schem /// Provide a name and this field will be declared to return a union. Use to declare union members. /// The resolver method to be called when the field is requested. /// IGraphQLResolvedFieldTemplate. - public static IGraphQLRuntimeTypeExtensionDefinition MapTypeExtension(this SchemaOptions schemaOptions, string fieldName, string unionName, Delegate resolverMethod = null) + public static IGraphQLRuntimeTypeExtensionDefinition MapTypeExtension(this SchemaOptions schemaOptions, string fieldName, string unionName, Delegate resolverMethod) { return MapTypeExtension( schemaOptions, @@ -178,7 +256,7 @@ public static IGraphQLRuntimeTypeExtensionDefinition MapTypeExtensionProvide a name and this field will be declared to return a union. Use to declare union members. /// The resolver method to be called when the field is requested. /// IGraphQLResolvedFieldTemplate. - public static IGraphQLRuntimeTypeExtensionDefinition MapTypeExtension(this SchemaOptions schemaOptions, Type fieldOwnerType, string fieldName, string unionName, Delegate resolverMethod = null) + public static IGraphQLRuntimeTypeExtensionDefinition MapTypeExtension(this SchemaOptions schemaOptions, Type fieldOwnerType, string fieldName, string unionName, Delegate resolverMethod) { var field = MapTypeExtensionInternal( schemaOptions, @@ -201,7 +279,7 @@ public static IGraphQLRuntimeTypeExtensionDefinition MapTypeExtension(this Schem } if (resolverMethod != null) - field = field.AddResolver(resolverMethod); + field = field.AddResolver(unionName, resolverMethod); return field; } @@ -314,10 +392,11 @@ public static IGraphQLRuntimeTypeExtensionDefinition AllowAnonymous(this IGraphQ /// IGraphQLFieldBuilder. public static IGraphQLRuntimeTypeExtensionDefinition AddResolver(this IGraphQLRuntimeTypeExtensionDefinition fieldBuilder, Delegate resolverMethod) { - fieldBuilder.Resolver = resolverMethod; - fieldBuilder.ReturnType = null; - - return fieldBuilder; + return AddResolver( + fieldBuilder, + null as Type, // returnType + null, // unionName + resolverMethod); } /// @@ -333,9 +412,80 @@ public static IGraphQLRuntimeTypeExtensionDefinition AddResolver(this IGraphQLRu /// parsed to determine input arguments for the field on the target schema. /// IGraphQLFieldBuilder. public static IGraphQLRuntimeTypeExtensionDefinition AddResolver(this IGraphQLRuntimeTypeExtensionDefinition fieldBuilder, Delegate resolverMethod) + { + return AddResolver( + fieldBuilder, + typeof(TReturnType), + null, // unionName + resolverMethod); + } + + /// + /// Sets the resolver to be used when this field is requested at runtime. + /// + /// + /// If this method is called more than once the previously set resolver will be replaced. + /// + /// The field being built. + /// Provide a name and this field will be declared to return a union. Use to declare union members. + /// The delegate to assign as the resolver. This method will be + /// parsed to determine input arguments for the field on the target schema. + /// IGraphQLFieldBuilder. + public static IGraphQLRuntimeTypeExtensionDefinition AddResolver(this IGraphQLRuntimeTypeExtensionDefinition fieldBuilder, string unionName, Delegate resolverMethod) + { + return AddResolver( + fieldBuilder, + null as Type, // returnType + unionName, + resolverMethod); + } + + /// + /// Sets the resolver to be used when this field is requested at runtime. + /// + /// + /// If this method is called more than once the previously set resolver will be replaced. + /// + /// The expected, primary return type of the field. Must be provided + /// if the supplied delegate returns an . + /// The field being built. + /// Provide a name and this field will be declared to return a union. Use to declare union members. + /// The delegate to assign as the resolver. This method will be + /// parsed to determine input arguments for the field on the target schema. + /// IGraphQLFieldBuilder. + public static IGraphQLRuntimeTypeExtensionDefinition AddResolver(this IGraphQLRuntimeTypeExtensionDefinition fieldBuilder, string unionName, Delegate resolverMethod) + { + return AddResolver( + fieldBuilder, + typeof(TReturnType), + unionName, + resolverMethod); + } + + private static IGraphQLRuntimeTypeExtensionDefinition AddResolver(this IGraphQLRuntimeTypeExtensionDefinition fieldBuilder, Type expectedReturnType, string unionName, Delegate resolverMethod) { fieldBuilder.Resolver = resolverMethod; - fieldBuilder.ReturnType = typeof(TReturnType); + fieldBuilder.ReturnType = expectedReturnType; + + // since the resolver was declared as non-union, remove any potential union setup that might have + // existed via a previous call. if TReturnType is a union proxy it will be + // picked up automatically during templating + var unionAttrib = fieldBuilder.Attributes.OfType().SingleOrDefault(); + if (string.IsNullOrEmpty(unionName)) + { + if (unionAttrib != null) + fieldBuilder.RemoveAttribute(unionAttrib); + } + else if (unionAttrib != null) + { + unionAttrib.UnionName = unionName?.Trim(); + unionAttrib.UnionMemberTypes.Clear(); + } + else + { + fieldBuilder.AddAttribute(new UnionAttribute(unionName.Trim())); + } + return fieldBuilder; } } diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_VirtualFields.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_VirtualFields.cs index 19d1f4a19..e657fbc21 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_VirtualFields.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_VirtualFields.cs @@ -10,9 +10,11 @@ namespace GraphQL.AspNet.Configuration { using System; + using System.Linq; using GraphQL.AspNet.Common; using GraphQL.AspNet.Execution; using GraphQL.AspNet.Interfaces.Configuration; + using GraphQL.AspNet.Interfaces.Controllers; using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; using GraphQL.AspNet.Schemas.Generation.RuntimeSchemaItemDefinitions; using Microsoft.AspNetCore.Authorization; @@ -26,7 +28,8 @@ public static partial class GraphQLRuntimeSchemaItemDefinitionExtensions /// Adds policy-based authorization requirements to the field. /// /// - /// This is similar to adding the to a controller method + /// This is similar to adding the to a controller method. Subsequent calls to this + /// method will cause more authorization restrictions to be added to the field. /// /// The field being built. /// The name of the policy to assign via this requirement. @@ -63,7 +66,9 @@ public static IGraphQLRuntimeFieldDefinition RequireAuthorization( public static IGraphQLRuntimeFieldDefinition AllowAnonymous(this IGraphQLRuntimeFieldDefinition fieldBuilder) { Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); - fieldBuilder.AddAttribute(new AllowAnonymousAttribute()); + if (!fieldBuilder.Attributes.OfType().Any()) + fieldBuilder.AddAttribute(new AllowAnonymousAttribute()); + return fieldBuilder; } @@ -88,8 +93,7 @@ public static IGraphQLRuntimeFieldDefinition MapQueryGroup(this ISchemaBuilder s /// IGraphQLRuntimeFieldDefinition. public static IGraphQLRuntimeFieldDefinition MapQueryGroup(this SchemaOptions schemaOptions, string template) { - var virtualField = new RuntimeVirtualFieldTemplate(schemaOptions, SchemaItemCollections.Query, template); - return virtualField; + return new RuntimeVirtualFieldTemplate(schemaOptions, SchemaItemCollections.Query, template); } /// @@ -111,22 +115,40 @@ public static IGraphQLRuntimeFieldDefinition MapMutationGroup(this ISchemaBuilde /// IGraphQLRuntimeFieldDefinition. public static IGraphQLRuntimeFieldDefinition MapMutationGroup(this SchemaOptions schemaOptions, string template) { - var virtualField = new RuntimeVirtualFieldTemplate(schemaOptions, SchemaItemCollections.Mutation, template); - return virtualField; + return new RuntimeVirtualFieldTemplate(schemaOptions, SchemaItemCollections.Mutation, template); } /// /// Maps an intermediate child field into the schema. This field will inherit any parameters set from its parent (including the template path). /// Any fields created from this new group will inherit any parameters set on the group AND the parent group. /// + /// + /// Any intermediate child fields created via this method will retain their operation association (e.g. Mutation, Query etc.), it cannot be changed. + /// /// The field under which this new field will be nested. /// The template pattern to be appended to the supplied . /// IGraphQLRuntimeFieldDefinition. - public static IGraphQLRuntimeFieldDefinition MapSubGroup(this IGraphQLRuntimeFieldDefinition field, string subTemplate) + public static IGraphQLRuntimeFieldDefinition MapChildGroup(this IGraphQLRuntimeFieldDefinition field, string subTemplate) { return new RuntimeVirtualFieldTemplate(field, subTemplate); } + /// + /// Maps a terminal child field into the schema and assigns the resolver method to it. + /// + /// The field under which this new field will be nested. + /// The template pattern to be appended to the supplied . + /// IGraphQLResolvedFieldBuilder. + public static IGraphQLRuntimeResolvedFieldDefinition MapField(this IGraphQLRuntimeFieldDefinition field, string subTemplate) + { + return MapField( + field, + subTemplate, + null as Type, // expectedReturnType + null, // unionName + null as Delegate); + } + /// /// Maps a terminal child field into the schema and assigns the resolver method to it. /// @@ -136,10 +158,62 @@ public static IGraphQLRuntimeFieldDefinition MapSubGroup(this IGraphQLRuntimeFie /// IGraphQLResolvedFieldBuilder. public static IGraphQLRuntimeResolvedFieldDefinition MapField(this IGraphQLRuntimeFieldDefinition field, string subTemplate, Delegate resolverMethod) { - var subField = new RuntimeResolvedFieldDefinition(field, subTemplate); - subField.AddResolver(resolverMethod); + return MapField( + field, + subTemplate, + null as Type, // expectedReturnType + null, // unionName + resolverMethod); + } + /// + /// Maps a terminal child field into the schema and assigns the resolver method to it. + /// + /// The expected, primary return type of the field. Must be provided + /// if the supplied delegate returns an . + /// The field under which this new field will be nested. + /// The template pattern to be appended to the supplied . + /// The resolver method to be called when this field is requested. + /// IGraphQLResolvedFieldBuilder. + public static IGraphQLRuntimeResolvedFieldDefinition MapField(this IGraphQLRuntimeFieldDefinition field, string subTemplate, Delegate resolverMethod) + { + return MapField( + field, + subTemplate, + typeof(TReturnType), // expectedReturnType + null, // unionName + resolverMethod); + } + + /// + /// Maps a terminal child field into the schema and assigns the resolver method to it. + /// + /// The field under which this new field will be nested. + /// The template pattern to be appended to the supplied . + /// Provide a name and this field will be declared to return a union. Use to declare union members. + /// The resolver method to be called when this field is requested. + /// IGraphQLResolvedFieldBuilder. + public static IGraphQLRuntimeResolvedFieldDefinition MapField(this IGraphQLRuntimeFieldDefinition field, string subTemplate, string unionName, Delegate resolverMethod) + { + return MapField( + field, + subTemplate, + null as Type, // expectedReturnType + unionName, // unionName + resolverMethod); + } + + private static IGraphQLRuntimeResolvedFieldDefinition MapField( + IGraphQLRuntimeFieldDefinition field, + string subTemplate, + Type expectedReturnType, + string unionName, + Delegate resolverMethod) + { + var subField = new RuntimeResolvedFieldDefinition(field, subTemplate); subField.Options.AddRuntimeSchemaItem(subField); + + subField.AddResolver(expectedReturnType, unionName, resolverMethod); return subField; } } diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeDirectiveTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeDirectiveTests.cs index b4807b935..49e092f5c 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeDirectiveTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeDirectiveTests.cs @@ -41,7 +41,7 @@ public void Runtime_TypeSystemDirective_IsInvokedCorrectly() o.AddType(); o.MapDirective("@myObjectDirective") .RestrictLocations(DirectiveLocation.OBJECT) - .AddResolver((int a, int b) => + .AddResolver((int a, int b) => { _values["generalTypeSystemDirective"] = a + b; return GraphActionResult.Ok(); @@ -67,7 +67,7 @@ public void Runtime_TypeSystemDirective_InjectedService_IsInvokedCorrectly() o.AddType(); o.MapDirective("@myObjectDirective") .RestrictLocations(DirectiveLocation.OBJECT) - .AddResolver((int a, IInjectedService service) => + .AddResolver((int a, IInjectedService service) => { _values["injectedService"] = a + service.FetchValue(); return GraphActionResult.Ok(); @@ -95,7 +95,7 @@ public void Runtime_TypeSystemDirective_InterfaceAsExplicitSchemaItem_ThrowsExce o.AddType(); o.MapDirective("@myObjectDirective") .RestrictLocations(DirectiveLocation.OBJECT) - .AddResolver((int a, [FromGraphQL] IInjectedService service) => + .AddResolver((int a, [FromGraphQL] IInjectedService service) => { _values["injectedServiceWrong"] = a + service.FetchValue(); return GraphActionResult.Ok(); @@ -122,7 +122,7 @@ public async Task Runtime_ExecutionDirective_IsInvokedCorrectly() o.AddController(); o.MapDirective("@myFieldDirective") .RestrictLocations(DirectiveLocation.FIELD) - .AddResolver(() => + .AddResolver(() => { _values["fieldDirective"] = 11; return GraphActionResult.Ok(); @@ -157,7 +157,7 @@ public async Task Runtime_ExecutionDirective_OnMinimalApiField_IsInvokedCorrectl o.MapDirective("@myFieldDirective") .RestrictLocations(DirectiveLocation.FIELD) - .AddResolver(() => + .AddResolver(() => { _values["fieldDirective"] = 11; return GraphActionResult.Ok(); @@ -193,7 +193,7 @@ public async Task Runtime_ExecutionDirective_WithSecurityParams_AndAllowedUser_R o.MapDirective("@secureDirective") .RestrictLocations(DirectiveLocation.FIELD) .RequireAuthorization("policy1") - .AddResolver(() => + .AddResolver(() => { _values["secureDirective1"] = 11; return GraphActionResult.Ok(); @@ -234,7 +234,7 @@ public async Task Runtime_ExecutionDirective_WithSecurityParams_AndUnAuthenticat o.MapDirective("@secureDirective") .RestrictLocations(DirectiveLocation.FIELD) .RequireAuthorization("policy1") - .AddResolver(() => + .AddResolver(() => { _values["secureDirective2"] = 11; return GraphActionResult.Ok(); @@ -268,7 +268,7 @@ public async Task Runtime_ExecutionDirective_WithSecurityParams_AndUnAuthorizedU o.MapDirective("@secureDirective") .RestrictLocations(DirectiveLocation.FIELD) .RequireAuthorization("policy1") - .AddResolver(() => + .AddResolver(() => { _values["secureDirective3"] = 11; return GraphActionResult.Ok(); @@ -304,7 +304,7 @@ public async Task Runtime_ExecutionDirective_WithDirectiveContext_SuppliesContex o.MapDirective("@injectedContext") .RestrictLocations(DirectiveLocation.FIELD) - .AddResolver((DirectiveResolutionContext context) => + .AddResolver((DirectiveResolutionContext context) => { if (context != null) _values["directiveResolutionContext0"] = 1; @@ -341,7 +341,7 @@ public async Task Runtime_ExecutionDirective_WithFieldResolutionContext_ThrowsEx o.MapDirective("@injectedContext") .RestrictLocations(DirectiveLocation.FIELD) - .AddResolver((FieldResolutionContext context) => + .AddResolver((FieldResolutionContext context) => { if (context != null) _values["directiveResolutionContext1"] = 1; @@ -377,7 +377,7 @@ public async Task Runtime_ExecutionDirective_WithMultipleDirectiveContext_Suppli o.MapDirective("@injectedContext") .RestrictLocations(DirectiveLocation.FIELD) - .AddResolver((DirectiveResolutionContext context, DirectiveResolutionContext context1) => + .AddResolver((DirectiveResolutionContext context, DirectiveResolutionContext context1) => { if (context != null && context == context1) _values["directiveResolutionContext2"] = 1; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedDirectiveTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedDirectiveTemplateTests.cs index ac31708d4..e3e1e3cd7 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedDirectiveTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedDirectiveTemplateTests.cs @@ -188,9 +188,9 @@ public void MappedDirective_WhenResolverIsChangedWithExplicitType_NewResolverIsU var directive = options.MapDirective("@mydirective", (string a) => 1); Assert.AreEqual(typeof(int), directive.Resolver.Method.ReturnType); - directive.AddResolver((string a) => "bob"); + directive.AddResolver((string a) => "bob"); Assert.AreEqual(typeof(string), directive.Resolver.Method.ReturnType); - Assert.AreEqual(typeof(decimal), directive.ReturnType); + Assert.IsNull(directive.ReturnType); } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedMutationGroupTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedMutationGroupTests.cs index 4b9e247df..701b7a19a 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedMutationGroupTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedMutationGroupTests.cs @@ -59,7 +59,7 @@ public void MapMutationGroup_WhenUnresolvedChildFieldIsAdded_PathIsCorrect() var field = options.MapMutationGroup("/path1/path2"); - var childField = field.MapSubGroup("/path3/path4"); + var childField = field.MapChildGroup("/path3/path4"); Assert.AreEqual("[mutation]/path1/path2/path3/path4", childField.Route.Path); } @@ -101,7 +101,7 @@ public void MapMutationGroup_WhenResolvedChildFieldIsAddedToUnresolvedChildField var options = new SchemaOptions(services); var field = options.MapMutationGroup("/path1/path2"); - var childField = field.MapSubGroup("/path3/path4"); + var childField = field.MapChildGroup("/path3/path4"); var resolvedField = childField.MapField("/path5/path6", (string a) => 1); Assert.AreEqual("[mutation]/path1/path2/path3/path4/path5/path6", resolvedField.Route.Path); diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedMutationTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedMutationTemplateTests.cs index 2dd33b746..ca7d408cc 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedMutationTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedMutationTemplateTests.cs @@ -91,18 +91,5 @@ public void MapMutation_WithUnionName0_AddsUnionNameToType() Assert.AreEqual("myUnion", attrib.UnionName); } - - [Test] - public void MapMutation_WithUnionName1_AddsUnionNameToType() - { - var services = new ServiceCollection(); - var options = new SchemaOptions(services); - - var typeExt = options.MapMutation("myField", "myUnion"); - - var attrib = typeExt.Attributes.OfType().SingleOrDefault(); - - Assert.AreEqual("myUnion", attrib.UnionName); - } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedQueryGroupTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedQueryGroupTests.cs index b4d123c8a..bebaa56a9 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedQueryGroupTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedQueryGroupTests.cs @@ -59,7 +59,7 @@ public void MapQueryGroup_WhenUnresolvedChildFieldIsAdded_PathIsCorrect() var field = options.MapQueryGroup("/path1/path2"); - var childField = field.MapSubGroup("/path3/path4"); + var childField = field.MapChildGroup("/path3/path4"); Assert.AreEqual("[query]/path1/path2/path3/path4", childField.Route.Path); } @@ -101,7 +101,7 @@ public void MapQueryGroup_WhenResolvedChildFieldIsAddedToUnresolvedChildField_Pa var options = new SchemaOptions(services); var field = options.MapQueryGroup("/path1/path2"); - var childField = field.MapSubGroup("/path3/path4"); + var childField = field.MapChildGroup("/path3/path4"); var resolvedField = childField.MapField("/path5/path6", (string a) => 1); Assert.AreEqual("[query]/path1/path2/path3/path4/path5/path6", resolvedField.Route.Path); diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedQueryTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedQueryTemplateTests.cs index 62715c45e..3a65908c5 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedQueryTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedQueryTemplateTests.cs @@ -93,18 +93,5 @@ public void MapQuery_WithUnionName0_AddsUnionNameToType() Assert.AreEqual("myUnion", attrib.UnionName); } - - [Test] - public void MapQuery_WithUnionName1_AddsUnionNameToType() - { - var services = new ServiceCollection(); - var options = new SchemaOptions(services); - - var typeExt = options.MapQuery("myField", "myUnion"); - - var attrib = typeExt.Attributes.OfType().SingleOrDefault(); - - Assert.AreEqual("myUnion", attrib.UnionName); - } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedTypeExtensionTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedTypeExtensionTemplateTests.cs index 3b222f663..3b4bbc541 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedTypeExtensionTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedTypeExtensionTemplateTests.cs @@ -218,16 +218,17 @@ public void MappedTypeExtension_WithUnionName0_AddsUnionNameToType() } [Test] - public void MappedTypeExtension_WithUnionName1_AddsUnionNameToType() + public void ResolvedField_SwappingOutResolvers_RemovesUnion() { var services = new ServiceCollection(); var options = new SchemaOptions(services); - var typeExt = options.MapTypeExtension("myField", "myUnion"); - - var attrib = typeExt.Attributes.OfType().SingleOrDefault(); + var typeExt = options.MapTypeExtension("myField", "myUnion", (string a) => 1); + Assert.AreEqual(1, typeExt.Attributes.Count(x => x is UnionAttribute)); - Assert.AreEqual("myUnion", attrib.UnionName); + // union is removed when resolver is re-declared + typeExt.AddResolver((int a) => 0); + Assert.AreEqual(0, typeExt.Attributes.Count(x => x is UnionAttribute)); } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/ResolvedFieldTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/ResolvedFieldTemplateTests.cs index 72b070dd1..55a29325f 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/ResolvedFieldTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/ResolvedFieldTemplateTests.cs @@ -122,5 +122,19 @@ public void ResolvedField_ResolverReturnsNullableT_ItsPreserved() // nullable int Assert.AreEqual(typeof(int?), field.Resolver.Method.ReturnType); } + + [Test] + public void ResolvedField_SwappingOutResolvers_RemovesUnion() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapQuery("/path1/path2", "myUnion", (string a) => (int?)1); + Assert.AreEqual(1, field.Attributes.Count(x => x is UnionAttribute)); + + // union is removed when resolver is re-declared + field.AddResolver((int a) => 0); + Assert.AreEqual(0, field.Attributes.Count(x => x is UnionAttribute)); + } } } \ No newline at end of file From 260e29b453c762ffe3f1b4269e9434e40f4656b7 Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Tue, 25 Jul 2023 17:55:26 -0700 Subject: [PATCH 52/63] WIP, more tests --- .../Attributes/SubscriptionAttribute.cs | 7 +- .../Attributes/SubscriptionRootAttribute.cs | 7 +- .../Attributes/MutationAttribute.cs | 9 +- .../Attributes/MutationRootAttribute.cs | 12 +- .../Attributes/PossibleTypesAttribute.cs | 6 +- .../Attributes/QueryAttribute.cs | 11 +- .../Attributes/QueryRootAttribute.cs | 7 +- .../Attributes/UnionAttribute.cs | 9 +- ...hemaItemDefinitionExtensions_Directives.cs | 20 +-- ...chemaItemDefinitionExtensions_Internals.cs | 99 ++++++++++++--- ...ItemDefinitionExtensions_ResolvedFields.cs | 66 +++------- ...ItemDefinitionExtensions_TypeExtensions.cs | 117 +++++++----------- ...aItemDefinitionExtensions_VirtualFields.cs | 2 +- .../MappedQueryGroupTests.cs | 87 ++++++++++++- .../ResolvedFieldTemplateTests.cs | 20 +++ .../TypeTemplates/ControllerTemplateTests.cs | 91 ++++++++++++++ .../ControllerWithDoubleDeclaredUnion.cs | 26 ++++ .../ControllerWithUnionAttributes.cs | 63 ++++++++++ 18 files changed, 464 insertions(+), 195 deletions(-) create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/ControllerWithDoubleDeclaredUnion.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/ControllerWithUnionAttributes.cs diff --git a/src/graphql-aspnet-subscriptions/Attributes/SubscriptionAttribute.cs b/src/graphql-aspnet-subscriptions/Attributes/SubscriptionAttribute.cs index 08608a266..0c0c2f2cf 100644 --- a/src/graphql-aspnet-subscriptions/Attributes/SubscriptionAttribute.cs +++ b/src/graphql-aspnet-subscriptions/Attributes/SubscriptionAttribute.cs @@ -82,7 +82,7 @@ public SubscriptionAttribute(string template, Type returnType) /// be sure to supply any additional concrete types so that they may be included in the object graph. /// Any additional types to include in the object graph on behalf of this method. public SubscriptionAttribute(string template, Type returnType, params Type[] additionalTypes) - : base(false, SchemaItemCollections.Subscription, template, returnType.AsEnumerable().Concat(additionalTypes).ToArray()) + : base(false, SchemaItemCollections.Subscription, template, (new Type[] { returnType }).Concat(additionalTypes ?? Enumerable.Empty()).ToArray()) { this.EventName = null; } @@ -93,15 +93,14 @@ public SubscriptionAttribute(string template, Type returnType, params Type[] add /// The template naming scheme to use to generate a graph field from this method. /// Name of the union type. /// The first of two required types to include in the union. - /// The second of two required types to include in the union. /// Any additional union types to include. - public SubscriptionAttribute(string template, string unionTypeName, Type unionTypeA, Type unionTypeB, params Type[] additionalUnionTypes) + public SubscriptionAttribute(string template, string unionTypeName, Type unionTypeA, params Type[] additionalUnionTypes) : base( false, SchemaItemCollections.Subscription, template, unionTypeName, - unionTypeA.AsEnumerable().Concat(unionTypeB.AsEnumerable()).Concat(additionalUnionTypes).ToArray()) + new Type[] { unionTypeA }.Concat(additionalUnionTypes ?? Enumerable.Empty()).ToArray()) { this.EventName = null; } diff --git a/src/graphql-aspnet-subscriptions/Attributes/SubscriptionRootAttribute.cs b/src/graphql-aspnet-subscriptions/Attributes/SubscriptionRootAttribute.cs index 57833d0b6..6184f7ed2 100644 --- a/src/graphql-aspnet-subscriptions/Attributes/SubscriptionRootAttribute.cs +++ b/src/graphql-aspnet-subscriptions/Attributes/SubscriptionRootAttribute.cs @@ -82,7 +82,7 @@ public SubscriptionRootAttribute(string template, Type returnType) /// be sure to supply any additional concrete types so that they may be included in the object graph. /// Any additional types to include in the object graph on behalf of this method. public SubscriptionRootAttribute(string template, Type returnType, params Type[] additionalTypes) - : base(true, SchemaItemCollections.Subscription, template, returnType.AsEnumerable().Concat(additionalTypes).ToArray()) + : base(true, SchemaItemCollections.Subscription, template, (new Type[] { returnType }).Concat(additionalTypes ?? Enumerable.Empty()).ToArray()) { this.EventName = null; } @@ -93,15 +93,14 @@ public SubscriptionRootAttribute(string template, Type returnType, params Type[] /// The template naming scheme to use to generate a graph field from this method. /// Name of the union type. /// The first of two required types to include in the union. - /// The second of two required types to include in the union. /// Any additional union types. - public SubscriptionRootAttribute(string template, string unionTypeName, Type unionTypeA, Type unionTypeB, params Type[] additionalUnionTypes) + public SubscriptionRootAttribute(string template, string unionTypeName, Type unionTypeA, params Type[] additionalUnionTypes) : base( true, SchemaItemCollections.Subscription, template, unionTypeName, - unionTypeA.AsEnumerable().Concat(unionTypeB.AsEnumerable()).Concat(additionalUnionTypes).ToArray()) + (new Type[] { unionTypeA }).Concat(additionalUnionTypes ?? Enumerable.Empty()).ToArray()) { this.EventName = null; } diff --git a/src/graphql-aspnet/Attributes/MutationAttribute.cs b/src/graphql-aspnet/Attributes/MutationAttribute.cs index dfc895a4c..a36183d9c 100644 --- a/src/graphql-aspnet/Attributes/MutationAttribute.cs +++ b/src/graphql-aspnet/Attributes/MutationAttribute.cs @@ -46,7 +46,7 @@ public MutationAttribute(string template) /// The template naming scheme to use to generate a graph field from this method. /// Name of the union type. public MutationAttribute(string template, string unionTypeName) - : this(template, unionTypeName, null, null) + : this(template, unionTypeName, null) { } @@ -92,7 +92,7 @@ public MutationAttribute(string template, Type returnType) /// be sure to supply any additional concrete types so that they may be included in the object graph. /// Any additional types to include in the object graph on behalf of this method. public MutationAttribute(string template, Type returnType, params Type[] additionalTypes) - : base(false, SchemaItemCollections.Mutation, template, returnType.AsEnumerable().Concat(additionalTypes).ToArray()) + : base(false, SchemaItemCollections.Mutation, template, (new Type[] { returnType }).Concat(additionalTypes ?? Enumerable.Empty()).ToArray()) { } @@ -102,15 +102,14 @@ public MutationAttribute(string template, Type returnType, params Type[] additio /// The template naming scheme to use to generate a graph field from this method. /// Name of the union type. /// The first of two required types to include in the union. - /// The second of two required types to include in the union. /// Any additional union types. - public MutationAttribute(string template, string unionTypeName, Type unionTypeA, Type unionTypeB, params Type[] additionalUnionTypes) + public MutationAttribute(string template, string unionTypeName, Type unionTypeA, params Type[] additionalUnionTypes) : base( false, SchemaItemCollections.Mutation, template, unionTypeName, - unionTypeA.AsEnumerable().Concat(unionTypeB.AsEnumerable()).Concat(additionalUnionTypes).ToArray()) + (new Type[] { unionTypeA }).Concat(additionalUnionTypes ?? Enumerable.Empty()).ToArray()) { } } diff --git a/src/graphql-aspnet/Attributes/MutationRootAttribute.cs b/src/graphql-aspnet/Attributes/MutationRootAttribute.cs index 1f6e76d5e..a1b8bb873 100644 --- a/src/graphql-aspnet/Attributes/MutationRootAttribute.cs +++ b/src/graphql-aspnet/Attributes/MutationRootAttribute.cs @@ -91,7 +91,7 @@ public MutationRootAttribute(string template, Type returnType) /// be sure to supply any additional concrete types so that they may be included in the object graph. /// Any additional types to include in the object graph on behalf of this method. public MutationRootAttribute(string template, Type returnType, params Type[] additionalTypes) - : base(true, SchemaItemCollections.Mutation, template, returnType.AsEnumerable().Concat(additionalTypes).ToArray()) + : base(true, SchemaItemCollections.Mutation, template, (new Type[] { returnType }).Concat(additionalTypes ?? Enumerable.Empty()).ToArray()) { } @@ -101,10 +101,14 @@ public MutationRootAttribute(string template, Type returnType, params Type[] add /// The template naming scheme to use to generate a graph field from this method. /// Name of the union type. /// The first of two required types to include in the union. - /// The second of two required types to include in the union. /// Any additional union types. - public MutationRootAttribute(string template, string unionTypeName, Type unionTypeA, Type unionTypeB, params Type[] additionalUnionTypes) - : base(true, SchemaItemCollections.Mutation, template, unionTypeName, unionTypeA.AsEnumerable().Concat(unionTypeB.AsEnumerable()).Concat(additionalUnionTypes).ToArray()) + public MutationRootAttribute(string template, string unionTypeName, Type unionTypeA, params Type[] additionalUnionTypes) + : base( + true, + SchemaItemCollections.Mutation, + template, + unionTypeName, + (new Type[] { unionTypeA }).Concat(additionalUnionTypes ?? Enumerable.Empty()).ToArray()) { } } diff --git a/src/graphql-aspnet/Attributes/PossibleTypesAttribute.cs b/src/graphql-aspnet/Attributes/PossibleTypesAttribute.cs index 98771b55d..4543c7c09 100644 --- a/src/graphql-aspnet/Attributes/PossibleTypesAttribute.cs +++ b/src/graphql-aspnet/Attributes/PossibleTypesAttribute.cs @@ -12,7 +12,6 @@ namespace GraphQL.AspNet.Attributes using System; using System.Collections.Generic; using System.Linq; - using GraphQL.AspNet.Common.Extensions; /// /// When an graph field returns an interface, use this attribute @@ -32,7 +31,10 @@ public class PossibleTypesAttribute : Attribute /// Any additional possible types. public PossibleTypesAttribute(Type firstPossibleType, params Type[] additionalPossibleTypes) { - this.PossibleTypes = firstPossibleType.AsEnumerable().Concat(additionalPossibleTypes).Where(x => x != null).ToList(); + this.PossibleTypes = new Type[] { firstPossibleType } + .Concat(additionalPossibleTypes ?? Enumerable.Empty()) + .Where(x => x != null) + .ToList(); } /// diff --git a/src/graphql-aspnet/Attributes/QueryAttribute.cs b/src/graphql-aspnet/Attributes/QueryAttribute.cs index a6b0f34d7..fe9083886 100644 --- a/src/graphql-aspnet/Attributes/QueryAttribute.cs +++ b/src/graphql-aspnet/Attributes/QueryAttribute.cs @@ -46,7 +46,7 @@ public QueryAttribute(string template) /// The template naming scheme to use to generate a graph field from this method. /// Name of the union type. public QueryAttribute(string template, string unionTypeName) - : this(template, unionTypeName, null, null) + : this(template, unionTypeName, null) { } @@ -92,7 +92,7 @@ public QueryAttribute(string template, Type returnType) /// be sure to supply any additional concrete types so that they may be included in the object graph. /// Any additional types to include in the object graph on behalf of this method. public QueryAttribute(string template, Type returnType, params Type[] additionalTypes) - : base(false, SchemaItemCollections.Query, template, returnType.AsEnumerable().Concat(additionalTypes).ToArray()) + : base(false, SchemaItemCollections.Query, template, (new Type[] { returnType }).Concat(additionalTypes ?? Enumerable.Empty()).ToArray()) { } @@ -101,16 +101,15 @@ public QueryAttribute(string template, Type returnType, params Type[] additional /// /// The template naming scheme to use to generate a graph field from this method. /// Name of the union type. - /// The first of two required types to include in the union. - /// The second of two required types to include in the union. + /// The first type to include in the union. /// Any additional union types to include. - public QueryAttribute(string template, string unionTypeName, Type unionTypeA, Type unionTypeB, params Type[] additionalUnionTypes) + public QueryAttribute(string template, string unionTypeName, Type unionTypeA, params Type[] additionalUnionTypes) : base( false, SchemaItemCollections.Query, template, unionTypeName, - unionTypeA.AsEnumerable().Concat(unionTypeB.AsEnumerable()).Concat(additionalUnionTypes).ToArray()) + (new Type[] { unionTypeA }).Concat(additionalUnionTypes ?? Enumerable.Empty()).ToArray()) { } } diff --git a/src/graphql-aspnet/Attributes/QueryRootAttribute.cs b/src/graphql-aspnet/Attributes/QueryRootAttribute.cs index 85aa7cc4c..b32714d6f 100644 --- a/src/graphql-aspnet/Attributes/QueryRootAttribute.cs +++ b/src/graphql-aspnet/Attributes/QueryRootAttribute.cs @@ -91,7 +91,7 @@ public QueryRootAttribute(string template, Type returnType) /// be sure to supply any additional concrete types so that they may be included in the object graph. /// Any additional types to include in the object graph on behalf of this method. public QueryRootAttribute(string template, Type returnType, params Type[] additionalTypes) - : base(true, SchemaItemCollections.Query, template, returnType.AsEnumerable().Concat(additionalTypes).ToArray()) + : base(true, SchemaItemCollections.Query, template, (new Type[] { returnType }).Concat(additionalTypes ?? Enumerable.Empty()).ToArray()) { } @@ -101,15 +101,14 @@ public QueryRootAttribute(string template, Type returnType, params Type[] additi /// The template naming scheme to use to generate a graph field from this method. /// Name of the union type. /// The first of two required types to include in the union. - /// The second of two required types to include in the union. /// Any additional union types. - public QueryRootAttribute(string template, string unionTypeName, Type unionTypeA, Type unionTypeB, params Type[] additionalUnionTypes) + public QueryRootAttribute(string template, string unionTypeName, Type unionTypeA, params Type[] additionalUnionTypes) : base( true, SchemaItemCollections.Query, template, unionTypeName, - unionTypeA.AsEnumerable().Concat(unionTypeB.AsEnumerable()).Concat(additionalUnionTypes).ToArray()) + (new Type[] { unionTypeA }).Concat(additionalUnionTypes ?? Enumerable.Empty()).ToArray()) { } } diff --git a/src/graphql-aspnet/Attributes/UnionAttribute.cs b/src/graphql-aspnet/Attributes/UnionAttribute.cs index c8bddae20..61a4ec3b3 100644 --- a/src/graphql-aspnet/Attributes/UnionAttribute.cs +++ b/src/graphql-aspnet/Attributes/UnionAttribute.cs @@ -32,18 +32,14 @@ public class UnionAttribute : GraphAttributeBase /// /// The name of the union as it should appear in the schema. /// The first member type to include in the union. - /// The second member type to include in the union. /// Additional member types to include in the union. - /// - /// All Unions must declare at least two member types that will be included in the union. - /// - public UnionAttribute(string unionName, Type firstUnionMemberType, Type secondUnionMemberType, params Type[] otherUnionMembers) + /// All Unions must declare at least two member types that will be included in the union. + public UnionAttribute(string unionName, Type firstUnionMemberType, params Type[] otherUnionMembers) { this.UnionName = unionName?.Trim(); var list = new List(2 + otherUnionMembers.Length); list.Add(firstUnionMemberType); - list.Add(secondUnionMemberType); list.AddRange(otherUnionMembers); this.UnionMemberTypes = list; } @@ -54,6 +50,7 @@ public UnionAttribute(string unionName, Type firstUnionMemberType, Type secondUn /// A type that inherits from or implements which /// declares all required information about the referenced union. public UnionAttribute(Type unionProxyType) + : this() { this.UnionName = null; if (unionProxyType != null) diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Directives.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Directives.cs index 771c46963..3f4e7a037 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Directives.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Directives.cs @@ -10,6 +10,7 @@ namespace GraphQL.AspNet.Configuration { using System; + using System.Diagnostics.CodeAnalysis; using System.Linq; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Common; @@ -43,11 +44,7 @@ public static IGraphQLRuntimeDirectiveDefinition RequireAuthorization( { Validation.ThrowIfNull(directiveTemplate, nameof(directiveTemplate)); - var attrib = new AuthorizeAttribute(); - attrib.Policy = policyName?.Trim(); - attrib.Roles = roles?.Trim(); - directiveTemplate.AddAttribute(attrib); - return directiveTemplate; + return RequireAuthorizationInternal(directiveTemplate, policyName, roles); } /// @@ -67,12 +64,7 @@ public static IGraphQLRuntimeDirectiveDefinition RequireAuthorization( public static IGraphQLRuntimeDirectiveDefinition AllowAnonymous(this IGraphQLRuntimeDirectiveDefinition directiveTemplate) { Validation.ThrowIfNull(directiveTemplate, nameof(directiveTemplate)); - if (directiveTemplate.Attributes.Count(x => x is AllowAnonymousAttribute) == 0) - { - directiveTemplate.AddAttribute(new AllowAnonymousAttribute()); - } - - return directiveTemplate; + return AllowAnonymousInternal(directiveTemplate); } /// @@ -132,11 +124,7 @@ public static IGraphQLRuntimeDirectiveDefinition RestrictLocations( /// IGraphQLRuntimeDirectiveDefinition. public static IGraphQLRuntimeDirectiveDefinition AddResolver(this IGraphQLRuntimeDirectiveDefinition directiveTemplate, Delegate resolverMethod) { - Validation.ThrowIfNull(directiveTemplate, nameof(directiveTemplate)); - directiveTemplate.Resolver = resolverMethod; - directiveTemplate.ReturnType = null; - - return directiveTemplate; + return AddResolverInternal(directiveTemplate, null, null, resolverMethod); } /// diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Internals.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Internals.cs index 60d33fdc2..ff4edfcd2 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Internals.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Internals.cs @@ -10,18 +10,78 @@ namespace GraphQL.AspNet.Configuration { using System; + using System.Linq; + using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Common; using GraphQL.AspNet.Execution; - using GraphQL.AspNet.Execution.Parsing.Lexing.Tokens; using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; using GraphQL.AspNet.Schemas.Generation.RuntimeSchemaItemDefinitions; using GraphQL.AspNet.Schemas.TypeSystem; + using Microsoft.AspNetCore.Authorization; /// /// Extension methods for configuring minimal API methods as fields on the graph. /// public static partial class GraphQLRuntimeSchemaItemDefinitionExtensions { + private static TItemType RequireAuthorizationInternal( + this TItemType schemaItem, + string policyName = null, + string roles = null) + where TItemType : IGraphQLRuntimeSchemaItemDefinition + { + Validation.ThrowIfNull(schemaItem, nameof(schemaItem)); + + var attrib = new AuthorizeAttribute(); + attrib.Policy = policyName?.Trim(); + attrib.Roles = roles?.Trim(); + schemaItem.AddAttribute(attrib); + + // remove any allow anon attriubtes + var allowAnonAttribs = schemaItem.Attributes.OfType().ToList(); + foreach (var anonAttrib in allowAnonAttribs) + schemaItem.RemoveAttribute(anonAttrib); + + return schemaItem; + } + + private static TItemType AllowAnonymousInternal(TItemType schemaItem) + where TItemType : IGraphQLRuntimeSchemaItemDefinition + { + Validation.ThrowIfNull(schemaItem, nameof(schemaItem)); + if (schemaItem.Attributes.Count(x => x is AllowAnonymousAttribute) == 0) + { + schemaItem.AddAttribute(new AllowAnonymousAttribute()); + } + + // remove any authorize attributes + var authAttribs = schemaItem.Attributes.OfType().ToList(); + foreach (var attib in authAttribs) + schemaItem.RemoveAttribute(attib); + + return schemaItem; + } + + private static TItemType ClearPossibleTypesInternal(TItemType fieldBuilder) + where TItemType : IGraphQLRuntimeSchemaItemDefinition + { + Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); + var attributes = fieldBuilder.Attributes.OfType().ToList(); + foreach (var att in attributes) + fieldBuilder.RemoveAttribute(att); + + return fieldBuilder; + } + + private static TItemType AddPossibleTypesInternal(TItemType fieldBuilder, Type firstPossibleType, params Type[] additionalPossibleTypes) + where TItemType : IGraphQLRuntimeSchemaItemDefinition + { + Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); + var possibleTypes = new PossibleTypesAttribute(firstPossibleType, additionalPossibleTypes); + fieldBuilder.AddAttribute(possibleTypes); + return fieldBuilder; + } + private static IGraphQLRuntimeFieldDefinition MapGraphQLFieldInternal( SchemaOptions schemaOptions, GraphOperationType operationType, @@ -38,23 +98,32 @@ private static IGraphQLRuntimeFieldDefinition MapGraphQLFieldInternal( return fieldTemplate; } - private static IGraphQLRuntimeTypeExtensionDefinition MapTypeExtensionInternal( - SchemaOptions schemaOptions, - Type typeToExtend, - string fieldName, - FieldResolutionMode resolutionMode) + private static TItemType AddResolverInternal(this TItemType fieldBuilder, Type expectedReturnType, string unionName, Delegate resolverMethod) + where TItemType : IGraphQLResolvableSchemaItemDefinition { - schemaOptions = Validation.ThrowIfNullOrReturn(schemaOptions, nameof(schemaOptions)); - fieldName = Validation.ThrowIfNullWhiteSpaceOrReturn(fieldName, nameof(fieldName)); + fieldBuilder.Resolver = resolverMethod; + fieldBuilder.ReturnType = expectedReturnType; - IGraphQLRuntimeTypeExtensionDefinition field = new RuntimeTypeExtensionDefinition( - schemaOptions, - typeToExtend, - fieldName, - resolutionMode); + // since the resolver was declared as non-union, remove any potential union setup that might have + // existed via a previous call. if TReturnType is a union proxy it will be + // picked up automatically during templating + var unionAttrib = fieldBuilder.Attributes.OfType().SingleOrDefault(); + if (string.IsNullOrEmpty(unionName)) + { + if (unionAttrib != null) + fieldBuilder.RemoveAttribute(unionAttrib); + } + else if (unionAttrib != null) + { + unionAttrib.UnionName = unionName?.Trim(); + unionAttrib.UnionMemberTypes.Clear(); + } + else + { + fieldBuilder.AddAttribute(new UnionAttribute(unionName.Trim())); + } - schemaOptions.AddRuntimeSchemaItem(field); - return field; + return fieldBuilder; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_ResolvedFields.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_ResolvedFields.cs index a522a5b48..cd5c2d77e 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_ResolvedFields.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_ResolvedFields.cs @@ -39,12 +39,7 @@ public static IGraphQLRuntimeResolvedFieldDefinition RequireAuthorization( string roles = null) { Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); - - var attrib = new AuthorizeAttribute(); - attrib.Policy = policyName?.Trim(); - attrib.Roles = roles?.Trim(); - fieldBuilder.AddAttribute(attrib); - return fieldBuilder; + return RequireAuthorizationInternal(fieldBuilder, policyName, roles); } /// @@ -59,8 +54,7 @@ public static IGraphQLRuntimeResolvedFieldDefinition RequireAuthorization( public static IGraphQLRuntimeResolvedFieldDefinition AllowAnonymous(this IGraphQLRuntimeResolvedFieldDefinition fieldBuilder) { Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); - fieldBuilder.AddAttribute(new AllowAnonymousAttribute()); - return fieldBuilder; + return AllowAnonymousInternal(fieldBuilder); } /// @@ -80,9 +74,8 @@ public static IGraphQLRuntimeResolvedFieldDefinition AllowAnonymous(this IGraphQ /// IGraphQLFieldBuilder. public static IGraphQLRuntimeResolvedFieldDefinition AddPossibleTypes(this IGraphQLRuntimeResolvedFieldDefinition fieldBuilder, Type firstPossibleType, params Type[] additionalPossibleTypes) { - var possibleTypes = new PossibleTypesAttribute(firstPossibleType, additionalPossibleTypes); - fieldBuilder.AddAttribute(possibleTypes); - return fieldBuilder; + Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); + return AddPossibleTypesInternal(fieldBuilder, firstPossibleType, additionalPossibleTypes); } /// @@ -93,11 +86,8 @@ public static IGraphQLRuntimeResolvedFieldDefinition AddPossibleTypes(this IGrap /// IGraphQLRuntimeResolvedFieldDefinition. public static IGraphQLRuntimeResolvedFieldDefinition ClearPossibleTypes(this IGraphQLRuntimeResolvedFieldDefinition fieldBuilder) { - var attributes = fieldBuilder.Attributes.OfType().ToList(); - foreach (var att in attributes) - fieldBuilder.RemoveAttribute(att); - - return fieldBuilder; + Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); + return ClearPossibleTypesInternal(fieldBuilder); } /// @@ -115,6 +105,7 @@ public static IGraphQLRuntimeResolvedFieldDefinition ClearPossibleTypes(this IGr /// IGraphQLFieldBuilder. public static IGraphQLRuntimeResolvedFieldDefinition WithName(this IGraphQLRuntimeResolvedFieldDefinition fieldBuilder, string internalName) { + Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); fieldBuilder.InternalName = internalName?.Trim(); return fieldBuilder; } @@ -133,7 +124,8 @@ public static IGraphQLRuntimeResolvedFieldDefinition AddResolver( string unionName, Delegate resolverMethod) { - return AddResolver( + Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); + return AddResolverInternal( fieldBuilder, null as Type, // return Type unionName, @@ -155,7 +147,8 @@ public static IGraphQLRuntimeResolvedFieldDefinition AddResolver( /// IGraphQLFieldBuilder. public static IGraphQLRuntimeResolvedFieldDefinition AddResolver(this IGraphQLRuntimeResolvedFieldDefinition fieldBuilder, string unionName, Delegate resolverMethod) { - return AddResolver( + Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); + return AddResolverInternal( fieldBuilder, typeof(TReturnType), unionName, @@ -174,7 +167,8 @@ public static IGraphQLRuntimeResolvedFieldDefinition AddResolver(th /// IGraphQLFieldBuilder. public static IGraphQLRuntimeResolvedFieldDefinition AddResolver(this IGraphQLRuntimeResolvedFieldDefinition fieldBuilder, Delegate resolverMethod) { - return AddResolver( + Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); + return AddResolverInternal( fieldBuilder, null as Type, // return Type null, // unionName @@ -195,42 +189,12 @@ public static IGraphQLRuntimeResolvedFieldDefinition AddResolver(this IGraphQLRu /// IGraphQLFieldBuilder. public static IGraphQLRuntimeResolvedFieldDefinition AddResolver(this IGraphQLRuntimeResolvedFieldDefinition fieldBuilder, Delegate resolverMethod) { - return AddResolver( + Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); + return AddResolverInternal( fieldBuilder, typeof(TReturnType), null, // unionName resolverMethod); } - - private static IGraphQLRuntimeResolvedFieldDefinition AddResolver( - this IGraphQLRuntimeResolvedFieldDefinition fieldBuilder, - Type expectedReturnType, - string unionName, - Delegate resolverMethod) - { - fieldBuilder.Resolver = resolverMethod; - fieldBuilder.ReturnType = expectedReturnType; - - // since the resolver was declared as non-union, remove any potential union setup that might have - // existed via a previous call. if TReturnType is a union proxy it will be - // picked up automatically during templating - var unionAttrib = fieldBuilder.Attributes.OfType().SingleOrDefault(); - if (string.IsNullOrEmpty(unionName)) - { - if (unionAttrib != null) - fieldBuilder.RemoveAttribute(unionAttrib); - } - else if (unionAttrib != null) - { - unionAttrib.UnionName = unionName?.Trim(); - unionAttrib.UnionMemberTypes.Clear(); - } - else - { - fieldBuilder.AddAttribute(new UnionAttribute(unionName.Trim())); - } - - return fieldBuilder; - } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_TypeExtensions.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_TypeExtensions.cs index e8c0ba38c..17f4af7e3 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_TypeExtensions.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_TypeExtensions.cs @@ -11,13 +11,13 @@ namespace GraphQL.AspNet.Configuration { using System; using System.Collections.Generic; - using System.Linq; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Common; using GraphQL.AspNet.Execution; using GraphQL.AspNet.Interfaces.Configuration; using GraphQL.AspNet.Interfaces.Controllers; using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; + using GraphQL.AspNet.Schemas.Generation.RuntimeSchemaItemDefinitions; using Microsoft.AspNetCore.Authorization; /// @@ -179,14 +179,12 @@ public static IGraphQLRuntimeTypeExtensionDefinition MapTypeExtensionIGraphQLResolvedFieldTemplate. public static IGraphQLRuntimeTypeExtensionDefinition MapTypeExtension(this SchemaOptions schemaOptions, Type fieldOwnerType, string fieldName) { - var field = MapTypeExtension( + return MapTypeExtension( schemaOptions, fieldOwnerType, fieldName, null, // unionName null as Delegate); - - return field; } /// @@ -204,14 +202,12 @@ public static IGraphQLRuntimeTypeExtensionDefinition MapTypeExtension(this Schem /// IGraphQLResolvedFieldTemplate. public static IGraphQLRuntimeTypeExtensionDefinition MapTypeExtension(this SchemaOptions schemaOptions, Type fieldOwnerType, string fieldName, Delegate resolverMethod) { - var field = MapTypeExtension( + return MapTypeExtension( schemaOptions, fieldOwnerType, fieldName, null, // unionName resolverMethod); - - return field; } /// @@ -258,25 +254,17 @@ public static IGraphQLRuntimeTypeExtensionDefinition MapTypeExtensionIGraphQLResolvedFieldTemplate. public static IGraphQLRuntimeTypeExtensionDefinition MapTypeExtension(this SchemaOptions schemaOptions, Type fieldOwnerType, string fieldName, string unionName, Delegate resolverMethod) { - var field = MapTypeExtensionInternal( + schemaOptions = Validation.ThrowIfNullOrReturn(schemaOptions, nameof(schemaOptions)); + fieldOwnerType = Validation.ThrowIfNullOrReturn(fieldOwnerType, nameof(fieldOwnerType)); + fieldName = Validation.ThrowIfNullWhiteSpaceOrReturn(fieldName, nameof(fieldName)); + + IGraphQLRuntimeTypeExtensionDefinition field = new RuntimeTypeExtensionDefinition( schemaOptions, fieldOwnerType, fieldName, FieldResolutionMode.PerSourceItem); - if (!string.IsNullOrWhiteSpace(unionName)) - { - var unionAttrib = field.Attributes.OfType().SingleOrDefault(); - if (unionAttrib != null) - { - unionAttrib.UnionName = unionName?.Trim(); - unionAttrib.UnionMemberTypes.Clear(); - } - else - { - field.AddAttribute(new UnionAttribute(unionName.Trim())); - } - } + schemaOptions.AddRuntimeSchemaItem(field); if (resolverMethod != null) field = field.AddResolver(unionName, resolverMethod); @@ -298,6 +286,7 @@ public static IGraphQLRuntimeTypeExtensionDefinition MapTypeExtension(this Schem /// IGraphQLTypeExtensionTemplate. public static IGraphQLRuntimeTypeExtensionDefinition WithBatchProcessing(this IGraphQLRuntimeTypeExtensionDefinition typeExtension) { + Validation.ThrowIfNull(typeExtension, nameof(typeExtension)); typeExtension.ExecutionMode = FieldResolutionMode.Batch; return typeExtension; } @@ -309,17 +298,28 @@ public static IGraphQLRuntimeTypeExtensionDefinition WithBatchProcessing(this IG /// /// This method can be called multiple times. Any new types will be appended to the field. /// - /// The field being built. + /// The field being built. /// The first possible type that might be returned by this /// field. /// Any number of additional possible types that /// might be returned by this field. /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeTypeExtensionDefinition AddPossibleTypes(this IGraphQLRuntimeTypeExtensionDefinition fieldBuilder, Type firstPossibleType, params Type[] additionalPossibleTypes) + public static IGraphQLRuntimeTypeExtensionDefinition AddPossibleTypes(this IGraphQLRuntimeTypeExtensionDefinition typeExtension, Type firstPossibleType, params Type[] additionalPossibleTypes) { - var possibleTypes = new PossibleTypesAttribute(firstPossibleType, additionalPossibleTypes); - fieldBuilder.AddAttribute(possibleTypes); - return fieldBuilder; + Validation.ThrowIfNull(typeExtension, nameof(typeExtension)); + return AddPossibleTypesInternal(typeExtension, firstPossibleType, additionalPossibleTypes); + } + + /// + /// Clears all extra defined possible types this field may declare. This will not affect the core type defined by the resolver, if + /// a resolver has been defined for this field. + /// + /// The field builder. + /// IGraphQLRuntimeResolvedFieldDefinition. + public static IGraphQLRuntimeTypeExtensionDefinition ClearPossibleTypes(this IGraphQLRuntimeTypeExtensionDefinition typeExtension) + { + Validation.ThrowIfNull(typeExtension, nameof(typeExtension)); + return ClearPossibleTypesInternal(typeExtension); } /// @@ -331,14 +331,14 @@ public static IGraphQLRuntimeTypeExtensionDefinition AddPossibleTypes(this IGrap /// This value does NOT affect the field name as it would appear in a schema. It only effects the internal /// name used in log messages and exception text. /// - /// The type exension field being built. + /// The type exension field being built. /// The value to use as the internal name for this field definition when its /// added to the schema. /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeTypeExtensionDefinition WithName(this IGraphQLRuntimeTypeExtensionDefinition fieldBuilder, string internalName) + public static IGraphQLRuntimeTypeExtensionDefinition WithName(this IGraphQLRuntimeTypeExtensionDefinition typeExtension, string internalName) { - fieldBuilder.InternalName = internalName; - return fieldBuilder; + typeExtension.InternalName = internalName; + return typeExtension; } /// @@ -357,12 +357,7 @@ public static IGraphQLRuntimeTypeExtensionDefinition RequireAuthorization( string roles = null) { Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); - - var attrib = new AuthorizeAttribute(); - attrib.Policy = policyName?.Trim(); - attrib.Roles = roles?.Trim(); - fieldBuilder.AddAttribute(attrib); - return fieldBuilder; + return RequireAuthorizationInternal(fieldBuilder, policyName, roles); } /// @@ -371,13 +366,12 @@ public static IGraphQLRuntimeTypeExtensionDefinition RequireAuthorization( /// /// This is similar to adding the to a controller method /// - /// The field being built. + /// The field being built. /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeTypeExtensionDefinition AllowAnonymous(this IGraphQLRuntimeTypeExtensionDefinition fieldBuilder) + public static IGraphQLRuntimeTypeExtensionDefinition AllowAnonymous(this IGraphQLRuntimeTypeExtensionDefinition typeExtension) { - Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); - fieldBuilder.AddAttribute(new AllowAnonymousAttribute()); - return fieldBuilder; + Validation.ThrowIfNull(typeExtension, nameof(typeExtension)); + return AllowAnonymousInternal(typeExtension); } /// @@ -386,14 +380,14 @@ public static IGraphQLRuntimeTypeExtensionDefinition AllowAnonymous(this IGraphQ /// /// If this method is called more than once the previously set resolver will be replaced. /// - /// The field being built. + /// The field being built. /// The delegate to assign as the resolver. This method will be /// parsed to determine input arguments for the field on the target schema. /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeTypeExtensionDefinition AddResolver(this IGraphQLRuntimeTypeExtensionDefinition fieldBuilder, Delegate resolverMethod) + public static IGraphQLRuntimeTypeExtensionDefinition AddResolver(this IGraphQLRuntimeTypeExtensionDefinition typeExtension, Delegate resolverMethod) { - return AddResolver( - fieldBuilder, + return AddResolverInternal( + typeExtension, null as Type, // returnType null, // unionName resolverMethod); @@ -413,7 +407,7 @@ public static IGraphQLRuntimeTypeExtensionDefinition AddResolver(this IGraphQLRu /// IGraphQLFieldBuilder. public static IGraphQLRuntimeTypeExtensionDefinition AddResolver(this IGraphQLRuntimeTypeExtensionDefinition fieldBuilder, Delegate resolverMethod) { - return AddResolver( + return AddResolverInternal( fieldBuilder, typeof(TReturnType), null, // unionName @@ -433,7 +427,7 @@ public static IGraphQLRuntimeTypeExtensionDefinition AddResolver(th /// IGraphQLFieldBuilder. public static IGraphQLRuntimeTypeExtensionDefinition AddResolver(this IGraphQLRuntimeTypeExtensionDefinition fieldBuilder, string unionName, Delegate resolverMethod) { - return AddResolver( + return AddResolverInternal( fieldBuilder, null as Type, // returnType unionName, @@ -455,38 +449,11 @@ public static IGraphQLRuntimeTypeExtensionDefinition AddResolver(this IGraphQLRu /// IGraphQLFieldBuilder. public static IGraphQLRuntimeTypeExtensionDefinition AddResolver(this IGraphQLRuntimeTypeExtensionDefinition fieldBuilder, string unionName, Delegate resolverMethod) { - return AddResolver( + return AddResolverInternal( fieldBuilder, typeof(TReturnType), unionName, resolverMethod); } - - private static IGraphQLRuntimeTypeExtensionDefinition AddResolver(this IGraphQLRuntimeTypeExtensionDefinition fieldBuilder, Type expectedReturnType, string unionName, Delegate resolverMethod) - { - fieldBuilder.Resolver = resolverMethod; - fieldBuilder.ReturnType = expectedReturnType; - - // since the resolver was declared as non-union, remove any potential union setup that might have - // existed via a previous call. if TReturnType is a union proxy it will be - // picked up automatically during templating - var unionAttrib = fieldBuilder.Attributes.OfType().SingleOrDefault(); - if (string.IsNullOrEmpty(unionName)) - { - if (unionAttrib != null) - fieldBuilder.RemoveAttribute(unionAttrib); - } - else if (unionAttrib != null) - { - unionAttrib.UnionName = unionName?.Trim(); - unionAttrib.UnionMemberTypes.Clear(); - } - else - { - fieldBuilder.AddAttribute(new UnionAttribute(unionName.Trim())); - } - - return fieldBuilder; - } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_VirtualFields.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_VirtualFields.cs index e657fbc21..e38ae92e6 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_VirtualFields.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_VirtualFields.cs @@ -213,7 +213,7 @@ private static IGraphQLRuntimeResolvedFieldDefinition MapField( var subField = new RuntimeResolvedFieldDefinition(field, subTemplate); subField.Options.AddRuntimeSchemaItem(subField); - subField.AddResolver(expectedReturnType, unionName, resolverMethod); + AddResolverInternal(subField, expectedReturnType, unionName, resolverMethod); return subField; } } diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedQueryGroupTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedQueryGroupTests.cs index bebaa56a9..db4ab22d4 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedQueryGroupTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedQueryGroupTests.cs @@ -150,9 +150,9 @@ public void MapQueryGroup_MultipleCopyAttribute_AppliedToGroupAndField_IsApplied .RequireAuthorization("policy2"); Assert.AreEqual(3, childField.Attributes.Count()); - var anonCount = childField.Attributes.Where(x => x is AuthorizeAttribute).Count(); + var authCount = childField.Attributes.Where(x => x is AuthorizeAttribute).Count(); - Assert.AreEqual(2, anonCount); + Assert.AreEqual(2, authCount); Assert.IsNotNull(childField.Attributes.SingleOrDefault(x => x is AuthorizeAttribute a && a.Policy == "policy1")); Assert.IsNotNull(childField.Attributes.SingleOrDefault(x => x is AuthorizeAttribute a && a.Policy == "policy2")); @@ -174,5 +174,88 @@ public void MapQueryGroup_MultipleCopyAttribute_AppliedToGroupAndField_IsApplied Assert.AreEqual(2, i); } + + [Test] + public void MapQueryGroup_MultipleSeperateChildGrous_AttributesAreAppliedCorrectly() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapQueryGroup("/path1/path2") + .RequireAuthorization("policy1"); + + var childGroup1 = field.MapChildGroup("path3") + .RequireAuthorization("policy2"); + var childField1 = childGroup1.MapField("/path4", (string a) => 1) + .RequireAuthorization("policy3"); + + var childGroup2 = field.MapChildGroup("path5") + .RequireAuthorization("policy4"); + var childField2 = childGroup2.MapField("path6", (string a) => 1) + .RequireAuthorization("policy5"); + + // three authorize attribs + primary + Assert.AreEqual(4, childField1.Attributes.Count()); + var authCount = childField1.Attributes.Where(x => x is AuthorizeAttribute).Count(); + + Assert.AreEqual(3, authCount); + Assert.IsNotNull(childField1.Attributes.SingleOrDefault(x => x is AuthorizeAttribute a && a.Policy == "policy1")); + Assert.IsNotNull(childField1.Attributes.SingleOrDefault(x => x is AuthorizeAttribute a && a.Policy == "policy2")); + Assert.IsNotNull(childField1.Attributes.SingleOrDefault(x => x is AuthorizeAttribute a && a.Policy == "policy3")); + + // ensure the order of applied attributes is parent field then child field + var i = 0; + foreach (var attrib in childField1.Attributes) + { + if (attrib is AuthorizeAttribute a && a.Policy == "policy1") + { + Assert.AreEqual(0, i); + i++; + } + else if (attrib is AuthorizeAttribute b && b.Policy == "policy2") + { + Assert.AreEqual(1, i); + i++; + } + else if (attrib is AuthorizeAttribute c && c.Policy == "policy3") + { + Assert.AreEqual(2, i); + i++; + } + } + + Assert.AreEqual(3, i); + + // three authorize attribs + primary + Assert.AreEqual(4, childField2.Attributes.Count()); + authCount = childField2.Attributes.Where(x => x is AuthorizeAttribute).Count(); + + Assert.AreEqual(3, authCount); + Assert.IsNotNull(childField2.Attributes.SingleOrDefault(x => x is AuthorizeAttribute a && a.Policy == "policy1")); + Assert.IsNotNull(childField2.Attributes.SingleOrDefault(x => x is AuthorizeAttribute a && a.Policy == "policy4")); + Assert.IsNotNull(childField2.Attributes.SingleOrDefault(x => x is AuthorizeAttribute a && a.Policy == "policy5")); + + i = 0; + foreach (var attrib in childField2.Attributes) + { + if (attrib is AuthorizeAttribute a && a.Policy == "policy1") + { + Assert.AreEqual(0, i); + i++; + } + else if (attrib is AuthorizeAttribute b && b.Policy == "policy4") + { + Assert.AreEqual(1, i); + i++; + } + else if (attrib is AuthorizeAttribute c && c.Policy == "policy5") + { + Assert.AreEqual(2, i); + i++; + } + } + + Assert.AreEqual(3, i); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/ResolvedFieldTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/ResolvedFieldTemplateTests.cs index 55a29325f..263f74b15 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/ResolvedFieldTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/ResolvedFieldTemplateTests.cs @@ -136,5 +136,25 @@ public void ResolvedField_SwappingOutResolvers_RemovesUnion() field.AddResolver((int a) => 0); Assert.AreEqual(0, field.Attributes.Count(x => x is UnionAttribute)); } + + [Test] + public void ResolvedField_PossibleTypeSwapping() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapQuery("/path1/path2", (string a) => (int?)1); + field.AddPossibleTypes(typeof(TwoPropertyObject), typeof(TwoPropertyObjectV2), typeof(TwoPropertyObjectV3)); + field.ClearPossibleTypes(); + field.AddPossibleTypes(typeof(TwoPropertyObject), typeof(TwoPropertyObjectV2)); + field.ClearPossibleTypes(); + field.AddPossibleTypes(typeof(TwoPropertyObject)); + + Assert.AreEqual(2, field.Attributes.Count()); + var possibleTypesAttrib = field.Attributes.SingleOrDefault(x => x is PossibleTypesAttribute) as PossibleTypesAttribute; + + Assert.AreEqual(1, possibleTypesAttrib.PossibleTypes.Count); + Assert.IsNotNull(possibleTypesAttrib.PossibleTypes.FirstOrDefault(x => x == typeof(TwoPropertyObject))); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTemplateTests.cs index 508cc9abd..09d47fe91 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTemplateTests.cs @@ -17,6 +17,7 @@ namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ControllerTestData; using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.DirectiveTestData; using NUnit.Framework; @@ -124,5 +125,95 @@ public void Parse_StaticMethodsWithProperGraphFieldDeclarations_AreSkipped() var action = Enumerable.First(template.Actions); Assert.AreEqual(nameof(ControllerWithStaticMethod.InstanceMethod), action.Name); } + + [Test] + public void Parse_UnionAttributeDefinedUnion_CreatesUnitonCorrectly() + { + var template = new GraphControllerTemplate(typeof(ControllerWithUnionAttributes)); + template.Parse(); + template.ValidateOrThrow(); + + var action = template.Actions.Single(x => x.InternalName.EndsWith(nameof(ControllerWithUnionAttributes.UnionDeclaredViaUnionAttribute))); + + Assert.IsNotNull(action.UnionProxy); + Assert.AreEqual("myUnion", action.UnionProxy.Name); + Assert.AreEqual(2, action.UnionProxy.Types.Count); + Assert.IsNotNull(action.UnionProxy.Types.Single(x => x == typeof(TwoPropertyObject))); + Assert.IsNotNull(action.UnionProxy.Types.Single(x => x == typeof(TwoPropertyObjectV2))); + } + + [Test] + public void Parse_UnionViaProxy_OnQuery() + { + var template = new GraphControllerTemplate(typeof(ControllerWithUnionAttributes)); + template.Parse(); + template.ValidateOrThrow(); + + var action = template.Actions.Single(x => x.InternalName.EndsWith(nameof(ControllerWithUnionAttributes.UnionViaProxyOnQuery))); + + Assert.IsNotNull(action.UnionProxy); + Assert.AreEqual("TestUnion", action.UnionProxy.Name); + Assert.AreEqual(1, action.UnionProxy.Types.Count); + Assert.IsNotNull(action.UnionProxy.Types.Single(x => x == typeof(TwoPropertyObject))); + } + + [Test] + public void Parse_UnionViaProxy_OnUnionAttribute() + { + var template = new GraphControllerTemplate(typeof(ControllerWithUnionAttributes)); + template.Parse(); + template.ValidateOrThrow(); + + var action = template.Actions.Single(x => x.InternalName.EndsWith(nameof(ControllerWithUnionAttributes.UnionViaProxyOnUnionAttribute))); + + Assert.IsNotNull(action.UnionProxy); + Assert.AreEqual("TestUnion", action.UnionProxy.Name); + Assert.AreEqual(1, action.UnionProxy.Types.Count); + Assert.IsNotNull(action.UnionProxy.Types.Single(x => x == typeof(TwoPropertyObject))); + } + + [Test] + public void Parse_UnionViaProxy_LotsOfUselessNulls_OnUnionAttribute() + { + var template = new GraphControllerTemplate(typeof(ControllerWithUnionAttributes)); + template.Parse(); + template.ValidateOrThrow(); + + var action = template.Actions.Single(x => x.InternalName.EndsWith(nameof(ControllerWithUnionAttributes.LotsOfNullsWithProxy))); + + Assert.IsNotNull(action.UnionProxy); + Assert.AreEqual("TestUnion", action.UnionProxy.Name); + Assert.AreEqual(1, action.UnionProxy.Types.Count); + Assert.IsNotNull(action.UnionProxy.Types.Single(x => x == typeof(TwoPropertyObject))); + } + + [Test] + public void Parse_UnionAttributeDefinedUnion_WithLotsOfNulls() + { + var template = new GraphControllerTemplate(typeof(ControllerWithUnionAttributes)); + template.Parse(); + template.ValidateOrThrow(); + + var action = template.Actions.Single(x => x.InternalName.EndsWith(nameof(ControllerWithUnionAttributes.LotsOfNullsWithDeclaration))); + + // only two actual types, all nulls are ignored + Assert.IsNotNull(action.UnionProxy); + Assert.AreEqual("myUnion2", action.UnionProxy.Name); + Assert.AreEqual(2, action.UnionProxy.Types.Count); + Assert.IsNotNull(action.UnionProxy.Types.Single(x => x == typeof(TwoPropertyObject))); + Assert.IsNotNull(action.UnionProxy.Types.Single(x => x == typeof(TwoPropertyObjectV2))); + } + + [Test] + public void Parse_DoubleDeclaredUnion_ThrowsException() + { + var template = new GraphControllerTemplate(typeof(ControllerWithDoubleDeclaredUnion)); + template.Parse(); + + var ex = Assert.Throws(() => + { + template.ValidateOrThrow(); + }); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/ControllerWithDoubleDeclaredUnion.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/ControllerWithDoubleDeclaredUnion.cs new file mode 100644 index 000000000..5a94be16a --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/ControllerWithDoubleDeclaredUnion.cs @@ -0,0 +1,26 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ControllerTestData +{ + using GraphQL.AspNet.Attributes; + using GraphQL.AspNet.Controllers; + using GraphQL.AspNet.Interfaces.Controllers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + + public class ControllerWithDoubleDeclaredUnion : GraphController + { + [Query("field", "myUnion", typeof(TwoPropertyObject))] + [Union("myUnion", typeof(TwoPropertyObject), typeof(TwoPropertyObjectV2))] + public IGraphActionResult UnionWithMixedTypeDeclaration() + { + return this.Ok(null); + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/ControllerWithUnionAttributes.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/ControllerWithUnionAttributes.cs new file mode 100644 index 000000000..1ce3372d9 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/ControllerWithUnionAttributes.cs @@ -0,0 +1,63 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ControllerTestData +{ + using GraphQL.AspNet.Attributes; + using GraphQL.AspNet.Controllers; + using GraphQL.AspNet.Interfaces.Controllers; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers.TestData; + + public class ControllerWithUnionAttributes : GraphController + { + [Query] + [Union("myUnion", typeof(TwoPropertyObject), typeof(TwoPropertyObjectV2))] + public IGraphActionResult UnionDeclaredViaUnionAttribute() + { + return this.Ok(null); + } + + [Query("field", "myUnion")] + [PossibleTypes(typeof(TwoPropertyObject), typeof(TwoPropertyObjectV2))] + public IGraphActionResult UnionWithMixedTypeDeclaration() + { + return this.Ok(null); + } + + [Query("field1", typeof(UnionWithInternalName))] + public IGraphActionResult UnionViaProxyOnQuery() + { + return this.Ok(null); + } + + [Query] + [Union(typeof(UnionWithInternalName))] + public IGraphActionResult UnionViaProxyOnUnionAttribute() + { + return this.Ok(null); + } + + [Query(returnType: null)] + [Union(typeof(UnionWithInternalName))] + [PossibleTypes(null, null, null, null)] + public IGraphActionResult LotsOfNullsWithProxy() + { + return this.Ok(null); + } + + [Query(returnType: typeof(TwoPropertyObject))] + [Union("myUnion2", typeof(TwoPropertyObjectV2), null, null)] + [PossibleTypes(null, null, null, null)] + public IGraphActionResult LotsOfNullsWithDeclaration() + { + return this.Ok(null); + } + } +} \ No newline at end of file From 6cb53ec988684fb1f9a204588a8a5688cfc861c3 Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Wed, 26 Jul 2023 05:43:19 -0700 Subject: [PATCH 53/63] WIP, more unit tests for minimal api coverage --- .../Attributes/QueryRootAttribute.cs | 6 +- ...ItemDefinitionExtensions_ResolvedFields.cs | 23 ---- ...ItemDefinitionExtensions_TypeExtensions.cs | 22 ---- .../MappedMutationTemplateTests.cs | 37 ++++++- .../MappedQueryGroupTests.cs | 39 +++++++ .../MappedTypeExtensionTemplateTests.cs | 101 ++++++++++++++---- .../ResolvedFieldTemplateTests.cs | 16 +++ 7 files changed, 175 insertions(+), 69 deletions(-) diff --git a/src/graphql-aspnet/Attributes/QueryRootAttribute.cs b/src/graphql-aspnet/Attributes/QueryRootAttribute.cs index b32714d6f..1614ef2cb 100644 --- a/src/graphql-aspnet/Attributes/QueryRootAttribute.cs +++ b/src/graphql-aspnet/Attributes/QueryRootAttribute.cs @@ -91,7 +91,11 @@ public QueryRootAttribute(string template, Type returnType) /// be sure to supply any additional concrete types so that they may be included in the object graph. /// Any additional types to include in the object graph on behalf of this method. public QueryRootAttribute(string template, Type returnType, params Type[] additionalTypes) - : base(true, SchemaItemCollections.Query, template, (new Type[] { returnType }).Concat(additionalTypes ?? Enumerable.Empty()).ToArray()) + : base( + true, + SchemaItemCollections.Query, + template, + (new Type[] { returnType }).Concat(additionalTypes ?? Enumerable.Empty()).ToArray()) { } diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_ResolvedFields.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_ResolvedFields.cs index cd5c2d77e..405a242b9 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_ResolvedFields.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_ResolvedFields.cs @@ -132,29 +132,6 @@ public static IGraphQLRuntimeResolvedFieldDefinition AddResolver( resolverMethod); } - /// - /// Sets the resolver to be used when this field is requested at runtime. - /// - /// - /// If this method is called more than once the previously set resolver will be replaced. - /// - /// The expected, primary return type of the field. Must be provided - /// if the supplied delegate returns an . - /// The field being built. - /// Provide a name and this field will be declared to return a union. Use to declare union members. - /// The delegate to assign as the resolver. This method will be - /// parsed to determine input arguments for the field on the target schema. - /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeResolvedFieldDefinition AddResolver(this IGraphQLRuntimeResolvedFieldDefinition fieldBuilder, string unionName, Delegate resolverMethod) - { - Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); - return AddResolverInternal( - fieldBuilder, - typeof(TReturnType), - unionName, - resolverMethod); - } - /// /// Sets the resolver to be used when this field is requested at runtime. /// diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_TypeExtensions.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_TypeExtensions.cs index 17f4af7e3..c7b1a51c2 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_TypeExtensions.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_TypeExtensions.cs @@ -433,27 +433,5 @@ public static IGraphQLRuntimeTypeExtensionDefinition AddResolver(this IGraphQLRu unionName, resolverMethod); } - - /// - /// Sets the resolver to be used when this field is requested at runtime. - /// - /// - /// If this method is called more than once the previously set resolver will be replaced. - /// - /// The expected, primary return type of the field. Must be provided - /// if the supplied delegate returns an . - /// The field being built. - /// Provide a name and this field will be declared to return a union. Use to declare union members. - /// The delegate to assign as the resolver. This method will be - /// parsed to determine input arguments for the field on the target schema. - /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeTypeExtensionDefinition AddResolver(this IGraphQLRuntimeTypeExtensionDefinition fieldBuilder, string unionName, Delegate resolverMethod) - { - return AddResolverInternal( - fieldBuilder, - typeof(TReturnType), - unionName, - resolverMethod); - } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedMutationTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedMutationTemplateTests.cs index ca7d408cc..bfc17f41d 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedMutationTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedMutationTemplateTests.cs @@ -72,9 +72,9 @@ public void MapMutation_WithUnionNameSetToNull_AddsUnionNameToType() var services = new ServiceCollection(); var options = new SchemaOptions(services); - var typeExt = options.MapMutation("myField", null, (string a) => 1); + var field = options.MapMutation("myField", null, (string a) => 1); - var attrib = typeExt.Attributes.OfType().SingleOrDefault(); + var attrib = field.Attributes.OfType().SingleOrDefault(); Assert.IsNull(attrib); } @@ -85,11 +85,40 @@ public void MapMutation_WithUnionName0_AddsUnionNameToType() var services = new ServiceCollection(); var options = new SchemaOptions(services); - var typeExt = options.MapMutation("myField", "myUnion", (string a) => 1); + var field = options.MapMutation("myField", "myUnion", (string a) => 1); - var attrib = typeExt.Attributes.OfType().SingleOrDefault(); + var attrib = field.Attributes.OfType().SingleOrDefault(); Assert.AreEqual("myUnion", attrib.UnionName); } + + [Test] + public void MapMutation_WithNoResolver_IsCreated() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapMutation("myField"); + + Assert.IsNull(field.Resolver); + Assert.IsNull(field.ReturnType); + + Assert.IsTrue(options.RuntimeTemplates.Contains(field)); + } + + [Test] + public void MapMutation_WithResolver_AndUnion_IsCreated() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapMutation("myField", "myUnion", () => 1); + + Assert.IsNotNull(field.Resolver); + + Assert.AreEqual(1, field.Attributes.OfType().Count()); + Assert.AreEqual("myUnion", field.Attributes.OfType().Single().UnionName); + Assert.IsTrue(options.RuntimeTemplates.Contains(field)); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedQueryGroupTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedQueryGroupTests.cs index db4ab22d4..f99279994 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedQueryGroupTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedQueryGroupTests.cs @@ -137,6 +137,45 @@ public void MapQueryGroup_SingleCopyAttribute_AppliedToGroupAndField_IsOnlyAppli Assert.AreEqual(1, anonCount); } + [Test] + public void MapField_WithNoResovler_FieldIsMade_ResolverIsNotSet() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var childField = options.MapQueryGroup("/path1/path2") + .MapField("myField"); + + Assert.IsNull(childField.Resolver); + } + + [Test] + public void MapField_WithResovler_AndUnion_BothAreSet() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var childField = options.MapQueryGroup("/path1/path2") + .MapField("myField", "myUnion", () => 1); + + Assert.IsNotNull(childField.Resolver); + Assert.AreEqual(1, childField.Attributes.OfType().Count()); + Assert.AreEqual("myUnion", childField.Attributes.OfType().Single().UnionName); + } + + [Test] + public void MapField_WithResovler_AndExplicitReturnType_IsMapped() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var childField = options.MapQueryGroup("/path1/path2") + .MapField("myField", () => 1); + + Assert.IsNotNull(childField.Resolver); + Assert.AreEqual(typeof(int?), childField.ReturnType); + } + [Test] public void MapQueryGroup_MultipleCopyAttribute_AppliedToGroupAndField_IsAppliedMultipleTimes() { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedTypeExtensionTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedTypeExtensionTemplateTests.cs index 3b4bbc541..ba5c8f21c 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedTypeExtensionTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedTypeExtensionTemplateTests.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Schemas.Generation.RuntimeFieldDeclarations +namespace GraphQL.AspNet.Tests.Schemas.Generation.RuntimetypeExtDeclarations { using System.Linq; using GraphQL.AspNet.Attributes; @@ -31,12 +31,12 @@ public void MapTypeExtension_ByOptions_AddsTypeExtensionToOptions() var services = new ServiceCollection(); var options = new SchemaOptions(services); - var typeExt = options.MapTypeExtension("myField"); + var typeExt = options.MapTypeExtension("mytypeExt"); Assert.IsInstanceOf(typeof(IGraphQLRuntimeTypeExtensionDefinition), typeExt); Assert.AreEqual(1, options.RuntimeTemplates.Count()); Assert.IsNotNull(options.RuntimeTemplates.FirstOrDefault(x => x == typeExt)); - Assert.AreEqual("[type]/TwoPropertyObject/myField", typeExt.Route.Path); + Assert.AreEqual("[type]/TwoPropertyObject/mytypeExt", typeExt.Route.Path); Assert.IsNull(typeExt.ReturnType); Assert.IsNull(typeExt.Resolver); Assert.AreEqual(FieldResolutionMode.PerSourceItem, typeExt.ExecutionMode); @@ -56,10 +56,10 @@ public void MapTypeExtension_WithName_AddsInternalName() var builderMock = new Mock(); builderMock.Setup(x => x.Options).Returns(options); - var typeExt = options.MapTypeExtension("myField") - .WithName("internalFieldName"); + var typeExt = options.MapTypeExtension("mytypeExt") + .WithName("internaltypeExtName"); - Assert.AreEqual("internalFieldName", typeExt.InternalName); + Assert.AreEqual("internaltypeExtName", typeExt.InternalName); } [Test] @@ -71,7 +71,7 @@ public void MapTypeExtension_ByBuilder_AddsTypeExtensionToOptions() var builderMock = new Mock(); builderMock.Setup(x => x.Options).Returns(options); - var typeExt = options.MapTypeExtension("myField"); + var typeExt = options.MapTypeExtension("mytypeExt"); Assert.IsInstanceOf(typeof(IGraphQLRuntimeTypeExtensionDefinition), typeExt); Assert.AreEqual(1, options.RuntimeTemplates.Count()); @@ -85,12 +85,12 @@ public void MapTypeExtension_ByOptions_WithResolver_AddsTypeExtensionToOptions() var services = new ServiceCollection(); var options = new SchemaOptions(services); - var typeExt = options.MapTypeExtension("myField", (string a) => 1); + var typeExt = options.MapTypeExtension("mytypeExt", (string a) => 1); Assert.IsInstanceOf(typeof(IGraphQLRuntimeTypeExtensionDefinition), typeExt); Assert.AreEqual(1, options.RuntimeTemplates.Count()); Assert.IsNotNull(options.RuntimeTemplates.FirstOrDefault(x => x == typeExt)); - Assert.AreEqual("[type]/TwoPropertyObject/myField", typeExt.Route.Path); + Assert.AreEqual("[type]/TwoPropertyObject/mytypeExt", typeExt.Route.Path); Assert.IsNull(typeExt.ReturnType); Assert.AreEqual(typeof(int), typeExt.Resolver.Method.ReturnType); } @@ -104,7 +104,7 @@ public void MapTypeExtension_ByBuilder_WithResolver_AddsTypeExtensionToOptions() var builderMock = new Mock(); builderMock.Setup(x => x.Options).Returns(options); - var typeExt = options.MapTypeExtension("myField", (string a) => 1); + var typeExt = options.MapTypeExtension("mytypeExt", (string a) => 1); Assert.IsInstanceOf(typeof(IGraphQLRuntimeTypeExtensionDefinition), typeExt); Assert.AreEqual(1, options.RuntimeTemplates.Count()); @@ -119,7 +119,7 @@ public void MappedTypeExtension_WhenAllowAnonymousAdded_AddsAnonymousAttribute() var services = new ServiceCollection(); var options = new SchemaOptions(services); - var typeExt = options.MapTypeExtension("myField", (string a) => 1); + var typeExt = options.MapTypeExtension("mytypeExt", (string a) => 1); typeExt.AllowAnonymous(); @@ -133,7 +133,7 @@ public void MappedTypeExtension_WhenRequireAuthAdded_AddsAuthAttribute() var services = new ServiceCollection(); var options = new SchemaOptions(services); - var typeExt = options.MapTypeExtension("myField", (string a) => 1); + var typeExt = options.MapTypeExtension("mytypeExt", (string a) => 1); typeExt.RequireAuthorization("policy1", "roles1"); @@ -150,7 +150,7 @@ public void MappedTypeExtension_WhenResolverIsChangedWithExplicitType_NewResolve var services = new ServiceCollection(); var options = new SchemaOptions(services); - var typeExt = options.MapTypeExtension("myField", (string a) => 1); + var typeExt = options.MapTypeExtension("mytypeExt", (string a) => 1); Assert.AreEqual(typeof(int), typeExt.Resolver.Method.ReturnType); typeExt.AddResolver((string a) => "bob"); @@ -164,7 +164,7 @@ public void MappedTypeExtension_WithBatchProcessing_ChangesExecutionMode() var services = new ServiceCollection(); var options = new SchemaOptions(services); - var typeExt = options.MapTypeExtension("myField", (string a) => 1); + var typeExt = options.MapTypeExtension("mytypeExt", (string a) => 1); Assert.AreEqual(FieldResolutionMode.PerSourceItem, typeExt.ExecutionMode); typeExt.WithBatchProcessing(); @@ -180,7 +180,7 @@ public void MappedTypeExtension_AddPossibleTypes_AddsAppropriateAttribute() var services = new ServiceCollection(); var options = new SchemaOptions(services); - var typeExt = options.MapTypeExtension("myField", (string a) => 1); + var typeExt = options.MapTypeExtension("mytypeExt", (string a) => 1); typeExt.AddPossibleTypes(typeof(TwoPropertyObjectV2), typeof(TwoPropertyObjectV3)); Assert.AreEqual(2, typeExt.Attributes.Count()); @@ -197,7 +197,7 @@ public void MappedTypeExtension_WithoutUnionName_AddsUnionNameToType() var services = new ServiceCollection(); var options = new SchemaOptions(services); - var typeExt = options.MapTypeExtension("myField", null, (string a) => 1); + var typeExt = options.MapTypeExtension("mytypeExt", null, (string a) => 1); var attrib = typeExt.Attributes.OfType().SingleOrDefault(); @@ -210,7 +210,7 @@ public void MappedTypeExtension_WithUnionName0_AddsUnionNameToType() var services = new ServiceCollection(); var options = new SchemaOptions(services); - var typeExt = options.MapTypeExtension("myField", "myUnion", (string a) => 1); + var typeExt = options.MapTypeExtension("mytypeExt", "myUnion", (string a) => 1); var attrib = typeExt.Attributes.OfType().SingleOrDefault(); @@ -218,17 +218,80 @@ public void MappedTypeExtension_WithUnionName0_AddsUnionNameToType() } [Test] - public void ResolvedField_SwappingOutResolvers_RemovesUnion() + public void MappedTypeExension_SwappingOutResolvers_RemovesUnion() { var services = new ServiceCollection(); var options = new SchemaOptions(services); - var typeExt = options.MapTypeExtension("myField", "myUnion", (string a) => 1); + var typeExt = options.MapTypeExtension("mytypeExt", "myUnion", (string a) => 1); Assert.AreEqual(1, typeExt.Attributes.Count(x => x is UnionAttribute)); // union is removed when resolver is re-declared typeExt.AddResolver((int a) => 0); Assert.AreEqual(0, typeExt.Attributes.Count(x => x is UnionAttribute)); } + + [Test] + public void MappedTypeExension_NoResolver_CreatesField() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var typeExt = options.MapTypeExtension("mytypeExt"); + Assert.AreEqual(1, typeExt.Attributes.Count()); + + // No Resolver is Set + Assert.IsNull(typeExt.Resolver); + } + + [Test] + public void MappedTypeExension_AddingUnionViaAddResolver_UnionIsApplied() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + // no union + var typeExt = options.MapTypeExtension("path2", (string a) => (int?)1); + + // union added + typeExt.AddResolver("myUnion", () => 0); + Assert.AreEqual(1, typeExt.Attributes.Count(x => x is UnionAttribute)); + Assert.AreEqual("myUnion", typeExt.Attributes.OfType().Single().UnionName); + } + + [Test] + public void MappedTypeExension_AddingResolver_WithExplicitReturnType_WithUnion_UnionIsApplied() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + // no union + var typeExt = options.MapTypeExtension("path2", (string a) => (int?)1); + + // union added + typeExt.AddResolver("myUnion", () => 0); + Assert.AreEqual(1, typeExt.Attributes.Count(x => x is UnionAttribute)); + Assert.AreEqual("myUnion", typeExt.Attributes.OfType().Single().UnionName); + } + + [Test] + public void MappedTypeExension_PossibleTypeSwapping() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var typeExt = options.MapTypeExtension("mytypeExt", (string a) => 1); + typeExt.AddPossibleTypes(typeof(TwoPropertyObject), typeof(TwoPropertyObjectV2), typeof(TwoPropertyObjectV3)); + typeExt.ClearPossibleTypes(); + typeExt.AddPossibleTypes(typeof(TwoPropertyObject), typeof(TwoPropertyObjectV2)); + typeExt.ClearPossibleTypes(); + typeExt.AddPossibleTypes(typeof(TwoPropertyObject)); + + Assert.AreEqual(2, typeExt.Attributes.Count()); + var possibleTypesAttrib = typeExt.Attributes.SingleOrDefault(x => x is PossibleTypesAttribute) as PossibleTypesAttribute; + + Assert.AreEqual(1, possibleTypesAttrib.PossibleTypes.Count); + Assert.IsNotNull(possibleTypesAttrib.PossibleTypes.FirstOrDefault(x => x == typeof(TwoPropertyObject))); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/ResolvedFieldTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/ResolvedFieldTemplateTests.cs index 263f74b15..12a72312f 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/ResolvedFieldTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/ResolvedFieldTemplateTests.cs @@ -156,5 +156,21 @@ public void ResolvedField_PossibleTypeSwapping() Assert.AreEqual(1, possibleTypesAttrib.PossibleTypes.Count); Assert.IsNotNull(possibleTypesAttrib.PossibleTypes.FirstOrDefault(x => x == typeof(TwoPropertyObject))); } + + [Test] + public void ResolvedField_AddingUnionViaAddResolver_UnionIsApplied() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + // no union + var field = options.MapQuery("/path1/path2", (string a) => (int?)1); + + // union added + field.AddResolver("myUnion", () => 0); + + Assert.AreEqual(1, field.Attributes.Count(x => x is UnionAttribute)); + Assert.AreEqual("myUnion", field.Attributes.OfType().Single().UnionName); + } } } \ No newline at end of file From 1690204b1d42516a118237a2b4c9cd64a2fd185d Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Fri, 28 Jul 2023 20:45:26 -0700 Subject: [PATCH 54/63] WIP, moar unit tests. --- .../Startup/GraphSchemaBuilder.cs | 2 +- .../Attributes/AttributeDataIntegrityTests.cs | 80 +++++++++++++++++++ .../Configuration/GraphSchemaBuilderTests.cs | 79 ++++++++++++++++++ .../MultiConstructorSchemWithDefaultValues.cs | 34 ++++++++ .../MultiConstructorSchema.cs | 40 ++++++++++ .../SchemaBuildTestData/OneServiceSchema.cs | 22 +++++ .../SchemaBuildTestData/TestService1.cs | 16 ++++ .../SchemaBuildTestData/TestService2.cs | 16 ++++ .../SchemaBuildTestData/TestService3.cs | 16 ++++ .../MappedMutationGroupTests.cs | 21 +++++ .../MappedMutationTemplateTests.cs | 43 ++++++++++ .../MappedQueryGroupTests.cs | 28 +++++++ .../MappedQueryTemplateTests.cs | 40 ++++++++++ .../MappedTypeExtensionTemplateTests.cs | 80 ++++++++++++++++++- .../ResolvedFieldTemplateTests.cs | 40 ++++++++++ 15 files changed, 553 insertions(+), 4 deletions(-) create mode 100644 src/unit-tests/graphql-aspnet-tests/Configuration/GraphSchemaBuilderTests.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Configuration/SchemaBuildTestData/MultiConstructorSchemWithDefaultValues.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Configuration/SchemaBuildTestData/MultiConstructorSchema.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Configuration/SchemaBuildTestData/OneServiceSchema.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Configuration/SchemaBuildTestData/TestService1.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Configuration/SchemaBuildTestData/TestService2.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Configuration/SchemaBuildTestData/TestService3.cs diff --git a/src/graphql-aspnet/Configuration/Startup/GraphSchemaBuilder.cs b/src/graphql-aspnet/Configuration/Startup/GraphSchemaBuilder.cs index 4c60b8386..3e1251cea 100644 --- a/src/graphql-aspnet/Configuration/Startup/GraphSchemaBuilder.cs +++ b/src/graphql-aspnet/Configuration/Startup/GraphSchemaBuilder.cs @@ -42,7 +42,7 @@ public static TSchema BuildSchema(IServiceProvider sp) where TSchema : class, ISchema { // the whole point of this method is to try every possible combination - // of parameters and give out a friendly error message if nothing works. + // of parameters and give out a friendly error message instead of using the service provider cryptic error message. Validation.ThrowIfNull(sp, nameof(sp)); List paramSet = null; if (!SCHEMA_CONSTRUCTORS.TryGetValue(typeof(TSchema), out var schemaConstructor)) diff --git a/src/unit-tests/graphql-aspnet-tests/Attributes/AttributeDataIntegrityTests.cs b/src/unit-tests/graphql-aspnet-tests/Attributes/AttributeDataIntegrityTests.cs index da9bbb75f..2e2a275eb 100644 --- a/src/unit-tests/graphql-aspnet-tests/Attributes/AttributeDataIntegrityTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Attributes/AttributeDataIntegrityTests.cs @@ -135,6 +135,46 @@ public void QueryAttribute_UnionConstructor_PropertyCheck() Assert.AreEqual(FieldResolutionMode.PerSourceItem, attrib.ExecutionMode); } + [Test] + public void QueryAttribute_UnionConstructor_1Type_PropertyCheck() + { + var attrib = new QueryAttribute("myField", "myUnionType", typeof(AttributeDataIntegrityTests)); + Assert.AreEqual(SchemaItemCollections.Query, attrib.FieldType); + Assert.AreEqual(false, attrib.IsRootFragment); + Assert.AreEqual("myUnionType", attrib.UnionTypeName); + Assert.AreEqual("myField", attrib.Template); + Assert.AreEqual(null, attrib.TypeExpression); + Assert.AreEqual(1, attrib.Types.Count); + Assert.AreEqual(typeof(AttributeDataIntegrityTests), attrib.Types[0]); + Assert.AreEqual(FieldResolutionMode.PerSourceItem, attrib.ExecutionMode); + } + + [Test] + public void QueryAttribute_UnionConstructor_NoTypes_PropertyCheck() + { + var attrib = new QueryAttribute("myField", "myUnionType"); + Assert.AreEqual(SchemaItemCollections.Query, attrib.FieldType); + Assert.AreEqual(false, attrib.IsRootFragment); + Assert.AreEqual("myUnionType", attrib.UnionTypeName); + Assert.AreEqual("myField", attrib.Template); + Assert.AreEqual(null, attrib.TypeExpression); + Assert.AreEqual(0, attrib.Types.Count); + Assert.AreEqual(FieldResolutionMode.PerSourceItem, attrib.ExecutionMode); + } + + [Test] + public void QueryAttribute_UnionConstructor_NullTypes_PropertyCheck() + { + var attrib = new QueryAttribute("myField", "myUnionType", null, null, null); + Assert.AreEqual(SchemaItemCollections.Query, attrib.FieldType); + Assert.AreEqual(false, attrib.IsRootFragment); + Assert.AreEqual("myUnionType", attrib.UnionTypeName); + Assert.AreEqual("myField", attrib.Template); + Assert.AreEqual(null, attrib.TypeExpression); + Assert.AreEqual(0, attrib.Types.Count); + Assert.AreEqual(FieldResolutionMode.PerSourceItem, attrib.ExecutionMode); + } + [Test] public void MutationAttribute_EmptyConstructor_PropertyCheck() { @@ -220,6 +260,46 @@ public void MutationAttribute_UnionConstructor_PropertyCheck() Assert.AreEqual(FieldResolutionMode.PerSourceItem, attrib.ExecutionMode); } + [Test] + public void MutationAttribute_UnionConstructor_1Type_PropertyCheck() + { + var attrib = new MutationAttribute("myField", "myUnionType", typeof(AttributeDataIntegrityTests)); + Assert.AreEqual(SchemaItemCollections.Mutation, attrib.FieldType); + Assert.AreEqual(false, attrib.IsRootFragment); + Assert.AreEqual("myUnionType", attrib.UnionTypeName); + Assert.AreEqual("myField", attrib.Template); + Assert.AreEqual(null, attrib.TypeExpression); + Assert.AreEqual(1, attrib.Types.Count); + Assert.AreEqual(typeof(AttributeDataIntegrityTests), attrib.Types[0]); + Assert.AreEqual(FieldResolutionMode.PerSourceItem, attrib.ExecutionMode); + } + + [Test] + public void MutationAttribute_UnionConstructor_NoTypes_PropertyCheck() + { + var attrib = new MutationAttribute("myField", "myUnionType"); + Assert.AreEqual(SchemaItemCollections.Mutation, attrib.FieldType); + Assert.AreEqual(false, attrib.IsRootFragment); + Assert.AreEqual("myUnionType", attrib.UnionTypeName); + Assert.AreEqual("myField", attrib.Template); + Assert.AreEqual(null, attrib.TypeExpression); + Assert.AreEqual(0, attrib.Types.Count); + Assert.AreEqual(FieldResolutionMode.PerSourceItem, attrib.ExecutionMode); + } + + [Test] + public void MutationAttribute_UnionConstructor_NullTypes_PropertyCheck() + { + var attrib = new MutationAttribute("myField", "myUnionType", null, null, null); + Assert.AreEqual(SchemaItemCollections.Mutation, attrib.FieldType); + Assert.AreEqual(false, attrib.IsRootFragment); + Assert.AreEqual("myUnionType", attrib.UnionTypeName); + Assert.AreEqual("myField", attrib.Template); + Assert.AreEqual(null, attrib.TypeExpression); + Assert.AreEqual(0, attrib.Types.Count); + Assert.AreEqual(FieldResolutionMode.PerSourceItem, attrib.ExecutionMode); + } + [Test] public void QueryRootAttribute_EmptyConstructor_PropertyCheck() { diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/GraphSchemaBuilderTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/GraphSchemaBuilderTests.cs new file mode 100644 index 000000000..7604caa43 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/GraphSchemaBuilderTests.cs @@ -0,0 +1,79 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Configuration +{ + using GraphQL.AspNet.Configuration.Startup; + using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Tests.Configuration.SchemaBuildTestData; + using Microsoft.Extensions.DependencyInjection; + using NUnit.Framework; + + [TestFixture] + public class GraphSchemaBuilderTests + { + [Test] + public void SimpleSchema_IsRenderedOut() + { + var collection = new ServiceCollection(); + collection.AddSingleton(); + + var provider = collection.BuildServiceProvider(); + var scope = provider.CreateScope(); + + var schema = GraphSchemaBuilder.BuildSchema(scope.ServiceProvider); + + Assert.IsNotNull(schema); + } + + [Test] + public void SchemaWithOneAvailableService_IsRenderedOut() + { + var collection = new ServiceCollection(); + collection.AddSingleton(); + collection.AddSingleton(); + + var provider = collection.BuildServiceProvider(); + var scope = provider.CreateScope(); + + var schema = GraphSchemaBuilder.BuildSchema(scope.ServiceProvider); + Assert.IsNotNull(schema); + } + + [Test] + public void MultipleConstructors_ButOnlyOneMatches_CorrectConstructorIsUsed() + { + var collection = new ServiceCollection(); + collection.AddSingleton(); + collection.AddSingleton(); + + var provider = collection.BuildServiceProvider(); + var scope = provider.CreateScope(); + + var schema = GraphSchemaBuilder.BuildSchema(scope.ServiceProvider); + Assert.IsNotNull(schema); + Assert.AreEqual(1, schema.PropValue); + } + + [Test] + public void MultipleConstructors_ButOnlyOneMatches_ButHasDefaultValues_CorrectConstructorIsUsed() + { + var collection = new ServiceCollection(); + collection.AddSingleton(); + collection.AddSingleton(); + + var provider = collection.BuildServiceProvider(); + var scope = provider.CreateScope(); + + var schema = GraphSchemaBuilder.BuildSchema(scope.ServiceProvider); + Assert.IsNotNull(schema); + Assert.AreEqual(3, schema.PropValue); + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/SchemaBuildTestData/MultiConstructorSchemWithDefaultValues.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/SchemaBuildTestData/MultiConstructorSchemWithDefaultValues.cs new file mode 100644 index 000000000..c920f5db6 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/SchemaBuildTestData/MultiConstructorSchemWithDefaultValues.cs @@ -0,0 +1,34 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Configuration.SchemaBuildTestData +{ + using System; + using GraphQL.AspNet.Schemas; + + public class MultiConstructorSchemWithDefaultValues : GraphSchema + { + public MultiConstructorSchemWithDefaultValues(TestService1 service) + { + this.PropValue = 1; + } + + public MultiConstructorSchemWithDefaultValues(TestService1 service, TestService2 service2) + { + this.PropValue = 2; + } + + public MultiConstructorSchemWithDefaultValues(TestService1 service = null, TestService2 service2 = null, TestService3 service3 = null) + { + this.PropValue = 3; + } + + public int PropValue { get; set; } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/SchemaBuildTestData/MultiConstructorSchema.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/SchemaBuildTestData/MultiConstructorSchema.cs new file mode 100644 index 000000000..156365f6c --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/SchemaBuildTestData/MultiConstructorSchema.cs @@ -0,0 +1,40 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Configuration.SchemaBuildTestData +{ + using System; + using GraphQL.AspNet.Schemas; + + public class MultiConstructorSchema : GraphSchema + { + public MultiConstructorSchema(TestService1 service) + { + ArgumentNullException.ThrowIfNull(service, nameof(service)); + this.PropValue = 1; + } + + public MultiConstructorSchema(TestService1 service, TestService2 service2) + { + ArgumentNullException.ThrowIfNull(service, nameof(service)); + ArgumentNullException.ThrowIfNull(service2, nameof(service2)); + this.PropValue = 2; + } + + public MultiConstructorSchema(TestService1 service, TestService2 service2, TestService3 service3) + { + ArgumentNullException.ThrowIfNull(service, nameof(service)); + ArgumentNullException.ThrowIfNull(service2, nameof(service2)); + ArgumentNullException.ThrowIfNull(service3, nameof(service3)); + this.PropValue = 3; + } + + public int PropValue { get; set; } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/SchemaBuildTestData/OneServiceSchema.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/SchemaBuildTestData/OneServiceSchema.cs new file mode 100644 index 000000000..d15c71781 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/SchemaBuildTestData/OneServiceSchema.cs @@ -0,0 +1,22 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Configuration.SchemaBuildTestData +{ + using System; + using GraphQL.AspNet.Schemas; + + public class OneServiceSchema : GraphSchema + { + public OneServiceSchema(TestService1 service) + { + ArgumentNullException.ThrowIfNull(service, nameof(service)); + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/SchemaBuildTestData/TestService1.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/SchemaBuildTestData/TestService1.cs new file mode 100644 index 000000000..aaa43d3b7 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/SchemaBuildTestData/TestService1.cs @@ -0,0 +1,16 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Configuration.SchemaBuildTestData +{ + public class TestService1 + { + public int Prop1 { get; set; } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/SchemaBuildTestData/TestService2.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/SchemaBuildTestData/TestService2.cs new file mode 100644 index 000000000..6bad91de6 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/SchemaBuildTestData/TestService2.cs @@ -0,0 +1,16 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Configuration.SchemaBuildTestData +{ + public class TestService2 + { + public int Prop1 { get; set; } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/SchemaBuildTestData/TestService3.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/SchemaBuildTestData/TestService3.cs new file mode 100644 index 000000000..84cb27b08 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/SchemaBuildTestData/TestService3.cs @@ -0,0 +1,16 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Configuration.SchemaBuildTestData +{ + public class TestService3 + { + public int Prop1 { get; set; } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedMutationGroupTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedMutationGroupTests.cs index 701b7a19a..74aa0704b 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedMutationGroupTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedMutationGroupTests.cs @@ -12,9 +12,11 @@ namespace GraphQL.AspNet.Tests.Schemas.Generation.RuntimeFieldDeclarations using System.Linq; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Interfaces.Configuration; using GraphQL.AspNet.Schemas; using Microsoft.AspNetCore.Authorization; using Microsoft.Extensions.DependencyInjection; + using Moq; using NUnit.Framework; [TestFixture] @@ -92,6 +94,7 @@ public void MapMutationGroup_WhenResolvedChildFieldIsAdded_PathIsCorrect() var childField = field.MapField("/path3/path4", (string a) => 1); Assert.AreEqual("[mutation]/path1/path2/path3/path4", childField.Route.Path); + Assert.AreEqual(1, childField.Attributes.Count(x => x is MutationRootAttribute)); } [Test] @@ -105,6 +108,7 @@ public void MapMutationGroup_WhenResolvedChildFieldIsAddedToUnresolvedChildField var resolvedField = childField.MapField("/path5/path6", (string a) => 1); Assert.AreEqual("[mutation]/path1/path2/path3/path4/path5/path6", resolvedField.Route.Path); + Assert.AreEqual(1, resolvedField.Attributes.Count(x => x is MutationRootAttribute)); Assert.IsNotNull(resolvedField.Resolver); } @@ -119,6 +123,23 @@ public void MapMutationGroup_WhenResolvedChildFieldIsAdded_AndParentPathIsChange var childField = field.MapField("/path3/path4", (string a) => 1); Assert.AreEqual("[mutation]/path1/path2/path3/path4", childField.Route.Path); + Assert.AreEqual(1, childField.Attributes.Count(x => x is MutationRootAttribute)); + } + + [Test] + public void MapField_FromSchemaBuilder_WithNoResovler_FieldIsMade_ResolverIsNotSet() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var builderMock = new Mock(); + builderMock.Setup(x => x.Options).Returns(options); + + var childField = builderMock.Object.MapMutationGroup("/path1/path2") + .MapField("myField"); + + Assert.IsNull(childField.Resolver); + Assert.AreEqual(1, childField.Attributes.Count(x => x is MutationRootAttribute)); } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedMutationTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedMutationTemplateTests.cs index bfc17f41d..14ee79d42 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedMutationTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedMutationTemplateTests.cs @@ -56,6 +56,28 @@ public void MapMutation_FromBuilder_WithDelegate_DoesAddFieldToSchema() var field = builderMock.Object.MapMutation("/path1/path2", TestDelegate); + Assert.IsNotNull(field); + Assert.AreEqual("[mutation]/path1/path2", field.Route.Path); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeResolvedFieldDefinition), field); + Assert.AreEqual(1, options.RuntimeTemplates.Count()); + Assert.IsNotNull(field.Resolver); + + Assert.AreEqual(1, field.Attributes.Count()); + var mutationRootAttrib = field.Attributes.FirstOrDefault(x => x.GetType() == typeof(MutationRootAttribute)); + Assert.IsNotNull(mutationRootAttrib); + } + + [Test] + public void MapMutation_FromBuilder_WithNoDelegate_DoesAddFieldToSchema() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var builderMock = new Mock(); + builderMock.Setup(x => x.Options).Returns(options); + + var field = builderMock.Object.MapMutation("/path1/path2"); + Assert.IsNotNull(field); Assert.AreEqual("[mutation]/path1/path2", field.Route.Path); Assert.IsInstanceOf(typeof(IGraphQLRuntimeResolvedFieldDefinition), field); @@ -66,6 +88,23 @@ public void MapMutation_FromBuilder_WithDelegate_DoesAddFieldToSchema() Assert.IsNotNull(mutationRootAttrib); } + [Test] + public void MapMutation_FromBuilder_WithUnionName0_AddsUnionNameToType() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var builderMock = new Mock(); + builderMock.Setup(x => x.Options).Returns(options); + + var field = builderMock.Object.MapMutation("myField", "myUnion", (string a) => 1); + + var attrib = field.Attributes.OfType().SingleOrDefault(); + + Assert.AreEqual("myUnion", attrib.UnionName); + Assert.AreEqual(1, field.Attributes.Count(x => x is MutationRootAttribute)); + } + [Test] public void MapMutation_WithUnionNameSetToNull_AddsUnionNameToType() { @@ -77,6 +116,7 @@ public void MapMutation_WithUnionNameSetToNull_AddsUnionNameToType() var attrib = field.Attributes.OfType().SingleOrDefault(); Assert.IsNull(attrib); + Assert.AreEqual(1, field.Attributes.Count(x => x is MutationRootAttribute)); } [Test] @@ -90,6 +130,7 @@ public void MapMutation_WithUnionName0_AddsUnionNameToType() var attrib = field.Attributes.OfType().SingleOrDefault(); Assert.AreEqual("myUnion", attrib.UnionName); + Assert.AreEqual(1, field.Attributes.Count(x => x is MutationRootAttribute)); } [Test] @@ -104,6 +145,7 @@ public void MapMutation_WithNoResolver_IsCreated() Assert.IsNull(field.ReturnType); Assert.IsTrue(options.RuntimeTemplates.Contains(field)); + Assert.AreEqual(1, field.Attributes.Count(x => x is MutationRootAttribute)); } [Test] @@ -119,6 +161,7 @@ public void MapMutation_WithResolver_AndUnion_IsCreated() Assert.AreEqual(1, field.Attributes.OfType().Count()); Assert.AreEqual("myUnion", field.Attributes.OfType().Single().UnionName); Assert.IsTrue(options.RuntimeTemplates.Contains(field)); + Assert.AreEqual(1, field.Attributes.Count(x => x is MutationRootAttribute)); } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedQueryGroupTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedQueryGroupTests.cs index f99279994..a9bd69d03 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedQueryGroupTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedQueryGroupTests.cs @@ -12,9 +12,11 @@ namespace GraphQL.AspNet.Tests.Schemas.Generation.RuntimeFieldDeclarations using System.Linq; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Interfaces.Configuration; using GraphQL.AspNet.Schemas; using Microsoft.AspNetCore.Authorization; using Microsoft.Extensions.DependencyInjection; + using Moq; using NUnit.Framework; [TestFixture] @@ -75,6 +77,7 @@ public void MapQueryGroup_WhenResolvedChildFieldIsAdded_PathIsCorrect() var childField = field.MapField("/path3/path4", (string a) => 1); Assert.AreEqual("[query]/path1/path2/path3/path4", childField.Route.Path); + Assert.AreEqual(1, childField.Attributes.Count(x => x is QueryRootAttribute)); } [Test] @@ -106,6 +109,7 @@ public void MapQueryGroup_WhenResolvedChildFieldIsAddedToUnresolvedChildField_Pa Assert.AreEqual("[query]/path1/path2/path3/path4/path5/path6", resolvedField.Route.Path); Assert.IsNotNull(resolvedField.Resolver); + Assert.AreEqual(1, resolvedField.Attributes.Count(x => x is QueryRootAttribute)); } [Test] @@ -119,6 +123,7 @@ public void MapQueryGroup_WhenResolvedChildFieldIsAdded_AndParentPathIsChanged_P var childField = field.MapField("/path3/path4", (string a) => 1); Assert.AreEqual("[query]/path1/path2/path3/path4", childField.Route.Path); + Assert.AreEqual(1, childField.Attributes.Count(x => x is QueryRootAttribute)); } [Test] @@ -135,6 +140,7 @@ public void MapQueryGroup_SingleCopyAttribute_AppliedToGroupAndField_IsOnlyAppli var anonCount = childField.Attributes.Where(x => x is AllowAnonymousAttribute).Count(); Assert.AreEqual(1, anonCount); + Assert.AreEqual(1, childField.Attributes.Count(x => x is QueryRootAttribute)); } [Test] @@ -147,6 +153,7 @@ public void MapField_WithNoResovler_FieldIsMade_ResolverIsNotSet() .MapField("myField"); Assert.IsNull(childField.Resolver); + Assert.AreEqual(1, childField.Attributes.Count(x => x is QueryRootAttribute)); } [Test] @@ -161,6 +168,7 @@ public void MapField_WithResovler_AndUnion_BothAreSet() Assert.IsNotNull(childField.Resolver); Assert.AreEqual(1, childField.Attributes.OfType().Count()); Assert.AreEqual("myUnion", childField.Attributes.OfType().Single().UnionName); + Assert.AreEqual(1, childField.Attributes.Count(x => x is QueryRootAttribute)); } [Test] @@ -174,6 +182,7 @@ public void MapField_WithResovler_AndExplicitReturnType_IsMapped() Assert.IsNotNull(childField.Resolver); Assert.AreEqual(typeof(int?), childField.ReturnType); + Assert.AreEqual(1, childField.Attributes.Count(x => x is QueryRootAttribute)); } [Test] @@ -194,6 +203,7 @@ public void MapQueryGroup_MultipleCopyAttribute_AppliedToGroupAndField_IsApplied Assert.AreEqual(2, authCount); Assert.IsNotNull(childField.Attributes.SingleOrDefault(x => x is AuthorizeAttribute a && a.Policy == "policy1")); Assert.IsNotNull(childField.Attributes.SingleOrDefault(x => x is AuthorizeAttribute a && a.Policy == "policy2")); + Assert.AreEqual(1, childField.Attributes.Count(x => x is QueryRootAttribute)); // ensure the order of applied attributes is parent field then child field var i = 0; @@ -241,6 +251,7 @@ public void MapQueryGroup_MultipleSeperateChildGrous_AttributesAreAppliedCorrect Assert.IsNotNull(childField1.Attributes.SingleOrDefault(x => x is AuthorizeAttribute a && a.Policy == "policy1")); Assert.IsNotNull(childField1.Attributes.SingleOrDefault(x => x is AuthorizeAttribute a && a.Policy == "policy2")); Assert.IsNotNull(childField1.Attributes.SingleOrDefault(x => x is AuthorizeAttribute a && a.Policy == "policy3")); + Assert.AreEqual(1, childField1.Attributes.Count(x => x is QueryRootAttribute)); // ensure the order of applied attributes is parent field then child field var i = 0; @@ -273,6 +284,7 @@ public void MapQueryGroup_MultipleSeperateChildGrous_AttributesAreAppliedCorrect Assert.IsNotNull(childField2.Attributes.SingleOrDefault(x => x is AuthorizeAttribute a && a.Policy == "policy1")); Assert.IsNotNull(childField2.Attributes.SingleOrDefault(x => x is AuthorizeAttribute a && a.Policy == "policy4")); Assert.IsNotNull(childField2.Attributes.SingleOrDefault(x => x is AuthorizeAttribute a && a.Policy == "policy5")); + Assert.AreEqual(1, childField2.Attributes.Count(x => x is QueryRootAttribute)); i = 0; foreach (var attrib in childField2.Attributes) @@ -296,5 +308,21 @@ public void MapQueryGroup_MultipleSeperateChildGrous_AttributesAreAppliedCorrect Assert.AreEqual(3, i); } + + [Test] + public void MapField_FromSchemaBuilder_WithNoResovler_FieldIsMade_ResolverIsNotSet() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var builderMock = new Mock(); + builderMock.Setup(x => x.Options).Returns(options); + + var childField = builderMock.Object.MapQueryGroup("/path1/path2") + .MapField("myField"); + + Assert.IsNull(childField.Resolver); + Assert.AreEqual(1, childField.Attributes.Count(x => x is QueryRootAttribute)); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedQueryTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedQueryTemplateTests.cs index 3a65908c5..5d447f860 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedQueryTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedQueryTemplateTests.cs @@ -93,5 +93,45 @@ public void MapQuery_WithUnionName0_AddsUnionNameToType() Assert.AreEqual("myUnion", attrib.UnionName); } + + [Test] + public void MapMutation_FromBuilder_WithNoDelegate_DoesAddFieldToSchema() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var builderMock = new Mock(); + builderMock.Setup(x => x.Options).Returns(options); + + var field = builderMock.Object.MapQuery("/path1/path2"); + + Assert.IsNotNull(field); + Assert.AreEqual("[query]/path1/path2", field.Route.Path); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeResolvedFieldDefinition), field); + Assert.AreEqual(1, options.RuntimeTemplates.Count()); + + Assert.AreEqual(1, field.Attributes.Count()); + var rootAttrib = field.Attributes.FirstOrDefault(x => x.GetType() == typeof(QueryRootAttribute)); + Assert.IsNotNull(rootAttrib); + } + + [Test] + public void MapMutation_FromBuilder_WithUnionName0_AddsUnionNameToType() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var builderMock = new Mock(); + builderMock.Setup(x => x.Options).Returns(options); + + var field = builderMock.Object.MapQuery("myField", "myUnion", (string a) => 1); + + var attrib = field.Attributes.OfType().SingleOrDefault(); + + Assert.AreEqual("myUnion", attrib.UnionName); + + var rootAttrib = field.Attributes.FirstOrDefault(x => x.GetType() == typeof(QueryRootAttribute)); + Assert.IsNotNull(rootAttrib); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedTypeExtensionTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedTypeExtensionTemplateTests.cs index ba5c8f21c..998c65580 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedTypeExtensionTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedTypeExtensionTemplateTests.cs @@ -47,6 +47,53 @@ public void MapTypeExtension_ByOptions_AddsTypeExtensionToOptions() Assert.IsNotNull(typeExtensionAttrib); } + [Test] + public void MapTypeExtension_ByOptions_AndTypeDeclaration_AddsTypeExtensionToOptions() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var typeExt = options.MapTypeExtension(typeof(TwoPropertyObject), "mytypeExt", (int x) => 0); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeTypeExtensionDefinition), typeExt); + + Assert.AreEqual(1, options.RuntimeTemplates.Count()); + Assert.IsNotNull(options.RuntimeTemplates.FirstOrDefault(x => x == typeExt)); + Assert.AreEqual("[type]/TwoPropertyObject/mytypeExt", typeExt.Route.Path); + Assert.IsNull(typeExt.ReturnType); + Assert.IsNotNull(typeExt.Resolver); + Assert.AreEqual(FieldResolutionMode.PerSourceItem, typeExt.ExecutionMode); + + Assert.AreEqual(1, typeExt.Attributes.Count()); + + var typeExtensionAttrib = typeExt.Attributes.FirstOrDefault(x => x.GetType() == typeof(TypeExtensionAttribute)); + Assert.IsNotNull(typeExtensionAttrib); + } + + + [Test] + public void MapTypeExtension_ByOptions_WithTypeParameter_AddsTypeExtensionToOptions() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var typeExt = options.MapTypeExtension(typeof(TwoPropertyObject), "mytypeExt"); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeTypeExtensionDefinition), typeExt); + + Assert.AreEqual(1, options.RuntimeTemplates.Count()); + Assert.IsNotNull(options.RuntimeTemplates.FirstOrDefault(x => x == typeExt)); + Assert.AreEqual("[type]/TwoPropertyObject/mytypeExt", typeExt.Route.Path); + Assert.IsNull(typeExt.ReturnType); + Assert.IsNull(typeExt.Resolver); + Assert.AreEqual(FieldResolutionMode.PerSourceItem, typeExt.ExecutionMode); + + Assert.AreEqual(1, typeExt.Attributes.Count()); + + var typeExtensionAttrib = typeExt.Attributes.FirstOrDefault(x => x.GetType() == typeof(TypeExtensionAttribute)); + Assert.IsNotNull(typeExtensionAttrib); + } + + + [Test] public void MapTypeExtension_WithName_AddsInternalName() { @@ -56,7 +103,7 @@ public void MapTypeExtension_WithName_AddsInternalName() var builderMock = new Mock(); builderMock.Setup(x => x.Options).Returns(options); - var typeExt = options.MapTypeExtension("mytypeExt") + var typeExt = builderMock.Object.MapTypeExtension("mytypeExt") .WithName("internaltypeExtName"); Assert.AreEqual("internaltypeExtName", typeExt.InternalName); @@ -71,7 +118,7 @@ public void MapTypeExtension_ByBuilder_AddsTypeExtensionToOptions() var builderMock = new Mock(); builderMock.Setup(x => x.Options).Returns(options); - var typeExt = options.MapTypeExtension("mytypeExt"); + var typeExt = builderMock.Object.MapTypeExtension("mytypeExt"); Assert.IsInstanceOf(typeof(IGraphQLRuntimeTypeExtensionDefinition), typeExt); Assert.AreEqual(1, options.RuntimeTemplates.Count()); @@ -104,7 +151,7 @@ public void MapTypeExtension_ByBuilder_WithResolver_AddsTypeExtensionToOptions() var builderMock = new Mock(); builderMock.Setup(x => x.Options).Returns(options); - var typeExt = options.MapTypeExtension("mytypeExt", (string a) => 1); + var typeExt = builderMock.Object.MapTypeExtension("mytypeExt", (string a) => 1); Assert.IsInstanceOf(typeof(IGraphQLRuntimeTypeExtensionDefinition), typeExt); Assert.AreEqual(1, options.RuntimeTemplates.Count()); @@ -231,6 +278,33 @@ public void MappedTypeExension_SwappingOutResolvers_RemovesUnion() Assert.AreEqual(0, typeExt.Attributes.Count(x => x is UnionAttribute)); } + + [Test] + public void MappedTypeExension_ViaOptions_WithUnion() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var typeExt = options.MapTypeExtension("mytypeExt", "myUnion", (string a) => 1); + Assert.AreEqual(1, typeExt.Attributes.Count(x => x is UnionAttribute)); + Assert.IsNotNull(typeExt.Resolver); + } + + + [Test] + public void MappedTypeExension_ViaBuilder_WithUnion() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var builderMock = new Mock(); + builderMock.Setup(x => x.Options).Returns(options); + + var typeExt = builderMock.Object.MapTypeExtension("mytypeExt", "myUnion", (string a) => 1); + Assert.AreEqual(1, typeExt.Attributes.Count(x => x is UnionAttribute)); + Assert.IsNotNull(typeExt.Resolver); + } + [Test] public void MappedTypeExension_NoResolver_CreatesField() { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/ResolvedFieldTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/ResolvedFieldTemplateTests.cs index 12a72312f..33af8e048 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/ResolvedFieldTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/ResolvedFieldTemplateTests.cs @@ -35,6 +35,23 @@ public void ResolvedField_WhenAllowAnonymousAdded_AddsAnonymousAttribute() Assert.IsNotNull(field.Attributes.FirstOrDefault(x => x is AllowAnonymousAttribute)); } + [Test] + public void ResolvedField_WhenAllowAnonymousAdded_AllAuthorizeAreRemoved() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapQuery("/path1/path2", (string a) => 1); + field.AddAttribute(new AuthorizeAttribute("policy1")); + Assert.AreEqual(1, field.Attributes.Count(x => x is AuthorizeAttribute)); + + field.AllowAnonymous(); + + Assert.AreEqual(2, field.Attributes.Count()); + Assert.IsNotNull(field.Attributes.FirstOrDefault(x => x is AllowAnonymousAttribute)); + Assert.AreEqual(0, field.Attributes.Count(x => x is AuthorizeAttribute)); + } + [Test] public void ResolvedField_WhenNameApplied_NameIsAttchedToFieldDeclaration() { @@ -66,6 +83,29 @@ public void ResolvedField_WhenRequireAuthAdded_AddsAuthAttribute() Assert.AreEqual("roles1", attrib.Roles); } + + [Test] + public void ResolvedField_WhenRequireAuthAdded_AllowAnonIsRemoved() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapQuery("/path1/path2", (string a) => 1); + field.AddAttribute(new AllowAnonymousAttribute()); + Assert.AreEqual(1, field.Attributes.Count(x => x is AllowAnonymousAttribute)); + + field.RequireAuthorization("policy1", "roles1"); + + Assert.AreEqual(2, field.Attributes.Count()); + + var attrib = field.Attributes.FirstOrDefault(x => x is AuthorizeAttribute) as AuthorizeAttribute; + Assert.IsNotNull(attrib); + Assert.AreEqual("policy1", attrib.Policy); + Assert.AreEqual("roles1", attrib.Roles); + + Assert.AreEqual(0, field.Attributes.Count(x => x is AllowAnonymousAttribute)); + } + [Test] public void ResolvedField_WhenResolverIsChanged_NewResolverIsUsed() { From adf4bbe41cb56ed4841f73db684bbaa5483766c2 Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Sat, 29 Jul 2023 20:12:04 -0700 Subject: [PATCH 55/63] WIP, minimal api subscription templating done --- ...untimeSubscriptionsDefinitionExtensions.cs | 183 ++++++++++++++++++ ...ionsDefinitionExtensions_ResolvedFields.cs | 170 ++++++++++++++++ ...tionsDefinitionExtensions_VirtualFields.cs | 45 +++++ .../SubscriptionBuilderExtensions.cs | 8 +- ...nEnabledRuntimeFieldExecutionController.cs | 22 +++ ...SubscriptionEnabledGraphQLSchemaFactory.cs | 43 ++++ ...criptionEnabledGraphQLTypeMakerFactory.cs} | 5 +- ...onEnabledRuntimeResolvedFieldDefinition.cs | 24 +++ ...meSubscriptionEnabledFieldGroupTemplate.cs | 63 ++++++ ...scriptionEnabledResolvedFieldDefinition.cs | 122 ++++++++++++ ...timeSubscriptionGraphControllerTemplate.cs | 72 +++++++ ...ptionControllerActionGraphFieldTemplate.cs | 4 +- .../SubscriptionGraphArgumentTemplate.cs | 3 +- .../SubscriptionGraphControllerTemplate.cs | 3 +- .../SubscriptionEnabledGraphFieldMaker.cs | 11 +- .../SubscriptionReceiverSchemaExtension.cs | 20 +- ...hemaItemDefinitionExtensions_Directives.cs | 2 +- ...maItemDefinitionExtensions_FieldGroups.cs} | 84 +------- ...chemaItemDefinitionExtensions_Internals.cs | 4 +- ...chemaItemDefinitionExtensions_Mutations.cs | 24 ++- ...eSchemaItemDefinitionExtensions_Queries.cs | 27 ++- ...ItemDefinitionExtensions_ResolvedFields.cs | 2 +- ...ItemDefinitionExtensions_TypeExtensions.cs | 2 +- .../Configuration/SchemaOptions.cs | 8 +- .../Controllers/GraphControllerBase.cs | 49 +++-- .../RuntimeFieldExecutionController.cs | 19 -- ...GraphQLSchemaFactory_RuntimeDefinitions.cs | 4 - .../Resolvers/FieldResolverMetaData.cs | 9 +- .../InternalFieldResolverMetaData.cs | 6 +- .../Execution/IGraphFieldResolverMetaData.cs | 10 + .../Interfaces/Internal/IGraphTypeTemplate.cs | 7 + .../IGraphQLRuntimeFieldDefinition.cs | 19 -- .../IGraphQLRuntimeFieldGroupDefinition.cs | 33 ++++ ... RuntimeControllerActionDefinitionBase.cs} | 22 +-- .../RuntimeDirectiveActionDefinition.cs | 2 +- ...mplate.cs => RuntimeFieldGroupTemplate.cs} | 26 ++- .../RuntimeFieldGroupTemplateBase.cs | 64 ++++++ .../RuntimeResolvedFieldDefinition.cs | 8 +- .../RuntimeTypeExtensionDefinition.cs | 5 +- .../GraphDirectiveMethodTemplate.cs | 3 +- .../TypeTemplates/GraphTypeTemplateBase.cs | 3 + .../Generation/TypeTemplates/ItemSource.cs | 29 +++ .../MethodGraphFieldTemplateBase.cs | 3 +- .../PropertyGraphFieldTemplate.cs | 3 +- .../RuntimeGraphControllerTemplate.cs | 3 + .../RuntimeGraphDirectiveTemplate.cs | 3 + .../Schemas/Structural/SchemaItemPath.cs | 34 ---- .../Structural/SchemaItemPath_Statics.cs | 35 ++++ ...SubscriptionEnabledFieldFieldMakerTests.cs | 13 +- .../Mocks/SubscriptionContextBuilder.cs | 1 - .../MappedSubscriptionGroupTests.cs | 145 ++++++++++++++ .../MappedSubscriptionTemplateTests.cs | 167 ++++++++++++++++ ...tionEnabledResolvedFieldDefinitionTests.cs | 52 +++++ .../OneMethodSubscriptionController.cs | 2 +- .../SubscriptionMethodController.cs | 2 +- .../SimpleSubscriptionController.cs | 2 +- .../GraphActionTemplateTests.cs | 7 +- .../GraphControllerTemplateTests.cs | 5 +- .../Schemas/RuntimeFieldGeneralTests.cs | 39 ++++ .../SubscriptionReceiverExtensionTests.cs | 3 +- ...criptionClientDispatchQueueAlerterTests.cs | 1 - .../SubscriptionClientDispatchQueueTests.cs | 2 - .../MappedDirectiveTemplateTests.cs | 2 +- .../MappedTypeExtensionTemplateTests.cs | 7 +- .../ResolvedFieldTemplateTests.cs | 3 +- .../RuntimeControllerActionTemplateTests.cs | 4 +- .../Schemas/RuntimeFieldsGeneralTests.cs | 8 +- 67 files changed, 1541 insertions(+), 274 deletions(-) create mode 100644 src/graphql-aspnet-subscriptions/Configuration/GraphQLRuntimeSubscriptionsDefinitionExtensions.cs create mode 100644 src/graphql-aspnet-subscriptions/Configuration/GraphQLRuntimeSubscriptionsDefinitionExtensions_ResolvedFields.cs create mode 100644 src/graphql-aspnet-subscriptions/Configuration/GraphQLRuntimeSubscriptionsDefinitionExtensions_VirtualFields.cs create mode 100644 src/graphql-aspnet-subscriptions/Controllers/SubscriptionEnabledRuntimeFieldExecutionController.cs create mode 100644 src/graphql-aspnet-subscriptions/Engine/SubscriptionEnabledGraphQLSchemaFactory.cs rename src/graphql-aspnet-subscriptions/Engine/{SubscriptionEnabledGraphQLTypeMakerFactory{TSchema}.cs => SubscriptionEnabledGraphQLTypeMakerFactory.cs} (93%) create mode 100644 src/graphql-aspnet-subscriptions/Interfaces/Schema/RuntimeDefinitions/IGraphQLSubscriptionEnabledRuntimeResolvedFieldDefinition.cs create mode 100644 src/graphql-aspnet-subscriptions/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeSubscriptionEnabledFieldGroupTemplate.cs create mode 100644 src/graphql-aspnet-subscriptions/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeSubscriptionEnabledResolvedFieldDefinition.cs create mode 100644 src/graphql-aspnet-subscriptions/Schemas/Generation/TypeTemplates/RuntimeSubscriptionGraphControllerTemplate.cs rename src/graphql-aspnet-subscriptions/{Internal => Schemas/Generation}/TypeTemplates/SubscriptionControllerActionGraphFieldTemplate.cs (98%) rename src/graphql-aspnet-subscriptions/{Internal => Schemas/Generation}/TypeTemplates/SubscriptionGraphArgumentTemplate.cs (94%) rename src/graphql-aspnet-subscriptions/{Internal => Schemas/Generation}/TypeTemplates/SubscriptionGraphControllerTemplate.cs (94%) rename src/graphql-aspnet-subscriptions/{Engine => Schemas}/TypeMakers/SubscriptionEnabledGraphFieldMaker.cs (88%) rename src/graphql-aspnet/Configuration/{GraphQLRuntimeSchemaItemDefinitionExtensions_VirtualFields.cs => GraphQLRuntimeSchemaItemDefinitionExtensions_FieldGroups.cs} (57%) delete mode 100644 src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeFieldDefinition.cs create mode 100644 src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeFieldGroupDefinition.cs rename src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/{BaseRuntimeControllerActionDefinition.cs => RuntimeControllerActionDefinitionBase.cs} (86%) rename src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/{RuntimeVirtualFieldTemplate.cs => RuntimeFieldGroupTemplate.cs} (68%) create mode 100644 src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeFieldGroupTemplateBase.cs create mode 100644 src/graphql-aspnet/Schemas/Generation/TypeTemplates/ItemSource.cs create mode 100644 src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/Generation/MappedSubscriptionGroupTests.cs create mode 100644 src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/Generation/MappedSubscriptionTemplateTests.cs create mode 100644 src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeSubscriptionEnabledResolvedFieldDefinitionTests.cs rename src/unit-tests/graphql-aspnet-subscriptions-tests/{Internal/Templating => Schemas/Generation/TypeTemplates}/ActionTestData/OneMethodSubscriptionController.cs (89%) rename src/unit-tests/graphql-aspnet-subscriptions-tests/{Internal/Templating => Schemas/Generation/TypeTemplates}/ActionTestData/SubscriptionMethodController.cs (96%) rename src/unit-tests/graphql-aspnet-subscriptions-tests/{Internal/Templating => Schemas/Generation/TypeTemplates}/ControllerTestData/SimpleSubscriptionController.cs (92%) rename src/unit-tests/graphql-aspnet-subscriptions-tests/{Internal/Templating => Schemas/Generation/TypeTemplates}/GraphActionTemplateTests.cs (96%) rename src/unit-tests/graphql-aspnet-subscriptions-tests/{Internal/Templating => Schemas/Generation/TypeTemplates}/GraphControllerTemplateTests.cs (86%) create mode 100644 src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/RuntimeFieldGeneralTests.cs diff --git a/src/graphql-aspnet-subscriptions/Configuration/GraphQLRuntimeSubscriptionsDefinitionExtensions.cs b/src/graphql-aspnet-subscriptions/Configuration/GraphQLRuntimeSubscriptionsDefinitionExtensions.cs new file mode 100644 index 000000000..950ed71b7 --- /dev/null +++ b/src/graphql-aspnet-subscriptions/Configuration/GraphQLRuntimeSubscriptionsDefinitionExtensions.cs @@ -0,0 +1,183 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Configuration +{ + using System; + using GraphQL.AspNet.Attributes; + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Execution; + using GraphQL.AspNet.Interfaces.Configuration; + using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; + using GraphQL.AspNet.Schemas.Generation.RuntimeSchemaItemDefinitions; + + /// + /// Extension methods for defining subscriptions via minimal api. + /// + public static partial class GraphQLRuntimeSubscriptionDefinitionExtensions + { + /// + /// Creates a new, explicitly resolvable field in the Subscription root object with the given path. This field cannot be + /// further extended or nested with other fields via the Mapping API. + /// + /// The builder representing the schema where this field + /// will be created. + /// The template path string for his field. (e.g. /path1/path2/path3) + /// IGraphQLFieldTemplate. + public static IGraphQLSubscriptionEnabledRuntimeResolvedFieldDefinition MapSubscription(this ISchemaBuilder schemaBuilder, string template) + { + Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); + + return MapSubscription( + schemaBuilder.Options, + template, + null, // unionName + null as Delegate); + } + + /// + /// Creates a new field in the Subscription object with the given path. This field can act as a + /// grouping field of other resolvable fields or be converted to an explicitly resolvable field itself. + /// + /// The builder representing the schema where this field + /// will be created. + /// The template path string for his field. (e.g. /path1/path2/path3) + /// The resolver method to execute when this + /// field is requested. + /// IGraphQLFieldTemplate. + public static IGraphQLSubscriptionEnabledRuntimeResolvedFieldDefinition MapSubscription(this ISchemaBuilder schemaBuilder, string template, Delegate resolverMethod) + { + Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); + return MapSubscription( + schemaBuilder.Options, + template, + null, // unionName + resolverMethod); + } + + /// + /// Creates a new field in the Subscription object with the given path. This field can act as a + /// grouping field of other resolvable fields or be converted to an explicitly resolvable field itself. + /// + /// The builder representing the schema where this field + /// will be created. + /// The template path string for his field. (e.g. /path1/path2/path3) + /// Provide a name and this field will be declared to return a union. Use to declare union members. + /// The resolver method to execute when this + /// field is requested. + /// IGraphQLFieldTemplate. + public static IGraphQLSubscriptionEnabledRuntimeResolvedFieldDefinition MapSubscription( + this ISchemaBuilder schemaBuilder, + string template, + string unionName, + Delegate resolverMethod) + { + Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); + + return MapSubscription( + schemaBuilder.Options, + template, + unionName, + resolverMethod); + } + + /// + /// Creates a new field in the Subscription root object with the given path. This field can act as a + /// grouping field of other resolvable fields or be converted to an explicitly resolvable field itself. + /// + /// The options representing the schema where this field + /// will be created. + /// The template path string for his field. (e.g. /path1/path2/path3) + /// IGraphQLFieldTemplate. + public static IGraphQLSubscriptionEnabledRuntimeResolvedFieldDefinition MapSubscription( + this SchemaOptions schemaOptions, + string template) + { + return MapSubscription( + schemaOptions, + template, + null, // unionMethod + null as Delegate); + } + + /// + /// Creates a new, explicitly resolvable field in the Subscription root object with the given path. This field cannot be + /// further extended or nested with other fields via the Mapping API. + /// + /// The options representing the schema where this field + /// will be created. + /// The template path string for his field. (e.g. /path1/path2/path3) + /// The resolver method to execute when + /// this field is requested by a caller. + /// IGraphQLResolvedFieldTemplate. + public static IGraphQLSubscriptionEnabledRuntimeResolvedFieldDefinition MapSubscription( + this SchemaOptions schemaOptions, + string template, + Delegate resolverMethod) + { + return MapSubscription( + schemaOptions, + template, + null, // unionMethod + resolverMethod); + } + + /// + /// Creates a new, explicitly resolvable field in the Subscription root object with the given path. This field cannot be + /// further extended or nested with other fields via the Mapping API. + /// + /// The options representing the schema where this field + /// will be created. + /// The template path string for his field. (e.g. /path1/path2/path3) + /// Provide a name and this field will be declared to return a union. Use to declare union members. + /// The resolver method to execute when + /// this field is requested by a caller. + /// IGraphQLResolvedFieldTemplate. + public static IGraphQLSubscriptionEnabledRuntimeResolvedFieldDefinition MapSubscription( + this SchemaOptions schemaOptions, + string template, + string unionName, + Delegate resolverMethod) + { + schemaOptions = Validation.ThrowIfNullOrReturn(schemaOptions, nameof(schemaOptions)); + template = Validation.ThrowIfNullWhiteSpaceOrReturn(template, nameof(template)); + + var fieldTemplate = new RuntimeSubscriptionEnabledFieldGroupTemplate( + schemaOptions, + template); + + var resolvedField = RuntimeSubscriptionEnabledResolvedFieldDefinition.FromFieldTemplate(fieldTemplate); + schemaOptions.AddRuntimeSchemaItem(resolvedField); + + if (!string.IsNullOrWhiteSpace(unionName)) + resolvedField.AddAttribute(new UnionAttribute(unionName.Trim())); + + resolvedField.AddResolver(unionName, resolverMethod); + return resolvedField; + } + + /// + /// Defines a custom event name for this subscription field. This event name is the key value + /// that must be published from a mutation to invoke this subscription for any subscribers. + /// + /// + /// This event name must be unique for this schema. + /// + /// The field to update. + /// Name of the event. + /// IGraphQLSubscriptionEnabledRuntimeResolvedFieldDefinition. + public static IGraphQLSubscriptionEnabledRuntimeResolvedFieldDefinition WithEventName( + this IGraphQLSubscriptionEnabledRuntimeResolvedFieldDefinition field, + string eventName) + { + field.EventName = eventName; + return field; + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet-subscriptions/Configuration/GraphQLRuntimeSubscriptionsDefinitionExtensions_ResolvedFields.cs b/src/graphql-aspnet-subscriptions/Configuration/GraphQLRuntimeSubscriptionsDefinitionExtensions_ResolvedFields.cs new file mode 100644 index 000000000..207159c67 --- /dev/null +++ b/src/graphql-aspnet-subscriptions/Configuration/GraphQLRuntimeSubscriptionsDefinitionExtensions_ResolvedFields.cs @@ -0,0 +1,170 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Configuration +{ + using System; + using GraphQL.AspNet.Attributes; + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Interfaces.Controllers; + using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; + using Microsoft.AspNetCore.Authorization; + + /// + /// Extension methods for defining subscriptions via minimal api. + /// + public partial class GraphQLRuntimeSubscriptionDefinitionExtensions + { + /// + /// Adds policy-based authorization requirements to the field. + /// + /// + /// This is similar to adding the to a controller method + /// + /// The field being built. + /// The name of the policy to assign via this requirement. + /// A comma-seperated list of roles to assign via this requirement. + /// IGraphQLFieldBuilder. + public static IGraphQLSubscriptionEnabledRuntimeResolvedFieldDefinition RequireAuthorization( + this IGraphQLSubscriptionEnabledRuntimeResolvedFieldDefinition fieldBuilder, + string policyName = null, + string roles = null) + { + Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); + GraphQLRuntimeSchemaItemDefinitionExtensions.RequireAuthorization(fieldBuilder, policyName, roles); + return fieldBuilder; + } + + /// + /// Indicates that the field should allow anonymous access. This will override any potential authorization requirements setup via + /// the "MapGroup" methods if this field was created within a group. + /// + /// + /// This is similar to adding the to a controller method + /// + /// The field being built. + /// IGraphQLFieldBuilder. + public static IGraphQLSubscriptionEnabledRuntimeResolvedFieldDefinition AllowAnonymous(this IGraphQLSubscriptionEnabledRuntimeResolvedFieldDefinition fieldBuilder) + { + Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); + GraphQLRuntimeSchemaItemDefinitionExtensions.AllowAnonymous(fieldBuilder); + return fieldBuilder; + } + + /// + /// Adds a set of possible return types for this field. This is synonymous to using the + /// on a controller's action method. + /// + /// + /// This method can be called multiple times. Any new types will be appended to the field. All types added + /// must be coercable to the declared return type of the assigned resolver for this field unless this field returns a union; in + /// which case the types will be added as union members. + /// + /// The field being built. + /// The first possible type that might be returned by this + /// field. + /// Any number of additional possible types that + /// might be returned by this field. + /// IGraphQLFieldBuilder. + public static IGraphQLSubscriptionEnabledRuntimeResolvedFieldDefinition AddPossibleTypes(this IGraphQLSubscriptionEnabledRuntimeResolvedFieldDefinition fieldBuilder, Type firstPossibleType, params Type[] additionalPossibleTypes) + { + Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); + GraphQLRuntimeSchemaItemDefinitionExtensions.AddPossibleTypes(fieldBuilder, firstPossibleType, additionalPossibleTypes); + return fieldBuilder; + } + + /// + /// Clears all extra defined possible types this field may declare. This will not affect the core type defined by the resolver, if + /// a resolver has been defined for this field. + /// + /// The field builder. + /// IGraphQLSubscriptionEnabledRuntimeResolvedFieldDefinition. + public static IGraphQLSubscriptionEnabledRuntimeResolvedFieldDefinition ClearPossibleTypes(this IGraphQLSubscriptionEnabledRuntimeResolvedFieldDefinition fieldBuilder) + { + Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); + GraphQLRuntimeSchemaItemDefinitionExtensions.ClearPossibleTypes(fieldBuilder); + return fieldBuilder; + } + + /// + /// Assigns a custom internal name to this field. This value will be used in error + /// messages and log entries instead of an anonymous method name. This can significantly increase readability + /// while trying to debug an issue. This value has no bearing on the runtime use of this field. It is cosmetic only. + /// + /// + /// This value does NOT affect the field name as it would appear in a schema. It only effects the internal + /// name used in log messages and exception text. + /// + /// The field being built. + /// The value to use as the internal name for this field definition when its + /// added to the schema. + /// IGraphQLFieldBuilder. + public static IGraphQLSubscriptionEnabledRuntimeResolvedFieldDefinition WithInternalName(this IGraphQLSubscriptionEnabledRuntimeResolvedFieldDefinition fieldBuilder, string internalName) + { + Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); + GraphQLRuntimeSchemaItemDefinitionExtensions.WithInternalName(fieldBuilder, internalName); + return fieldBuilder; + } + + /// + /// Indicates this field will return a union and sets the resolver to be used when this field is requested at runtime. The provided + /// resolver should return a . + /// + /// The field being built. + /// Provide a name and this field will be declared to return a union. Use to declare union members. + /// The delegate to assign as the resolver. This method will be + /// parsed to determine input arguments for the field on the target schema. + /// IGraphQLFieldBuilder. + public static IGraphQLSubscriptionEnabledRuntimeResolvedFieldDefinition AddResolver( + this IGraphQLSubscriptionEnabledRuntimeResolvedFieldDefinition fieldBuilder, + string unionName, + Delegate resolverMethod) + { + Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); + GraphQLRuntimeSchemaItemDefinitionExtensions.AddResolver(fieldBuilder, unionName, resolverMethod); + return fieldBuilder; + } + + /// + /// Sets the resolver to be used when this field is requested at runtime. + /// + /// + /// If this method is called more than once the previously set resolver will be replaced. + /// + /// The field being built. + /// The delegate to assign as the resolver. This method will be + /// parsed to determine input arguments for the field on the target schema. + /// IGraphQLFieldBuilder. + public static IGraphQLSubscriptionEnabledRuntimeResolvedFieldDefinition AddResolver(this IGraphQLSubscriptionEnabledRuntimeResolvedFieldDefinition fieldBuilder, Delegate resolverMethod) + { + Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); + GraphQLRuntimeSchemaItemDefinitionExtensions.AddResolver(fieldBuilder, resolverMethod); + return fieldBuilder; + } + + /// + /// Sets the resolver to be used when this field is requested at runtime. + /// + /// + /// If this method is called more than once the previously set resolver will be replaced. + /// + /// The expected, primary return type of the field. Must be provided + /// if the supplied delegate returns an . + /// The field being built. + /// The delegate to assign as the resolver. This method will be + /// parsed to determine input arguments for the field on the target schema. + /// IGraphQLFieldBuilder. + public static IGraphQLSubscriptionEnabledRuntimeResolvedFieldDefinition AddResolver(this IGraphQLSubscriptionEnabledRuntimeResolvedFieldDefinition fieldBuilder, Delegate resolverMethod) + { + Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); + GraphQLRuntimeSchemaItemDefinitionExtensions.AddResolver(fieldBuilder, resolverMethod); + return fieldBuilder; + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet-subscriptions/Configuration/GraphQLRuntimeSubscriptionsDefinitionExtensions_VirtualFields.cs b/src/graphql-aspnet-subscriptions/Configuration/GraphQLRuntimeSubscriptionsDefinitionExtensions_VirtualFields.cs new file mode 100644 index 000000000..07dfaa360 --- /dev/null +++ b/src/graphql-aspnet-subscriptions/Configuration/GraphQLRuntimeSubscriptionsDefinitionExtensions_VirtualFields.cs @@ -0,0 +1,45 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Configuration +{ + using GraphQL.AspNet.Interfaces.Configuration; + using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; + using GraphQL.AspNet.Schemas.Generation.RuntimeSchemaItemDefinitions; + + /// + /// Extension methods for defining subscriptions via minimal api. + /// + public static partial class GraphQLRuntimeSubscriptionDefinitionExtensions + { + /// + /// Begins a new field group for the subscription schema object. All fields created using + /// this group will be nested underneath it and inherit any set parameters such as authorization requirements. + /// + /// The builder to append the Subscription group to. + /// The template path for this group. + /// IGraphQLRuntimeFieldDefinition. + public static IGraphQLRuntimeFieldGroupDefinition MapSubscriptionGroup(this ISchemaBuilder schemaBuilder, string template) + { + return MapSubscriptionGroup(schemaBuilder?.Options, template); + } + + /// + /// Begins a new field group for the subscription schema object. All fields created using + /// this group will be nested underneath it and inherit any set parameters such as authorization requirements. + /// + /// The schema options to append the Subscription group to. + /// The template path for this group. + /// IGraphQLRuntimeFieldDefinition. + public static IGraphQLRuntimeFieldGroupDefinition MapSubscriptionGroup(this SchemaOptions schemaOptions, string template) + { + return new RuntimeSubscriptionEnabledFieldGroupTemplate(schemaOptions, template); + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet-subscriptions/Configuration/SubscriptionBuilderExtensions.cs b/src/graphql-aspnet-subscriptions/Configuration/SubscriptionBuilderExtensions.cs index 825cd0541..69ba97882 100644 --- a/src/graphql-aspnet-subscriptions/Configuration/SubscriptionBuilderExtensions.cs +++ b/src/graphql-aspnet-subscriptions/Configuration/SubscriptionBuilderExtensions.cs @@ -46,7 +46,7 @@ public static ISchemaBuilder AddSubscriptions( // then publishing adds one additional middleware component return schemaBuilder .AddSubscriptionServer(options) - .AddSubscriptionPublishing(options); + .AddSubscriptionPublishing(); } /// @@ -54,11 +54,9 @@ public static ISchemaBuilder AddSubscriptions( /// /// The type of schema being configured. /// The schema builder. - /// An action function to configure the subscription options. - /// GraphQL.AspNet.Interfaces.Configuration.ISchemaBuilder<TSchema>. + /// ISchemaBuilder<TSchema>. public static ISchemaBuilder AddSubscriptionPublishing( - this ISchemaBuilder schemaBuilder, - Action> options = null) + this ISchemaBuilder schemaBuilder) where TSchema : class, ISchema { Validation.ThrowIfNull(schemaBuilder, nameof(schemaBuilder)); diff --git a/src/graphql-aspnet-subscriptions/Controllers/SubscriptionEnabledRuntimeFieldExecutionController.cs b/src/graphql-aspnet-subscriptions/Controllers/SubscriptionEnabledRuntimeFieldExecutionController.cs new file mode 100644 index 000000000..42ca9f07a --- /dev/null +++ b/src/graphql-aspnet-subscriptions/Controllers/SubscriptionEnabledRuntimeFieldExecutionController.cs @@ -0,0 +1,22 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Controllers +{ + using GraphQL.AspNet.Attributes; + + /// + /// A special controller instance for executing subscription runtime configured controller + /// actions (e.g. minimal api defined fields). + /// + [GraphRoot] + internal class SubscriptionEnabledRuntimeFieldExecutionController : GraphController + { + } +} \ No newline at end of file diff --git a/src/graphql-aspnet-subscriptions/Engine/SubscriptionEnabledGraphQLSchemaFactory.cs b/src/graphql-aspnet-subscriptions/Engine/SubscriptionEnabledGraphQLSchemaFactory.cs new file mode 100644 index 000000000..c39c31ee1 --- /dev/null +++ b/src/graphql-aspnet-subscriptions/Engine/SubscriptionEnabledGraphQLSchemaFactory.cs @@ -0,0 +1,43 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Engine +{ + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; + using GraphQL.AspNet.Schemas.TypeSystem; + + /// + /// A schema creation factory that understands and can generate subscription types. + /// + /// The type of the schema being generated. + public class SubscriptionEnabledGraphQLSchemaFactory : DefaultGraphQLSchemaFactory + where TSchema : class, ISchema + { + /// + protected override void AddRuntimeFieldDefinition(IGraphQLRuntimeResolvedFieldDefinition fieldDefinition) + { + Validation.ThrowIfNull(fieldDefinition, nameof(fieldDefinition)); + + if (fieldDefinition is IGraphQLSubscriptionEnabledRuntimeResolvedFieldDefinition subField) + { + var template = new RuntimeSubscriptionGraphControllerTemplate(subField); + template.Parse(); + template.ValidateOrThrow(); + + this.AddController(template); + return; + } + + base.AddRuntimeFieldDefinition(fieldDefinition); + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet-subscriptions/Engine/SubscriptionEnabledGraphQLTypeMakerFactory{TSchema}.cs b/src/graphql-aspnet-subscriptions/Engine/SubscriptionEnabledGraphQLTypeMakerFactory.cs similarity index 93% rename from src/graphql-aspnet-subscriptions/Engine/SubscriptionEnabledGraphQLTypeMakerFactory{TSchema}.cs rename to src/graphql-aspnet-subscriptions/Engine/SubscriptionEnabledGraphQLTypeMakerFactory.cs index 2f9e8b23c..3abffd1d3 100644 --- a/src/graphql-aspnet-subscriptions/Engine/SubscriptionEnabledGraphQLTypeMakerFactory{TSchema}.cs +++ b/src/graphql-aspnet-subscriptions/Engine/SubscriptionEnabledGraphQLTypeMakerFactory.cs @@ -12,12 +12,11 @@ namespace GraphQL.AspNet.Engine using System; using GraphQL.AspNet.Common; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Engine.TypeMakers; using GraphQL.AspNet.Interfaces.Engine; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal.TypeTemplates; - using GraphQL.AspNet.Schemas.Generation; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; + using GraphQL.AspNet.Schemas.TypeMakers; using GraphQL.AspNet.Schemas.TypeSystem; /// diff --git a/src/graphql-aspnet-subscriptions/Interfaces/Schema/RuntimeDefinitions/IGraphQLSubscriptionEnabledRuntimeResolvedFieldDefinition.cs b/src/graphql-aspnet-subscriptions/Interfaces/Schema/RuntimeDefinitions/IGraphQLSubscriptionEnabledRuntimeResolvedFieldDefinition.cs new file mode 100644 index 000000000..e0c24ca39 --- /dev/null +++ b/src/graphql-aspnet-subscriptions/Interfaces/Schema/RuntimeDefinitions/IGraphQLSubscriptionEnabledRuntimeResolvedFieldDefinition.cs @@ -0,0 +1,24 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions +{ + /// + /// A special marker interface to indicate a runtime resolved field is subscription enabled. + /// + public interface IGraphQLSubscriptionEnabledRuntimeResolvedFieldDefinition : IGraphQLRuntimeResolvedFieldDefinition + { + /// + /// Gets or sets the name of the event that must be published from a mutation to invoke this + /// subscription. + /// + /// The name of the published event that identifies this subscription. + string EventName { get; set; } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet-subscriptions/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeSubscriptionEnabledFieldGroupTemplate.cs b/src/graphql-aspnet-subscriptions/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeSubscriptionEnabledFieldGroupTemplate.cs new file mode 100644 index 000000000..496e584a2 --- /dev/null +++ b/src/graphql-aspnet-subscriptions/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeSubscriptionEnabledFieldGroupTemplate.cs @@ -0,0 +1,63 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Schemas.Generation.RuntimeSchemaItemDefinitions +{ + using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Execution; + using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; + + /// + /// A with the ability to create subscription + /// enabled minimal api fields. + /// + public sealed class RuntimeSubscriptionEnabledFieldGroupTemplate : RuntimeFieldGroupTemplateBase + { + /// + /// Initializes a new instance of the class. + /// + /// The primary schema options where this field (and its children) will be + /// instantiated. + /// The path template describing this field. + public RuntimeSubscriptionEnabledFieldGroupTemplate( + SchemaOptions options, string pathTemplate) + : base( + options, + SchemaItemCollections.Subscription, + pathTemplate) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The field from which this entity is being added. + /// The partial path template to be appended to + /// the parent's already defined template. + public RuntimeSubscriptionEnabledFieldGroupTemplate( + IGraphQLRuntimeFieldGroupDefinition parentField, string fieldSubTemplate) + : base(parentField, fieldSubTemplate) + { + } + + /// + public override IGraphQLRuntimeFieldGroupDefinition MapChildGroup(string pathTemplate) + { + return new RuntimeSubscriptionEnabledFieldGroupTemplate(this, pathTemplate); + } + + /// + public override IGraphQLRuntimeResolvedFieldDefinition MapField(string pathTemplate) + { + var field = new RuntimeSubscriptionEnabledResolvedFieldDefinition(this, pathTemplate, null); + this.Options.AddRuntimeSchemaItem(field); + return field; + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet-subscriptions/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeSubscriptionEnabledResolvedFieldDefinition.cs b/src/graphql-aspnet-subscriptions/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeSubscriptionEnabledResolvedFieldDefinition.cs new file mode 100644 index 000000000..8f8648a47 --- /dev/null +++ b/src/graphql-aspnet-subscriptions/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeSubscriptionEnabledResolvedFieldDefinition.cs @@ -0,0 +1,122 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Schemas.Generation.RuntimeSchemaItemDefinitions +{ + using System; + using GraphQL.AspNet.Attributes; + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Execution; + using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; + using GraphQL.AspNet.Schemas.Structural; + + /// + /// A runtime field definition that supports additional required data items to properly setup a subscription via + /// a "minimal api" call. + /// + public class RuntimeSubscriptionEnabledResolvedFieldDefinition : RuntimeResolvedFieldDefinition, IGraphQLSubscriptionEnabledRuntimeResolvedFieldDefinition + { + private string _customEventName; + + /// + /// Converts the unresolved field into a resolved field. The newly generated field + /// will NOT be attached to any schema and will not have an assigned resolver. + /// + /// The field template. + /// IGraphQLResolvedFieldTemplate. + internal static IGraphQLSubscriptionEnabledRuntimeResolvedFieldDefinition FromFieldTemplate(IGraphQLRuntimeFieldGroupDefinition fieldTemplate) + { + Validation.ThrowIfNull(fieldTemplate, nameof(fieldTemplate)); + var field = new RuntimeSubscriptionEnabledResolvedFieldDefinition( + fieldTemplate.Options, + fieldTemplate.Route, + null); + + foreach (var attrib in fieldTemplate.Attributes) + field.AddAttribute(attrib); + + return field; + } + + /// + /// Initializes a new instance of the class. + /// + /// The parent field builder to which this new, resolved field + /// will be appended. + /// The template part to append to the parent field's template. + /// Name of the event that must be published to invoke this subscription + /// field. + public RuntimeSubscriptionEnabledResolvedFieldDefinition( + IGraphQLRuntimeFieldGroupDefinition parentFieldBuilder, + string fieldSubTemplate, + string eventName) + : base(parentFieldBuilder, fieldSubTemplate) + { + this.EventName = eventName?.Trim(); + } + + /// + /// Initializes a new instance of the class. + /// + /// The schema options to which this field is being added. + /// The full route to use for this item. + /// Name of the event that must be published to invoke this subscription + /// field. + private RuntimeSubscriptionEnabledResolvedFieldDefinition( + SchemaOptions schemaOptions, + SchemaItemPath route, + string eventName) + : base(schemaOptions, route) + { + this.EventName = eventName?.Trim(); + } + + /// + protected override Attribute CreatePrimaryAttribute() + { + var (collection, path) = this.Route; + if (collection == SchemaItemCollections.Subscription) + { + return new SubscriptionRootAttribute(path, this.ReturnType) + { + InternalName = this.InternalName, + EventName = this.EventName, + }; + } + + return base.CreatePrimaryAttribute(); + } + + /// + public string EventName + { + get + { + return _customEventName; + } + + set + { + _customEventName = value?.Trim(); + if (!string.IsNullOrWhiteSpace(_customEventName)) + return; + + var (_, path) = this.Route; + + // turns path1/path2/path3 => path1_path2_path3 + _customEventName = string.Join( + "_", + path.Split( + Constants.Routing.PATH_SEPERATOR, + StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)); + } + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet-subscriptions/Schemas/Generation/TypeTemplates/RuntimeSubscriptionGraphControllerTemplate.cs b/src/graphql-aspnet-subscriptions/Schemas/Generation/TypeTemplates/RuntimeSubscriptionGraphControllerTemplate.cs new file mode 100644 index 000000000..a66efed27 --- /dev/null +++ b/src/graphql-aspnet-subscriptions/Schemas/Generation/TypeTemplates/RuntimeSubscriptionGraphControllerTemplate.cs @@ -0,0 +1,72 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates +{ + using System.Collections.Generic; + using GraphQL.AspNet.Controllers; + using GraphQL.AspNet.Execution.Exceptions; + using GraphQL.AspNet.Interfaces.Internal; + using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; + + /// + /// A "controller template" representing a single runtime configured subscription field (e.g. minimal api). + /// This template is never cached. + /// + internal class RuntimeSubscriptionGraphControllerTemplate : SubscriptionGraphControllerTemplate + { + private readonly IMemberInfoProvider _fieldProvider; + private readonly IGraphQLRuntimeResolvedFieldDefinition _fieldDefinition; + + /// + /// Initializes a new instance of the class. + /// + /// A single, runtime configured, field definition + /// to templatize for a specfic schema. + public RuntimeSubscriptionGraphControllerTemplate(IGraphQLSubscriptionEnabledRuntimeResolvedFieldDefinition fieldDefinition) + : base(typeof(SubscriptionEnabledRuntimeFieldExecutionController)) + { + _fieldDefinition = fieldDefinition; + if (fieldDefinition.Resolver?.Method != null) + { + _fieldProvider = new MemberInfoProvider( + fieldDefinition.Resolver.Method, + new RuntimeSchemaItemAttributeProvider(fieldDefinition)); + } + } + + /// + protected override IEnumerable GatherPossibleFieldTemplates() + { + yield return _fieldProvider; + } + + /// + protected override bool CouldBeGraphField(IMemberInfoProvider fieldProvider) + { + return fieldProvider != null && fieldProvider == _fieldProvider; + } + + /// + public override void ValidateOrThrow() + { + if (_fieldDefinition?.Resolver?.Method == null) + { + throw new GraphTypeDeclarationException( + $"Unable to templatize the runtime field definition of '{_fieldDefinition?.Route.Path ?? "~null~"}' the resolver " + + $"is not properly configured."); + } + + base.ValidateOrThrow(); + } + + /// + public override ItemSource TemplateSource => ItemSource.Runtime; + } +} \ No newline at end of file diff --git a/src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionControllerActionGraphFieldTemplate.cs b/src/graphql-aspnet-subscriptions/Schemas/Generation/TypeTemplates/SubscriptionControllerActionGraphFieldTemplate.cs similarity index 98% rename from src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionControllerActionGraphFieldTemplate.cs rename to src/graphql-aspnet-subscriptions/Schemas/Generation/TypeTemplates/SubscriptionControllerActionGraphFieldTemplate.cs index b1776d01e..e46bd7077 100644 --- a/src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionControllerActionGraphFieldTemplate.cs +++ b/src/graphql-aspnet-subscriptions/Schemas/Generation/TypeTemplates/SubscriptionControllerActionGraphFieldTemplate.cs @@ -7,18 +7,18 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.TypeTemplates +namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates { using System; using System.Diagnostics; using System.Linq; using System.Reflection; + using GraphQL.AspNet; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Interfaces.Internal; - using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.TypeSystem; /// diff --git a/src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionGraphArgumentTemplate.cs b/src/graphql-aspnet-subscriptions/Schemas/Generation/TypeTemplates/SubscriptionGraphArgumentTemplate.cs similarity index 94% rename from src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionGraphArgumentTemplate.cs rename to src/graphql-aspnet-subscriptions/Schemas/Generation/TypeTemplates/SubscriptionGraphArgumentTemplate.cs index 4d7f84d04..3f37ff266 100644 --- a/src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionGraphArgumentTemplate.cs +++ b/src/graphql-aspnet-subscriptions/Schemas/Generation/TypeTemplates/SubscriptionGraphArgumentTemplate.cs @@ -7,13 +7,12 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.TypeTemplates +namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates { using System.Reflection; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Interfaces.Internal; - using GraphQL.AspNet.Schemas.Generation.TypeTemplates; /// /// An input argument template that is capable of parsing additional information diff --git a/src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionGraphControllerTemplate.cs b/src/graphql-aspnet-subscriptions/Schemas/Generation/TypeTemplates/SubscriptionGraphControllerTemplate.cs similarity index 94% rename from src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionGraphControllerTemplate.cs rename to src/graphql-aspnet-subscriptions/Schemas/Generation/TypeTemplates/SubscriptionGraphControllerTemplate.cs index 84719c609..2fd4bc100 100644 --- a/src/graphql-aspnet-subscriptions/Internal/TypeTemplates/SubscriptionGraphControllerTemplate.cs +++ b/src/graphql-aspnet-subscriptions/Schemas/Generation/TypeTemplates/SubscriptionGraphControllerTemplate.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Internal.TypeTemplates +namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates { using System; using System.Diagnostics; @@ -16,7 +16,6 @@ namespace GraphQL.AspNet.Internal.TypeTemplates using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Interfaces.Internal; - using GraphQL.AspNet.Schemas.Generation.TypeTemplates; /// /// A set of parsed metadata, read from a declared , to properly diff --git a/src/graphql-aspnet-subscriptions/Engine/TypeMakers/SubscriptionEnabledGraphFieldMaker.cs b/src/graphql-aspnet-subscriptions/Schemas/TypeMakers/SubscriptionEnabledGraphFieldMaker.cs similarity index 88% rename from src/graphql-aspnet-subscriptions/Engine/TypeMakers/SubscriptionEnabledGraphFieldMaker.cs rename to src/graphql-aspnet-subscriptions/Schemas/TypeMakers/SubscriptionEnabledGraphFieldMaker.cs index 3bf6b5009..e6a019715 100644 --- a/src/graphql-aspnet-subscriptions/Engine/TypeMakers/SubscriptionEnabledGraphFieldMaker.cs +++ b/src/graphql-aspnet-subscriptions/Schemas/TypeMakers/SubscriptionEnabledGraphFieldMaker.cs @@ -7,15 +7,7 @@ // License: MIT // ************************************************************* -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* -namespace GraphQL.AspNet.Engine.TypeMakers +namespace GraphQL.AspNet.Schemas.TypeMakers { using System.Collections.Generic; using GraphQL.AspNet.Configuration.Formatting; @@ -23,7 +15,6 @@ namespace GraphQL.AspNet.Engine.TypeMakers using GraphQL.AspNet.Interfaces.Engine; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Internal.TypeTemplates; using GraphQL.AspNet.Schemas.Generation.TypeMakers; using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.TypeSystem; diff --git a/src/graphql-aspnet-subscriptions/SubscriptionServer/SubscriptionReceiverSchemaExtension.cs b/src/graphql-aspnet-subscriptions/SubscriptionServer/SubscriptionReceiverSchemaExtension.cs index f16d85143..a340fda73 100644 --- a/src/graphql-aspnet-subscriptions/SubscriptionServer/SubscriptionReceiverSchemaExtension.cs +++ b/src/graphql-aspnet-subscriptions/SubscriptionServer/SubscriptionReceiverSchemaExtension.cs @@ -95,8 +95,8 @@ public void Configure(SchemaOptions options) // swap out the master templating provider for the schema to one that includes // support for the subscription action type if and only if the developer has not // already registered their own custom one - var existing = _schemaBuilder.Options.ServiceCollection.FirstOrDefault(x => x.ServiceType == typeof(IGraphQLTypeMakerFactory)); - if (existing != null) + var existingTypeMakers = _schemaBuilder.Options.ServiceCollection.FirstOrDefault(x => x.ServiceType == typeof(IGraphQLTypeMakerFactory)); + if (existingTypeMakers != null) { _schemaBuilder.Options .ServiceCollection @@ -111,6 +111,22 @@ public void Configure(SchemaOptions options) typeof(SubscriptionEnabledGraphQLTypeMakerFactory), ServiceLifetime.Transient)); + var existingFactories = _schemaBuilder.Options.ServiceCollection.FirstOrDefault(x => x.ServiceType == typeof(IGraphQLSchemaFactory)); + if (existingFactories != null) + { + _schemaBuilder.Options + .ServiceCollection + .RemoveAll(typeof(IGraphQLSchemaFactory)); + } + + _schemaBuilder.Options + .ServiceCollection + .TryAdd( + new ServiceDescriptor( + typeof(IGraphQLSchemaFactory), + typeof(SubscriptionEnabledGraphQLSchemaFactory), + ServiceLifetime.Transient)); + // Update the query execution pipeline // ------------------------------------------ // Wipe out the current execution pipeline and rebuild with diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Directives.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Directives.cs index 3f4e7a037..7ab773e64 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Directives.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Directives.cs @@ -140,7 +140,7 @@ public static IGraphQLRuntimeDirectiveDefinition AddResolver(this IGraphQLRuntim /// The value to use as the internal name for this field definition when its /// added to the schema. /// IGraphQLRuntimeDirectiveDefinition. - public static IGraphQLRuntimeDirectiveDefinition WithName(this IGraphQLRuntimeDirectiveDefinition directiveTemplate, string internalName) + public static IGraphQLRuntimeDirectiveDefinition WithInternalName(this IGraphQLRuntimeDirectiveDefinition directiveTemplate, string internalName) { Validation.ThrowIfNull(directiveTemplate, nameof(directiveTemplate)); directiveTemplate.InternalName = internalName; diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_VirtualFields.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_FieldGroups.cs similarity index 57% rename from src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_VirtualFields.cs rename to src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_FieldGroups.cs index e38ae92e6..78a0b16b3 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_VirtualFields.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_FieldGroups.cs @@ -12,11 +12,8 @@ namespace GraphQL.AspNet.Configuration using System; using System.Linq; using GraphQL.AspNet.Common; - using GraphQL.AspNet.Execution; - using GraphQL.AspNet.Interfaces.Configuration; using GraphQL.AspNet.Interfaces.Controllers; using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; - using GraphQL.AspNet.Schemas.Generation.RuntimeSchemaItemDefinitions; using Microsoft.AspNetCore.Authorization; /// @@ -35,8 +32,8 @@ public static partial class GraphQLRuntimeSchemaItemDefinitionExtensions /// The name of the policy to assign via this requirement. /// A comma-seperated list of roles to assign via this requirement. /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeFieldDefinition RequireAuthorization( - this IGraphQLRuntimeFieldDefinition fieldBuilder, + public static IGraphQLRuntimeFieldGroupDefinition RequireAuthorization( + this IGraphQLRuntimeFieldGroupDefinition fieldBuilder, string policyName = null, string roles = null) { @@ -63,7 +60,7 @@ public static IGraphQLRuntimeFieldDefinition RequireAuthorization( /// /// The field being built. /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeFieldDefinition AllowAnonymous(this IGraphQLRuntimeFieldDefinition fieldBuilder) + public static IGraphQLRuntimeFieldGroupDefinition AllowAnonymous(this IGraphQLRuntimeFieldGroupDefinition fieldBuilder) { Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); if (!fieldBuilder.Attributes.OfType().Any()) @@ -72,74 +69,13 @@ public static IGraphQLRuntimeFieldDefinition AllowAnonymous(this IGraphQLRuntime return fieldBuilder; } - /// - /// Begins a new field group for the query schema object. All fields created using - /// this group will be nested underneath it and inherit any set parameters such as authorization requirements. - /// - /// The builder to append the query group to. - /// The template path for this group. - /// IGraphQLRuntimeFieldDefinition. - public static IGraphQLRuntimeFieldDefinition MapQueryGroup(this ISchemaBuilder schemaBuilder, string template) - { - return MapQueryGroup(schemaBuilder?.Options, template); - } - - /// - /// Begins a new field group for the query schema object. All fields created using - /// this group will be nested underneath it and inherit any set parameters such as authorization requirements. - /// - /// The schema options to append the query group to. - /// The template path for this group. - /// IGraphQLRuntimeFieldDefinition. - public static IGraphQLRuntimeFieldDefinition MapQueryGroup(this SchemaOptions schemaOptions, string template) - { - return new RuntimeVirtualFieldTemplate(schemaOptions, SchemaItemCollections.Query, template); - } - - /// - /// Begins a new field group for the mutation schema object. All fields created using this group will be nested underneath it and inherit any set parameters such as authorization requirements. - /// - /// The builder to append the mutation group to. - /// The template path for this group. - /// IGraphQLRuntimeFieldDefinition. - public static IGraphQLRuntimeFieldDefinition MapMutationGroup(this ISchemaBuilder schemaBuilder, string template) - { - return MapMutationGroup(schemaBuilder?.Options, template); - } - - /// - /// Begins a new field group for the mutation schema object. All fields created using this group will be nested underneath it and inherit any set parameters such as authorization requirements. - /// - /// The schema options to append the mutation group to. - /// The template path for this group. - /// IGraphQLRuntimeFieldDefinition. - public static IGraphQLRuntimeFieldDefinition MapMutationGroup(this SchemaOptions schemaOptions, string template) - { - return new RuntimeVirtualFieldTemplate(schemaOptions, SchemaItemCollections.Mutation, template); - } - - /// - /// Maps an intermediate child field into the schema. This field will inherit any parameters set from its parent (including the template path). - /// Any fields created from this new group will inherit any parameters set on the group AND the parent group. - /// - /// - /// Any intermediate child fields created via this method will retain their operation association (e.g. Mutation, Query etc.), it cannot be changed. - /// - /// The field under which this new field will be nested. - /// The template pattern to be appended to the supplied . - /// IGraphQLRuntimeFieldDefinition. - public static IGraphQLRuntimeFieldDefinition MapChildGroup(this IGraphQLRuntimeFieldDefinition field, string subTemplate) - { - return new RuntimeVirtualFieldTemplate(field, subTemplate); - } - /// /// Maps a terminal child field into the schema and assigns the resolver method to it. /// /// The field under which this new field will be nested. /// The template pattern to be appended to the supplied . /// IGraphQLResolvedFieldBuilder. - public static IGraphQLRuntimeResolvedFieldDefinition MapField(this IGraphQLRuntimeFieldDefinition field, string subTemplate) + public static IGraphQLRuntimeResolvedFieldDefinition MapField(this IGraphQLRuntimeFieldGroupDefinition field, string subTemplate) { return MapField( field, @@ -156,7 +92,7 @@ public static IGraphQLRuntimeResolvedFieldDefinition MapField(this IGraphQLRunti /// The template pattern to be appended to the supplied . /// The resolver method to be called when this field is requested. /// IGraphQLResolvedFieldBuilder. - public static IGraphQLRuntimeResolvedFieldDefinition MapField(this IGraphQLRuntimeFieldDefinition field, string subTemplate, Delegate resolverMethod) + public static IGraphQLRuntimeResolvedFieldDefinition MapField(this IGraphQLRuntimeFieldGroupDefinition field, string subTemplate, Delegate resolverMethod) { return MapField( field, @@ -175,7 +111,7 @@ public static IGraphQLRuntimeResolvedFieldDefinition MapField(this IGraphQLRunti /// The template pattern to be appended to the supplied . /// The resolver method to be called when this field is requested. /// IGraphQLResolvedFieldBuilder. - public static IGraphQLRuntimeResolvedFieldDefinition MapField(this IGraphQLRuntimeFieldDefinition field, string subTemplate, Delegate resolverMethod) + public static IGraphQLRuntimeResolvedFieldDefinition MapField(this IGraphQLRuntimeFieldGroupDefinition field, string subTemplate, Delegate resolverMethod) { return MapField( field, @@ -193,7 +129,7 @@ public static IGraphQLRuntimeResolvedFieldDefinition MapField(this /// Provide a name and this field will be declared to return a union. Use to declare union members. /// The resolver method to be called when this field is requested. /// IGraphQLResolvedFieldBuilder. - public static IGraphQLRuntimeResolvedFieldDefinition MapField(this IGraphQLRuntimeFieldDefinition field, string subTemplate, string unionName, Delegate resolverMethod) + public static IGraphQLRuntimeResolvedFieldDefinition MapField(this IGraphQLRuntimeFieldGroupDefinition field, string subTemplate, string unionName, Delegate resolverMethod) { return MapField( field, @@ -204,15 +140,13 @@ public static IGraphQLRuntimeResolvedFieldDefinition MapField(this IGraphQLRunti } private static IGraphQLRuntimeResolvedFieldDefinition MapField( - IGraphQLRuntimeFieldDefinition field, + IGraphQLRuntimeFieldGroupDefinition field, string subTemplate, Type expectedReturnType, string unionName, Delegate resolverMethod) { - var subField = new RuntimeResolvedFieldDefinition(field, subTemplate); - subField.Options.AddRuntimeSchemaItem(subField); - + var subField = field.MapField(subTemplate); AddResolverInternal(subField, expectedReturnType, unionName, resolverMethod); return subField; } diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Internals.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Internals.cs index ff4edfcd2..43264c1e1 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Internals.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Internals.cs @@ -82,7 +82,7 @@ private static TItemType AddPossibleTypesInternal(TItemType fieldBuil return fieldBuilder; } - private static IGraphQLRuntimeFieldDefinition MapGraphQLFieldInternal( + private static IGraphQLRuntimeFieldGroupDefinition MapGraphQLFieldInternal( SchemaOptions schemaOptions, GraphOperationType operationType, string pathTemplate) @@ -90,7 +90,7 @@ private static IGraphQLRuntimeFieldDefinition MapGraphQLFieldInternal( schemaOptions = Validation.ThrowIfNullOrReturn(schemaOptions, nameof(schemaOptions)); pathTemplate = Validation.ThrowIfNullWhiteSpaceOrReturn(pathTemplate, nameof(pathTemplate)); - var fieldTemplate = new RuntimeVirtualFieldTemplate( + var fieldTemplate = new RuntimeFieldGroupTemplate( schemaOptions, (SchemaItemCollections)operationType, pathTemplate); diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Mutations.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Mutations.cs index 5e75271b8..4e24c694b 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Mutations.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Mutations.cs @@ -10,9 +10,9 @@ namespace GraphQL.AspNet.Configuration { using System; - using System.Linq; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Common; + using GraphQL.AspNet.Execution; using GraphQL.AspNet.Interfaces.Configuration; using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; using GraphQL.AspNet.Schemas.Generation.RuntimeSchemaItemDefinitions; @@ -23,6 +23,28 @@ namespace GraphQL.AspNet.Configuration /// public static partial class GraphQLRuntimeSchemaItemDefinitionExtensions { + /// + /// Begins a new field group for the mutation schema object. All fields created using this group will be nested underneath it and inherit any set parameters such as authorization requirements. + /// + /// The builder to append the mutation group to. + /// The template path for this group. + /// IGraphQLRuntimeFieldDefinition. + public static IGraphQLRuntimeFieldGroupDefinition MapMutationGroup(this ISchemaBuilder schemaBuilder, string template) + { + return MapMutationGroup(schemaBuilder?.Options, template); + } + + /// + /// Begins a new field group for the mutation schema object. All fields created using this group will be nested underneath it and inherit any set parameters such as authorization requirements. + /// + /// The schema options to append the mutation group to. + /// The template path for this group. + /// IGraphQLRuntimeFieldDefinition. + public static IGraphQLRuntimeFieldGroupDefinition MapMutationGroup(this SchemaOptions schemaOptions, string template) + { + return new RuntimeFieldGroupTemplate(schemaOptions, SchemaItemCollections.Mutation, template); + } + /// /// Creates a new, explicitly resolvable field in the mutation root object with the given path. This field cannot be /// further extended or nested with other fields via the Mapping API. diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Queries.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Queries.cs index f5302dda9..af02bcd82 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Queries.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_Queries.cs @@ -10,20 +10,43 @@ namespace GraphQL.AspNet.Configuration { using System; - using System.Linq; using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Common; + using GraphQL.AspNet.Execution; using GraphQL.AspNet.Interfaces.Configuration; using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; using GraphQL.AspNet.Schemas.Generation.RuntimeSchemaItemDefinitions; using GraphQL.AspNet.Schemas.TypeSystem; - using Microsoft.VisualBasic; /// /// Extension methods for configuring minimal API methods as fields on the graph. /// public static partial class GraphQLRuntimeSchemaItemDefinitionExtensions { + /// + /// Begins a new field group for the query schema object. All fields created using + /// this group will be nested underneath it and inherit any set parameters such as authorization requirements. + /// + /// The builder to append the query group to. + /// The template path for this group. + /// IGraphQLRuntimeFieldDefinition. + public static IGraphQLRuntimeFieldGroupDefinition MapQueryGroup(this ISchemaBuilder schemaBuilder, string template) + { + return MapQueryGroup(schemaBuilder?.Options, template); + } + + /// + /// Begins a new field group for the query schema object. All fields created using + /// this group will be nested underneath it and inherit any set parameters such as authorization requirements. + /// + /// The schema options to append the query group to. + /// The template path for this group. + /// IGraphQLRuntimeFieldDefinition. + public static IGraphQLRuntimeFieldGroupDefinition MapQueryGroup(this SchemaOptions schemaOptions, string template) + { + return new RuntimeFieldGroupTemplate(schemaOptions, SchemaItemCollections.Query, template); + } + /// /// Creates a new, explicitly resolvable field in the query root object with the given path. This field cannot be /// further extended or nested with other fields via the Mapping API. diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_ResolvedFields.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_ResolvedFields.cs index 405a242b9..c7eb91ed2 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_ResolvedFields.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_ResolvedFields.cs @@ -103,7 +103,7 @@ public static IGraphQLRuntimeResolvedFieldDefinition ClearPossibleTypes(this IGr /// The value to use as the internal name for this field definition when its /// added to the schema. /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeResolvedFieldDefinition WithName(this IGraphQLRuntimeResolvedFieldDefinition fieldBuilder, string internalName) + public static IGraphQLRuntimeResolvedFieldDefinition WithInternalName(this IGraphQLRuntimeResolvedFieldDefinition fieldBuilder, string internalName) { Validation.ThrowIfNull(fieldBuilder, nameof(fieldBuilder)); fieldBuilder.InternalName = internalName?.Trim(); diff --git a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_TypeExtensions.cs b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_TypeExtensions.cs index c7b1a51c2..accaf668a 100644 --- a/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_TypeExtensions.cs +++ b/src/graphql-aspnet/Configuration/GraphQLRuntimeSchemaItemDefinitionExtensions_TypeExtensions.cs @@ -335,7 +335,7 @@ public static IGraphQLRuntimeTypeExtensionDefinition ClearPossibleTypes(this IGr /// The value to use as the internal name for this field definition when its /// added to the schema. /// IGraphQLFieldBuilder. - public static IGraphQLRuntimeTypeExtensionDefinition WithName(this IGraphQLRuntimeTypeExtensionDefinition typeExtension, string internalName) + public static IGraphQLRuntimeTypeExtensionDefinition WithInternalName(this IGraphQLRuntimeTypeExtensionDefinition typeExtension, string internalName) { typeExtension.InternalName = internalName; return typeExtension; diff --git a/src/graphql-aspnet/Configuration/SchemaOptions.cs b/src/graphql-aspnet/Configuration/SchemaOptions.cs index cd8962d01..41ae55cef 100644 --- a/src/graphql-aspnet/Configuration/SchemaOptions.cs +++ b/src/graphql-aspnet/Configuration/SchemaOptions.cs @@ -336,14 +336,14 @@ internal void FinalizeServiceRegistration() } /// - /// Adds "runtime declared" schema item to this instance so that it can be - /// created and registered when the schema is set up. + /// Adds a "runtime declared" schema item to this instance so that it can be + /// registered when the schema is set up. /// /// - /// "Runtime declared" schema items are synonymous with minimal api defined fields. + /// "Runtime declared" schema items are synonymous with minimal api defined fields and directives. /// /// The schema item to include. - internal void AddRuntimeSchemaItem(IGraphQLRuntimeSchemaItemDefinition template) + public void AddRuntimeSchemaItem(IGraphQLRuntimeSchemaItemDefinition template) { this.ServiceCollection.AddRuntimeFieldExecutionSupport(); _runtimeTemplates.Add(template); diff --git a/src/graphql-aspnet/Controllers/GraphControllerBase.cs b/src/graphql-aspnet/Controllers/GraphControllerBase.cs index 4e6751cfc..602ac0ca4 100644 --- a/src/graphql-aspnet/Controllers/GraphControllerBase.cs +++ b/src/graphql-aspnet/Controllers/GraphControllerBase.cs @@ -10,6 +10,7 @@ namespace GraphQL.AspNet.Controllers { using System; + using System.Data.SqlTypes; using System.Reflection; using System.Security.Claims; using System.Threading.Tasks; @@ -23,6 +24,7 @@ namespace GraphQL.AspNet.Controllers using GraphQL.AspNet.Interfaces.Execution; using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Interfaces.Web; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using Microsoft.AspNetCore.Http; /// @@ -136,22 +138,45 @@ internal virtual async Task InvokeActionAsync( /// The exact return value from the invoked resolver. protected virtual object CreateAndInvokeAction(IGraphFieldResolverMetaData resolverMetaData, object[] invocationArguments) { - if (resolverMetaData.Method.DeclaringType != this.GetType()) + switch (resolverMetaData.DefinitionSource) { - throw new TargetException($"Unable to invoke action '{_resolverMetaData.InternalName}' on controller '{this.GetType().FriendlyName()}'. The controller " + - "does not own the method."); - } + case ItemSource.DesignTime: + if (resolverMetaData.Method.DeclaringType != this.GetType()) + { + throw new TargetException($"Unable to invoke action '{_resolverMetaData.InternalName}' on controller '{this.GetType().FriendlyName()}'. The controller " + + "does not own the method."); + } - if (resolverMetaData.Method.IsStatic) - { - throw new TargetException($"Unable to invoke action '{_resolverMetaData.InternalName}' on controller '{this.GetType().FriendlyName()}'. The method " + - "is static and cannot be directly invoked on this controller instance."); - } + if (resolverMetaData.Method.IsStatic) + { + throw new TargetException($"Unable to invoke action '{_resolverMetaData.InternalName}' on controller '{this.GetType().FriendlyName()}'. The method " + + "is static and cannot be directly invoked on this controller instance."); + } - var invoker = InstanceFactory.CreateInstanceMethodInvoker(resolverMetaData.Method); + var ctrlInvoker = InstanceFactory.CreateInstanceMethodInvoker(resolverMetaData.Method); + var controllerRef = this as object; + return ctrlInvoker(ref controllerRef, invocationArguments); - var controllerRef = this as object; - return invoker(ref controllerRef, invocationArguments); + case ItemSource.Runtime: + // minimal api resolvers are allowed to be static since there is no + // extra context to setup or make available such as 'this.User' etc. + if (resolverMetaData.Method.IsStatic) + { + var staticInvoker = InstanceFactory.CreateStaticMethodInvoker(resolverMetaData.Method); + return staticInvoker(invocationArguments); + } + else + { + var instanceInvoker = InstanceFactory.CreateInstanceMethodInvoker(resolverMetaData.Method); + var instance = InstanceFactory.CreateInstance(resolverMetaData.Method.DeclaringType); + return instanceInvoker(ref instance, invocationArguments); + } + + default: + throw new TargetException( + $"Unable to execute the target resolver {resolverMetaData.InternalName}. " + + $"Invalid or unsupported source location '{_resolverMetaData.DefinitionSource}'."); + } } /// diff --git a/src/graphql-aspnet/Controllers/RuntimeFieldExecutionController.cs b/src/graphql-aspnet/Controllers/RuntimeFieldExecutionController.cs index 60aa2d923..0140c97f7 100644 --- a/src/graphql-aspnet/Controllers/RuntimeFieldExecutionController.cs +++ b/src/graphql-aspnet/Controllers/RuntimeFieldExecutionController.cs @@ -10,8 +10,6 @@ namespace GraphQL.AspNet.Controllers { using GraphQL.AspNet.Attributes; - using GraphQL.AspNet.Common.Generics; - using GraphQL.AspNet.Interfaces.Execution; /// /// A special controller instance for executing runtime configured controller @@ -20,22 +18,5 @@ namespace GraphQL.AspNet.Controllers [GraphRoot] internal sealed class RuntimeFieldExecutionController : GraphController { - /// - protected override object CreateAndInvokeAction(IGraphFieldResolverMetaData resolverMetaData, object[] invocationArguments) - { - // minimal api resolvers are allowed to be static since there is no - // extra context to setup or make available such as 'this.User' etc. - if (resolverMetaData.Method.IsStatic) - { - var invoker = InstanceFactory.CreateStaticMethodInvoker(resolverMetaData.Method); - return invoker(invocationArguments); - } - else - { - var invoker = InstanceFactory.CreateInstanceMethodInvoker(resolverMetaData.Method); - var instance = InstanceFactory.CreateInstance(resolverMetaData.Method.DeclaringType); - return invoker(ref instance, invocationArguments); - } - } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_RuntimeDefinitions.cs b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_RuntimeDefinitions.cs index 62bf743ec..fedd6e9a4 100644 --- a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_RuntimeDefinitions.cs +++ b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory_RuntimeDefinitions.cs @@ -9,11 +9,8 @@ namespace GraphQL.AspNet.Engine { - using System; - using System.Reflection.Metadata; using GraphQL.AspNet.Common; using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; - using GraphQL.AspNet.Schemas.Generation.RuntimeSchemaItemDefinitions; using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.TypeSystem; @@ -39,7 +36,6 @@ protected virtual void AddRuntimeSchemaItemDefinition(IGraphQLRuntimeSchemaItemD this.AddRuntimeDirectiveDefinition(directiveDef); break; - // TODO: Add support for directives // TODO: Add warning log entries for unsupported item defs. } } diff --git a/src/graphql-aspnet/Execution/Resolvers/FieldResolverMetaData.cs b/src/graphql-aspnet/Execution/Resolvers/FieldResolverMetaData.cs index 8b4b9c286..47815ed92 100644 --- a/src/graphql-aspnet/Execution/Resolvers/FieldResolverMetaData.cs +++ b/src/graphql-aspnet/Execution/Resolvers/FieldResolverMetaData.cs @@ -14,6 +14,7 @@ namespace GraphQL.AspNet.Execution.Resolvers using System.Reflection; using GraphQL.AspNet.Common; using GraphQL.AspNet.Interfaces.Execution; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; /// /// A metadata object containing parsed and computed values related to @@ -35,6 +36,7 @@ internal class FieldResolverMetaData : IGraphFieldResolverMetaData /// The exact name of the resolver method or property name as its declared in source code. /// The type of the .NET class or struct where the resolver method is declared. /// The name of the .NET class or struct where the resolver method is declared. + /// A value indicating where the code that this resolver represents was declared. public FieldResolverMetaData( MethodInfo method, IGraphFieldResolverParameterMetaDataCollection parameters, @@ -43,7 +45,8 @@ public FieldResolverMetaData( string internalName, string declaredName, Type parentObjectType, - string parentInternalName) + string parentInternalName, + ItemSource itemSource) { this.Method = Validation.ThrowIfNullOrReturn(method, nameof(method)); @@ -56,6 +59,7 @@ public FieldResolverMetaData( this.DeclaredName = Validation.ThrowIfNullWhiteSpaceOrReturn(declaredName, nameof(declaredName)); this.ParentObjectType = Validation.ThrowIfNullOrReturn(parentObjectType, nameof(parentObjectType)); this.ParentInternalName = Validation.ThrowIfNullWhiteSpaceOrReturn(parentInternalName, nameof(parentInternalName)); + this.DefinitionSource = itemSource; } /// @@ -81,5 +85,8 @@ public FieldResolverMetaData( /// public string DeclaredName { get; } + + /// + public ItemSource DefinitionSource { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Execution/Resolvers/InternalFieldResolverMetaData.cs b/src/graphql-aspnet/Execution/Resolvers/InternalFieldResolverMetaData.cs index 0d42bf5eb..c9bdaf5cf 100644 --- a/src/graphql-aspnet/Execution/Resolvers/InternalFieldResolverMetaData.cs +++ b/src/graphql-aspnet/Execution/Resolvers/InternalFieldResolverMetaData.cs @@ -14,6 +14,7 @@ namespace GraphQL.AspNet.Execution.Resolvers using GraphQL.AspNet.Common; using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Interfaces.Execution; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; /// /// A helper class for generating valid metadata for introspection and other internal value resolvers @@ -26,7 +27,7 @@ internal static class InternalFieldResolverMetaData /// /// The type that will masqurade as "owning" the resolver. /// IGraphFieldResolverMetaData. - public static IGraphFieldResolverMetaData CreateMetadata(Type owningType) + internal static IGraphFieldResolverMetaData CreateMetadata(Type owningType) { Validation.ThrowIfNull(owningType, nameof(owningType)); @@ -41,7 +42,8 @@ public static IGraphFieldResolverMetaData CreateMetadata(Type owningType) nameof(InternalValueResolver), methodInfo.Name, owningType, - owningType.FriendlyName()); + owningType.FriendlyName(), + ItemSource.DesignTime); } private static int InternalValueResolver() diff --git a/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverMetaData.cs b/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverMetaData.cs index 36654115f..2698456ea 100644 --- a/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverMetaData.cs +++ b/src/graphql-aspnet/Interfaces/Execution/IGraphFieldResolverMetaData.cs @@ -11,6 +11,7 @@ namespace GraphQL.AspNet.Interfaces.Execution { using System; using System.Reflection; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; /// /// A data package describing the details necessary to @@ -80,5 +81,14 @@ public interface IGraphFieldResolverMetaData /// /// The arguments defined on this field. IGraphFieldResolverParameterMetaDataCollection Parameters { get; } + + /// + /// Gets a value indicating whether this resolver is defined at runtime. + /// + /// + /// A runtime defined resolver indicates use of minimal api methods. + /// + /// true if this instance is defined at runtime; otherwise, false. + ItemSource DefinitionSource { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Internal/IGraphTypeTemplate.cs b/src/graphql-aspnet/Interfaces/Internal/IGraphTypeTemplate.cs index 6f2b7e928..8fa3ba049 100644 --- a/src/graphql-aspnet/Interfaces/Internal/IGraphTypeTemplate.cs +++ b/src/graphql-aspnet/Interfaces/Internal/IGraphTypeTemplate.cs @@ -11,6 +11,7 @@ namespace GraphQL.AspNet.Interfaces.Internal { using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.TypeSystem; /// @@ -37,5 +38,11 @@ public interface IGraphTypeTemplate : ISchemaItemTemplate, ISecureItem /// /// true if publish; otherwise, false. bool Publish { get; } + + /// + /// Gets the location where the type this template represents was declared. + /// + /// The template source. + ItemSource TemplateSource { get; } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeFieldDefinition.cs b/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeFieldDefinition.cs deleted file mode 100644 index 8ee426e14..000000000 --- a/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeFieldDefinition.cs +++ /dev/null @@ -1,19 +0,0 @@ -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - -namespace GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions -{ - /// - /// An intermediate template that utilizies a key/value pair system to build up a set of component parts - /// that the templating engine will use to generate a full fledged field in a schema. - /// - public interface IGraphQLRuntimeFieldDefinition : IGraphQLRuntimeSchemaItemDefinition - { - } -} \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeFieldGroupDefinition.cs b/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeFieldGroupDefinition.cs new file mode 100644 index 000000000..f6ec533bf --- /dev/null +++ b/src/graphql-aspnet/Interfaces/Schema/RuntimeDefinitions/IGraphQLRuntimeFieldGroupDefinition.cs @@ -0,0 +1,33 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions +{ + /// + /// An intermediate template that utilizies a key/value pair system to build up a set of component parts + /// that the templating engine will use to generate a full fledged field in a schema. + /// + public interface IGraphQLRuntimeFieldGroupDefinition : IGraphQLRuntimeSchemaItemDefinition + { + /// + /// Creates a new, resolvable field as a child of this group instance. + /// + /// The path template to incorporate on the field. + /// IGraphQLRuntimeResolvedFieldDefinition. + IGraphQLRuntimeResolvedFieldDefinition MapField(string pathTemplate); + + /// + /// Creates an intermediate child group, nested under this group instance with the given + /// path template. + /// + /// The path template to incorpate on the child group. + /// IGraphQLRuntimeFieldGroupDefinition. + IGraphQLRuntimeFieldGroupDefinition MapChildGroup(string pathTemplate); + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/BaseRuntimeControllerActionDefinition.cs b/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeControllerActionDefinitionBase.cs similarity index 86% rename from src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/BaseRuntimeControllerActionDefinition.cs rename to src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeControllerActionDefinitionBase.cs index e3b24266f..4767bd75a 100644 --- a/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/BaseRuntimeControllerActionDefinition.cs +++ b/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeControllerActionDefinitionBase.cs @@ -22,25 +22,25 @@ namespace GraphQL.AspNet.Schemas.Generation.RuntimeSchemaItemDefinitions /// An abstract class containing all the common elements across minimal field builders and /// their supporting classes. /// - internal abstract class BaseRuntimeControllerActionDefinition : IGraphQLRuntimeSchemaItemDefinition + public abstract class RuntimeControllerActionDefinitionBase : IGraphQLRuntimeSchemaItemDefinition { - private readonly IGraphQLRuntimeFieldDefinition _parentField; + private readonly IGraphQLRuntimeFieldGroupDefinition _parentField; /// - /// Prevents a default instance of the class from being created. + /// Prevents a default instance of the class from being created. /// - private BaseRuntimeControllerActionDefinition() + private RuntimeControllerActionDefinitionBase() { this.AppendedAttributes = new List(); } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The schema options where this field item /// is being defined. /// The full route to use for this schema item. - protected BaseRuntimeControllerActionDefinition( + protected RuntimeControllerActionDefinitionBase( SchemaOptions options, SchemaItemPath route) : this() @@ -50,13 +50,13 @@ protected BaseRuntimeControllerActionDefinition( } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The schema options where this field item /// is being defined. /// The schema collection this item will belong to. /// The path template identifying this item. - protected BaseRuntimeControllerActionDefinition( + protected RuntimeControllerActionDefinitionBase( SchemaOptions options, SchemaItemCollections collection, string pathTemplate) @@ -69,13 +69,13 @@ protected BaseRuntimeControllerActionDefinition( } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The field from which this entity is being added. /// The partial path template defined for this /// individual entity. - protected BaseRuntimeControllerActionDefinition( - IGraphQLRuntimeFieldDefinition parentField, + protected RuntimeControllerActionDefinitionBase( + IGraphQLRuntimeFieldGroupDefinition parentField, string partialPathTemplate) : this() { diff --git a/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeDirectiveActionDefinition.cs b/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeDirectiveActionDefinition.cs index 2c908cdb7..5d068c709 100644 --- a/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeDirectiveActionDefinition.cs +++ b/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeDirectiveActionDefinition.cs @@ -23,7 +23,7 @@ namespace GraphQL.AspNet.Schemas.Generation.RuntimeSchemaItemDefinitions /// used to generate new graphql directives via a minimal api style of coding. /// [DebuggerDisplay("{Route.Path}")] - internal class RuntimeDirectiveActionDefinition : BaseRuntimeControllerActionDefinition, IGraphQLRuntimeDirectiveDefinition + public class RuntimeDirectiveActionDefinition : RuntimeControllerActionDefinitionBase, IGraphQLRuntimeDirectiveDefinition { /// /// Initializes a new instance of the class. diff --git a/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeVirtualFieldTemplate.cs b/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeFieldGroupTemplate.cs similarity index 68% rename from src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeVirtualFieldTemplate.cs rename to src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeFieldGroupTemplate.cs index cfcd5ea5e..8e6c7d1a6 100644 --- a/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeVirtualFieldTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeFieldGroupTemplate.cs @@ -16,20 +16,20 @@ namespace GraphQL.AspNet.Schemas.Generation.RuntimeSchemaItemDefinitions using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; /// - /// An internal implementation of the + /// An internal implementation of the /// used to generate new graphql fields via a minimal api style of coding. /// [DebuggerDisplay("{Route.Path}")] - internal class RuntimeVirtualFieldTemplate : BaseRuntimeControllerActionDefinition, IGraphQLRuntimeFieldDefinition + public sealed class RuntimeFieldGroupTemplate : RuntimeFieldGroupTemplateBase, IGraphQLRuntimeFieldGroupDefinition { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The schema options that will own the fields created from /// this builder. /// The schema collection this item will belong to. /// The path template identifying this item. - public RuntimeVirtualFieldTemplate( + public RuntimeFieldGroupTemplate( SchemaOptions options, SchemaItemCollections collection, string pathTemplate) @@ -38,21 +38,29 @@ public RuntimeVirtualFieldTemplate( } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The field from which this entity is being added. /// The partial path template to be appended to /// the parent's already defined template. - public RuntimeVirtualFieldTemplate( - IGraphQLRuntimeFieldDefinition parentField, string fieldSubTemplate) + public RuntimeFieldGroupTemplate( + IGraphQLRuntimeFieldGroupDefinition parentField, string fieldSubTemplate) : base(parentField, fieldSubTemplate) { } /// - protected override Attribute CreatePrimaryAttribute() + public override IGraphQLRuntimeResolvedFieldDefinition MapField(string pathTemplate) { - return null; + var field = new RuntimeResolvedFieldDefinition(this, pathTemplate); + this.Options.AddRuntimeSchemaItem(field); + return field; + } + + /// + public override IGraphQLRuntimeFieldGroupDefinition MapChildGroup(string pathTemplate) + { + return new RuntimeFieldGroupTemplate(this, pathTemplate); } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeFieldGroupTemplateBase.cs b/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeFieldGroupTemplateBase.cs new file mode 100644 index 000000000..39cf02bc4 --- /dev/null +++ b/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeFieldGroupTemplateBase.cs @@ -0,0 +1,64 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Schemas.Generation.RuntimeSchemaItemDefinitions +{ + using System; + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Execution; + using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; + + /// + /// An internal implementation of the + /// used to generate new graphql fields via a minimal api style of coding. + /// + public abstract class RuntimeFieldGroupTemplateBase : RuntimeControllerActionDefinitionBase, IGraphQLRuntimeFieldGroupDefinition + { + /// + /// Initializes a new instance of the class. + /// + /// The schema options that will own the fields created from + /// this builder. + /// The schema collection this item will belong to. + /// The path template identifying this item. + protected RuntimeFieldGroupTemplateBase( + SchemaOptions options, + SchemaItemCollections collection, + string pathTemplate) + : base(options, collection, pathTemplate) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The field from which this entity is being added. + /// The partial path template defined for this + /// individual entity. + protected RuntimeFieldGroupTemplateBase( + IGraphQLRuntimeFieldGroupDefinition parentField, + string partialPathTemplate) + : base(parentField, partialPathTemplate) + { + } + + /// + protected override Attribute CreatePrimaryAttribute() + { + return null; + } + + /// + public abstract IGraphQLRuntimeResolvedFieldDefinition MapField(string pathTemplate); + + /// + public abstract IGraphQLRuntimeFieldGroupDefinition MapChildGroup(string pathTemplate); + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeResolvedFieldDefinition.cs b/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeResolvedFieldDefinition.cs index 35698c5ed..bf7118bbd 100644 --- a/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeResolvedFieldDefinition.cs +++ b/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeResolvedFieldDefinition.cs @@ -23,7 +23,7 @@ namespace GraphQL.AspNet.Schemas.Generation.RuntimeSchemaItemDefinitions /// used to generate new graphql fields via a minimal api style of coding. /// [DebuggerDisplay("{Route.Path}")] - internal class RuntimeResolvedFieldDefinition : BaseRuntimeControllerActionDefinition, IGraphQLRuntimeResolvedFieldDefinition + public class RuntimeResolvedFieldDefinition : RuntimeControllerActionDefinitionBase, IGraphQLRuntimeResolvedFieldDefinition { /// /// Converts the unresolved field into a resolved field. The newly generated field @@ -31,7 +31,7 @@ internal class RuntimeResolvedFieldDefinition : BaseRuntimeControllerActionDefin /// /// The field template. /// IGraphQLResolvedFieldTemplate. - public static IGraphQLRuntimeResolvedFieldDefinition FromFieldTemplate(IGraphQLRuntimeFieldDefinition fieldTemplate) + internal static IGraphQLRuntimeResolvedFieldDefinition FromFieldTemplate(IGraphQLRuntimeFieldGroupDefinition fieldTemplate) { Validation.ThrowIfNull(fieldTemplate, nameof(fieldTemplate)); var field = new RuntimeResolvedFieldDefinition( @@ -49,7 +49,7 @@ public static IGraphQLRuntimeResolvedFieldDefinition FromFieldTemplate(IGraphQLR /// /// The schema options to which this field is being added. /// The full route to use for this item. - private RuntimeResolvedFieldDefinition( + protected RuntimeResolvedFieldDefinition( SchemaOptions schemaOptions, SchemaItemPath route) : base(schemaOptions, route) @@ -77,7 +77,7 @@ public RuntimeResolvedFieldDefinition( /// will be appended. /// The template part to append to the parent field's template. public RuntimeResolvedFieldDefinition( - IGraphQLRuntimeFieldDefinition parentFieldBuilder, + IGraphQLRuntimeFieldGroupDefinition parentFieldBuilder, string fieldSubTemplate) : base(parentFieldBuilder, fieldSubTemplate) { diff --git a/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeTypeExtensionDefinition.cs b/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeTypeExtensionDefinition.cs index 2741e6cb5..f12a05b2e 100644 --- a/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeTypeExtensionDefinition.cs +++ b/src/graphql-aspnet/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeTypeExtensionDefinition.cs @@ -14,18 +14,17 @@ namespace GraphQL.AspNet.Schemas.Generation.RuntimeSchemaItemDefinitions using GraphQL.AspNet.Attributes; using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Execution; - using GraphQL.AspNet.Execution.RulesEngine.RuleSets.DocumentValidation.QueryInputValueSteps; using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; /// - /// An internal implementation of the + /// An internal implementation of the /// used to generate new type extensions via a minimal api style of coding. /// [DebuggerDisplay("{Route.Path}")] - internal class RuntimeTypeExtensionDefinition : RuntimeResolvedFieldDefinition, IGraphQLRuntimeTypeExtensionDefinition + public class RuntimeTypeExtensionDefinition : RuntimeResolvedFieldDefinition, IGraphQLRuntimeTypeExtensionDefinition { /// /// Initializes a new instance of the class. diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveMethodTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveMethodTemplate.cs index 9eff8c11b..5c5abfbe7 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveMethodTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveMethodTemplate.cs @@ -228,7 +228,8 @@ public IGraphFieldResolverMetaData CreateResolverMetaData() this.InternalName, this.Method.Name, this.Parent.ObjectType, - this.Parent.InternalName); + this.Parent.InternalName, + this.Parent.TemplateSource); } /// diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphTypeTemplateBase.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphTypeTemplateBase.cs index 4b44f697a..f50c8aef7 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphTypeTemplateBase.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphTypeTemplateBase.cs @@ -68,5 +68,8 @@ protected override void ParseTemplateDefinition() /// public virtual bool Publish { get; private set; } + + /// + public virtual ItemSource TemplateSource => ItemSource.DesignTime; } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/ItemSource.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/ItemSource.cs new file mode 100644 index 000000000..514edb697 --- /dev/null +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/ItemSource.cs @@ -0,0 +1,29 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Schemas.Generation.TypeTemplates +{ + /// + /// An enum that indicates where a piece of data (typically a graph type or resolver) was templated from. + /// + public enum ItemSource + { + /// + /// Indicates that the data item was created from code declared at design time. That it was a + /// defined, precomipled type in the developer's source code. + /// + DesignTime, + + /// + /// Indicates that the data item was created from code declared at run time. That it was configured + /// at startup, after the program code had been compiled. + /// + Runtime, + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplateBase.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplateBase.cs index 692df3dad..bbadfe03a 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplateBase.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/MethodGraphFieldTemplateBase.cs @@ -129,7 +129,8 @@ public override IGraphFieldResolverMetaData CreateResolverMetaData() this.InternalName, this.Method.Name, this.Parent.ObjectType, - this.Parent.InternalName); + this.Parent.InternalName, + this.Parent.TemplateSource); } /// diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/PropertyGraphFieldTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/PropertyGraphFieldTemplate.cs index c7aa728a5..e728a7979 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/PropertyGraphFieldTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/PropertyGraphFieldTemplate.cs @@ -135,7 +135,8 @@ public override IGraphFieldResolverMetaData CreateResolverMetaData() this.InternalName, this.Property.Name, this.Parent.ObjectType, - this.Parent.InternalName); + this.Parent.InternalName, + this.Parent.TemplateSource); } /// diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/RuntimeGraphControllerTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/RuntimeGraphControllerTemplate.cs index ce54c7b84..37db8c583 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/RuntimeGraphControllerTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/RuntimeGraphControllerTemplate.cs @@ -65,5 +65,8 @@ public override void ValidateOrThrow() base.ValidateOrThrow(); } + + /// + public override ItemSource TemplateSource => ItemSource.Runtime; } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/RuntimeGraphDirectiveTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/RuntimeGraphDirectiveTemplate.cs index 6ebb83104..b29a7c379 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/RuntimeGraphDirectiveTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/RuntimeGraphDirectiveTemplate.cs @@ -87,5 +87,8 @@ public override void ValidateOrThrow() base.ValidateOrThrow(); } + + /// + public override ItemSource TemplateSource => ItemSource.Runtime; } } \ No newline at end of file diff --git a/src/graphql-aspnet/Schemas/Structural/SchemaItemPath.cs b/src/graphql-aspnet/Schemas/Structural/SchemaItemPath.cs index 8a8c9c4d2..bcfe90e49 100644 --- a/src/graphql-aspnet/Schemas/Structural/SchemaItemPath.cs +++ b/src/graphql-aspnet/Schemas/Structural/SchemaItemPath.cs @@ -329,40 +329,6 @@ public IEnumerator GetEnumerator() while (item != null); } - /// - /// Normalizes a given route path fragement removing duplicate seperators, ensuring starting and tail end seperators - /// are correct etc. - /// - /// The fragment to normalize. - /// System.String. - public static string NormalizeFragment(string routefragment) - { - // ensure a working path - routefragment = routefragment?.Trim() ?? string.Empty; - routefragment = routefragment.Replace(RouteConstants.ALT_PATH_SEPERATOR, RouteConstants.PATH_SEPERATOR); - - // doubled up seperators may happen if a 3rd party is joining route fragments (especially if the seperator is a '/') - // trim them down - while (routefragment.Contains(RouteConstants.DOUBLE_PATH_SEPERATOR)) - { - routefragment = routefragment.Replace(RouteConstants.DOUBLE_PATH_SEPERATOR, RouteConstants.PATH_SEPERATOR); - } - - // if the path ends with or starts with a seperator (indicating a potential group segment) - // thats fine but is not needed to identify the segment in and of itself, trim it off - while (routefragment.EndsWith(RouteConstants.PATH_SEPERATOR)) - { - routefragment = routefragment.Substring(0, routefragment.Length - RouteConstants.PATH_SEPERATOR.Length); - } - - while (routefragment.StartsWith(RouteConstants.PATH_SEPERATOR)) - { - routefragment = routefragment.Substring(routefragment.IndexOf(RouteConstants.PATH_SEPERATOR, StringComparison.Ordinal) + RouteConstants.PATH_SEPERATOR.Length); - } - - return routefragment; - } - /// /// Creates a list of all the fully qualified parent paths this path is nested under. /// diff --git a/src/graphql-aspnet/Schemas/Structural/SchemaItemPath_Statics.cs b/src/graphql-aspnet/Schemas/Structural/SchemaItemPath_Statics.cs index 44dacf668..68a0e3d57 100644 --- a/src/graphql-aspnet/Schemas/Structural/SchemaItemPath_Statics.cs +++ b/src/graphql-aspnet/Schemas/Structural/SchemaItemPath_Statics.cs @@ -9,6 +9,7 @@ namespace GraphQL.AspNet.Schemas.Structural { + using System; using System.Linq; using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Execution; @@ -41,6 +42,40 @@ public static string Join(SchemaItemCollections fieldType, params string[] route return SchemaItemPath.Join(fieldType.ToRouteRoot().AsEnumerable().Concat(routeSegments).ToArray()); } + /// + /// Normalizes a given route path fragement removing duplicate seperators, ensuring starting and tail end seperators + /// are correct etc. + /// + /// The fragment to normalize. + /// System.String. + public static string NormalizeFragment(string routefragment) + { + // ensure a working path + routefragment = routefragment?.Trim() ?? string.Empty; + routefragment = routefragment.Replace(RouteConstants.ALT_PATH_SEPERATOR, RouteConstants.PATH_SEPERATOR); + + // doubled up seperators may happen if a 3rd party is joining route fragments (especially if the seperator is a '/') + // trim them down + while (routefragment.Contains(RouteConstants.DOUBLE_PATH_SEPERATOR)) + { + routefragment = routefragment.Replace(RouteConstants.DOUBLE_PATH_SEPERATOR, RouteConstants.PATH_SEPERATOR); + } + + // if the path ends with or starts with a seperator (indicating a potential group segment) + // thats fine but is not needed to identify the segment in and of itself, trim it off + while (routefragment.EndsWith(RouteConstants.PATH_SEPERATOR)) + { + routefragment = routefragment.Substring(0, routefragment.Length - RouteConstants.PATH_SEPERATOR.Length); + } + + while (routefragment.StartsWith(RouteConstants.PATH_SEPERATOR)) + { + routefragment = routefragment.Substring(routefragment.IndexOf(RouteConstants.PATH_SEPERATOR, StringComparison.Ordinal) + RouteConstants.PATH_SEPERATOR.Length); + } + + return routefragment; + } + /// /// Implements the == operator. /// diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/SubscriptionEnabledFieldFieldMakerTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/SubscriptionEnabledFieldFieldMakerTests.cs index dc3782d4e..c186d2a95 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/SubscriptionEnabledFieldFieldMakerTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Engine/SubscriptionEnabledFieldFieldMakerTests.cs @@ -10,18 +10,15 @@ namespace GraphQL.AspNet.Tests.Engine { using System.Linq; - using GraphQL.AspNet.Engine.TypeMakers; using GraphQL.AspNet.Interfaces.Internal; - using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Schemas.Generation.TypeMakers; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.Structural; - using GraphQL.AspNet.Tests.Framework; + using GraphQL.AspNet.Schemas.TypeMakers; using GraphQL.AspNet.Tests.Engine.TestData; + using GraphQL.AspNet.Tests.Framework; using Moq; using NUnit.Framework; - using GraphQL.AspNet.Schemas.Generation; - using GraphQL.AspNet.Schemas; - using GraphQL.AspNet.Engine; - using GraphQL.AspNet.Schemas.Generation.TypeMakers; [TestFixture] public class SubscriptionEnabledFieldFieldMakerTests @@ -43,7 +40,7 @@ public void SubscriptionActionField_TransfersDirectives() var schema = new TestServerBuilder().Build().Schema; - var maker = new SubscriptionEnabledGraphFieldMaker(schema, new GraphArgumentMaker(schema)); + var maker = new SubscriptionEnabledGraphFieldMaker(schema, new GraphArgumentMaker(schema)); var field = maker.CreateField(actionTemplate).Field; diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Mocks/SubscriptionContextBuilder.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Mocks/SubscriptionContextBuilder.cs index db504ce63..096c3f503 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Mocks/SubscriptionContextBuilder.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Mocks/SubscriptionContextBuilder.cs @@ -20,7 +20,6 @@ namespace GraphQL.AspNet.Tests.Mocks using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Interfaces.Security; using GraphQL.AspNet.Interfaces.Subscriptions; - using GraphQL.AspNet.Internal.TypeTemplates; using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.Structural; using Moq; diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/Generation/MappedSubscriptionGroupTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/Generation/MappedSubscriptionGroupTests.cs new file mode 100644 index 000000000..f2fc60a56 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/Generation/MappedSubscriptionGroupTests.cs @@ -0,0 +1,145 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.Generation +{ + using System.Linq; + using GraphQL.AspNet.Attributes; + using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Interfaces.Configuration; + using GraphQL.AspNet.Schemas; + using Microsoft.AspNetCore.Authorization; + using Microsoft.Extensions.DependencyInjection; + using Moq; + using NUnit.Framework; + + [TestFixture] + public class MappedSubscriptionGroupTests + { + [Test] + public void MapSubscriptionGroup_WhenAllowAnonymousAdded_AddsAnonymousAttribute() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapSubscriptionGroup("/path1/path2"); + + field.AllowAnonymous(); + + Assert.AreEqual(1, field.Attributes.Count()); + Assert.IsNotNull(field.Attributes.FirstOrDefault(x => x is AllowAnonymousAttribute)); + } + + [Test] + public void MapSubscriptionGroup_WhenRequireAuthAdded_AddsAuthAttribute() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapSubscriptionGroup("/path1/path2"); + + field.RequireAuthorization("policy1", "roles1"); + + Assert.AreEqual(1, field.Attributes.Count()); + var attrib = field.Attributes.FirstOrDefault(x => x is AuthorizeAttribute) as AuthorizeAttribute; + Assert.IsNotNull(attrib); + Assert.AreEqual("policy1", attrib.Policy); + Assert.AreEqual("roles1", attrib.Roles); + } + + [Test] + public void MapSubscriptionGroup_WhenUnresolvedChildFieldIsAdded_PathIsCorrect() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapSubscriptionGroup("/path1/path2"); + + var childField = field.MapChildGroup("/path3/path4"); + + Assert.AreEqual("[subscription]/path1/path2/path3/path4", childField.Route.Path); + } + + [Test] + public void MapSubscriptionGroup_WhenAllowAnonymousAdded_ThenResolvedField_AddsAnonymousAttributeToField() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapSubscriptionGroup("/path1/path2"); + + field.AllowAnonymous(); + + var chidlField = field.MapField("/path3/path4", (string a) => 1); + + Assert.AreEqual(2, chidlField.Attributes.Count()); + Assert.IsNotNull(chidlField.Attributes.FirstOrDefault(x => x is AllowAnonymousAttribute)); + Assert.IsNotNull(chidlField.Attributes.FirstOrDefault(x => x is SubscriptionRootAttribute)); + } + + [Test] + public void MapSubscriptionGroup_WhenResolvedChildFieldIsAdded_PathIsCorrect() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapSubscriptionGroup("/path1/path2"); + + var childField = field.MapField("/path3/path4", (string a) => 1); + + Assert.AreEqual("[subscription]/path1/path2/path3/path4", childField.Route.Path); + Assert.AreEqual(1, childField.Attributes.Count(x => x is SubscriptionRootAttribute)); + } + + [Test] + public void MapSubscriptionGroup_WhenResolvedChildFieldIsAddedToUnresolvedChildField_PathIsCorrect() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapSubscriptionGroup("/path1/path2"); + var childField = field.MapChildGroup("/path3/path4"); + var resolvedField = childField.MapField("/path5/path6", (string a) => 1); + + Assert.AreEqual("[subscription]/path1/path2/path3/path4/path5/path6", resolvedField.Route.Path); + Assert.AreEqual(1, resolvedField.Attributes.Count(x => x is SubscriptionRootAttribute)); + Assert.IsNotNull(resolvedField.Resolver); + } + + [Test] + public void MapSubscriptionGroup_WhenResolvedChildFieldIsAdded_AndParentPathIsChanged_PathIsCorrect() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapSubscriptionGroup("/path1/path2"); + + var childField = field.MapField("/path3/path4", (string a) => 1); + + Assert.AreEqual("[subscription]/path1/path2/path3/path4", childField.Route.Path); + Assert.AreEqual(1, childField.Attributes.Count(x => x is SubscriptionRootAttribute)); + } + + [Test] + public void MapField_FromSchemaBuilder_WithNoResovler_FieldIsMade_ResolverIsNotSet() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var builderMock = new Mock(); + builderMock.Setup(x => x.Options).Returns(options); + + var childField = builderMock.Object.MapSubscriptionGroup("/path1/path2") + .MapField("myField"); + + Assert.IsNull(childField.Resolver); + Assert.AreEqual(1, childField.Attributes.Count(x => x is SubscriptionRootAttribute)); + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/Generation/MappedSubscriptionTemplateTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/Generation/MappedSubscriptionTemplateTests.cs new file mode 100644 index 000000000..528fe3adb --- /dev/null +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/Generation/MappedSubscriptionTemplateTests.cs @@ -0,0 +1,167 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.Generation +{ + using System.Linq; + using GraphQL.AspNet.Attributes; + using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Interfaces.Configuration; + using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; + using GraphQL.AspNet.Schemas; + using Microsoft.Extensions.DependencyInjection; + using Moq; + using NUnit.Framework; + + [TestFixture] + public class MappedSubscriptionTemplateTests + { + public int TestDelegate(string a) + { + return 0; + } + + [Test] + public void MapSubscription_FromSchemaOptions_WithDelegate_DoesAddFieldToSchema() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapSubscription("/path1/path2", TestDelegate); + + Assert.IsNotNull(field); + Assert.AreEqual("[subscription]/path1/path2", field.Route.Path); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeResolvedFieldDefinition), field); + Assert.AreEqual(1, options.RuntimeTemplates.Count()); + + Assert.AreEqual(1, field.Attributes.Count()); + var SubscriptionRootAttrib = field.Attributes.FirstOrDefault(x => x.GetType() == typeof(SubscriptionRootAttribute)); + Assert.IsNotNull(SubscriptionRootAttrib); + } + + [Test] + public void MapSubscription_FromBuilder_WithDelegate_DoesAddFieldToSchema() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var builderMock = new Mock(); + builderMock.Setup(x => x.Options).Returns(options); + + var field = builderMock.Object.MapSubscription("/path1/path2", TestDelegate); + + Assert.IsNotNull(field); + Assert.AreEqual("[subscription]/path1/path2", field.Route.Path); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeResolvedFieldDefinition), field); + Assert.AreEqual(1, options.RuntimeTemplates.Count()); + Assert.IsNotNull(field.Resolver); + + Assert.AreEqual(1, field.Attributes.Count()); + var SubscriptionRootAttrib = field.Attributes.FirstOrDefault(x => x.GetType() == typeof(SubscriptionRootAttribute)); + Assert.IsNotNull(SubscriptionRootAttrib); + } + + [Test] + public void MapSubscription_FromBuilder_WithNoDelegate_DoesAddFieldToSchema() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var builderMock = new Mock(); + builderMock.Setup(x => x.Options).Returns(options); + + var field = builderMock.Object.MapSubscription("/path1/path2"); + + Assert.IsNotNull(field); + Assert.AreEqual("[subscription]/path1/path2", field.Route.Path); + Assert.IsInstanceOf(typeof(IGraphQLRuntimeResolvedFieldDefinition), field); + Assert.AreEqual(1, options.RuntimeTemplates.Count()); + + Assert.AreEqual(1, field.Attributes.Count()); + var SubscriptionRootAttrib = field.Attributes.FirstOrDefault(x => x.GetType() == typeof(SubscriptionRootAttribute)); + Assert.IsNotNull(SubscriptionRootAttrib); + } + + [Test] + public void MapSubscription_FromBuilder_WithUnionName0_AddsUnionNameToType() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var builderMock = new Mock(); + builderMock.Setup(x => x.Options).Returns(options); + + var field = builderMock.Object.MapSubscription("myField", "myUnion", (string a) => 1); + + var attrib = field.Attributes.OfType().SingleOrDefault(); + + Assert.AreEqual("myUnion", attrib.UnionName); + Assert.AreEqual(1, field.Attributes.Count(x => x is SubscriptionRootAttribute)); + } + + [Test] + public void MapSubscription_WithUnionNameSetToNull_AddsUnionNameToType() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapSubscription("myField", null, (string a) => 1); + + var attrib = field.Attributes.OfType().SingleOrDefault(); + + Assert.IsNull(attrib); + Assert.AreEqual(1, field.Attributes.Count(x => x is SubscriptionRootAttribute)); + } + + [Test] + public void MapSubscription_WithUnionName0_AddsUnionNameToType() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapSubscription("myField", "myUnion", (string a) => 1); + + var attrib = field.Attributes.OfType().SingleOrDefault(); + + Assert.AreEqual("myUnion", attrib.UnionName); + Assert.AreEqual(1, field.Attributes.Count(x => x is SubscriptionRootAttribute)); + } + + [Test] + public void MapSubscription_WithNoResolver_IsCreated() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapSubscription("myField"); + + Assert.IsNull(field.Resolver); + Assert.IsNull(field.ReturnType); + + Assert.IsTrue(options.RuntimeTemplates.Contains(field)); + Assert.AreEqual(1, field.Attributes.Count(x => x is SubscriptionRootAttribute)); + } + + [Test] + public void MapSubscription_WithResolver_AndUnion_IsCreated() + { + var services = new ServiceCollection(); + var options = new SchemaOptions(services); + + var field = options.MapSubscription("myField", "myUnion", () => 1); + + Assert.IsNotNull(field.Resolver); + + Assert.AreEqual(1, field.Attributes.OfType().Count()); + Assert.AreEqual("myUnion", field.Attributes.OfType().Single().UnionName); + Assert.IsTrue(options.RuntimeTemplates.Contains(field)); + Assert.AreEqual(1, field.Attributes.Count(x => x is SubscriptionRootAttribute)); + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeSubscriptionEnabledResolvedFieldDefinitionTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeSubscriptionEnabledResolvedFieldDefinitionTests.cs new file mode 100644 index 000000000..fcb1f3ae8 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/Generation/RuntimeSchemaItemDefinitions/RuntimeSubscriptionEnabledResolvedFieldDefinitionTests.cs @@ -0,0 +1,52 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas.Generation.RuntimeSchemaItemDefinitions +{ + using System.IO; + using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Schemas.Generation.RuntimeSchemaItemDefinitions; + using Microsoft.Extensions.DependencyInjection; + using NUnit.Framework; + + [TestFixture] + public class RuntimeSubscriptionEnabledResolvedFieldDefinitionTests + { + [TestCase("field1", "field1")] + [TestCase("field1/field2", "field1_field2")] + [TestCase("/field1/field2", "field1_field2")] + [TestCase("/field1/field2/", "field1_field2")] + [TestCase("/field1/field2/field3/field4/field5", "field1_field2_field3_field4_field5")] + [TestCase("field1/field_2_/field_3", "field1_field_2__field_3")] + public void NoEventNameSupplied_EventNameIsSetToFieldName(string path, string expectedEventName) + { + var collection = new ServiceCollection(); + var options = new SchemaOptions(collection); + + var field = new RuntimeSubscriptionEnabledFieldGroupTemplate(options, path); + var resolvedField = RuntimeSubscriptionEnabledResolvedFieldDefinition.FromFieldTemplate(field); + + Assert.AreEqual(expectedEventName, resolvedField.EventName); + } + + [Test] + public void EventNameSupplied_IsSetToProvidedName() + { + var collection = new ServiceCollection(); + var options = new SchemaOptions(collection); + + var field = new RuntimeSubscriptionEnabledFieldGroupTemplate(options, "field1"); + var resolvedField = RuntimeSubscriptionEnabledResolvedFieldDefinition.FromFieldTemplate(field); + resolvedField.EventName = "theEventName"; + + Assert.AreEqual("theEventName", resolvedField.EventName); + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/ActionTestData/OneMethodSubscriptionController.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/Generation/TypeTemplates/ActionTestData/OneMethodSubscriptionController.cs similarity index 89% rename from src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/ActionTestData/OneMethodSubscriptionController.cs rename to src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/Generation/TypeTemplates/ActionTestData/OneMethodSubscriptionController.cs index 427c7f34e..1b73d9376 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/ActionTestData/OneMethodSubscriptionController.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/Generation/TypeTemplates/ActionTestData/OneMethodSubscriptionController.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ActionTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ActionTestData { using System.ComponentModel; using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/ActionTestData/SubscriptionMethodController.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/Generation/TypeTemplates/ActionTestData/SubscriptionMethodController.cs similarity index 96% rename from src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/ActionTestData/SubscriptionMethodController.cs rename to src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/Generation/TypeTemplates/ActionTestData/SubscriptionMethodController.cs index 294895235..0f91683e2 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/ActionTestData/SubscriptionMethodController.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/Generation/TypeTemplates/ActionTestData/SubscriptionMethodController.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ActionTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ActionTestData { using System.ComponentModel; using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/ControllerTestData/SimpleSubscriptionController.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/Generation/TypeTemplates/ControllerTestData/SimpleSubscriptionController.cs similarity index 92% rename from src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/ControllerTestData/SimpleSubscriptionController.cs rename to src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/Generation/TypeTemplates/ControllerTestData/SimpleSubscriptionController.cs index fb44ccd21..70f5b83e2 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/ControllerTestData/SimpleSubscriptionController.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/Generation/TypeTemplates/ControllerTestData/SimpleSubscriptionController.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating.ControllerTestData +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ControllerTestData { using System.Threading.Tasks; using GraphQL.AspNet.Attributes; diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/GraphActionTemplateTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/Generation/TypeTemplates/GraphActionTemplateTests.cs similarity index 96% rename from src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/GraphActionTemplateTests.cs rename to src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/Generation/TypeTemplates/GraphActionTemplateTests.cs index 174ebffde..48004174c 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/GraphActionTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/Generation/TypeTemplates/GraphActionTemplateTests.cs @@ -7,19 +7,18 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates { using System.Linq; using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Execution; using GraphQL.AspNet.Execution.Exceptions; - using GraphQL.AspNet.Interfaces.Execution; using GraphQL.AspNet.Interfaces.Internal; - using GraphQL.AspNet.Internal.TypeTemplates; + using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.Structural; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Tests.Common.CommonHelpers; - using GraphQL.AspNet.Tests.Internal.Templating.ActionTestData; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ActionTestData; using Moq; using NUnit.Framework; diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/GraphControllerTemplateTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/Generation/TypeTemplates/GraphControllerTemplateTests.cs similarity index 86% rename from src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/GraphControllerTemplateTests.cs rename to src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/Generation/TypeTemplates/GraphControllerTemplateTests.cs index 4395ceb95..79c5808a3 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Internal/Templating/GraphControllerTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/Generation/TypeTemplates/GraphControllerTemplateTests.cs @@ -7,12 +7,11 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Tests.Internal.Templating +namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates { using System.Linq; - using GraphQL.AspNet.Internal.TypeTemplates; using GraphQL.AspNet.Schemas.Generation.TypeTemplates; - using GraphQL.AspNet.Tests.Internal.Templating.ControllerTestData; + using GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ControllerTestData; using NUnit.Framework; [TestFixture] diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/RuntimeFieldGeneralTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/RuntimeFieldGeneralTests.cs new file mode 100644 index 000000000..0fdd52416 --- /dev/null +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/RuntimeFieldGeneralTests.cs @@ -0,0 +1,39 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Schemas +{ + using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Tests.Common.CommonHelpers; + using GraphQL.AspNet.Tests.Framework; + using GraphQL.AspNet.Tests.Mocks; + using NUnit.Framework; + + [TestFixture] + public class RuntimeFieldGeneralTests + { + [Test] + public void General_SubscriptionField_IsRegistered() + { + var server = new TestServerBuilder() + .AddGraphQL(o => + { + o.MapSubscription("field1", (TwoPropertyObject source, int param1) => source); + }) + .AddSubscriptionServer() + .Build(); + + var operation = server.Schema.Operations[GraphOperationType.Subscription]; + var field = operation.Fields.FindField("field1"); + Assert.IsNotNull(field); + Assert.AreEqual("field1", field.Name); + } + } +} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionReceiverExtensionTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionReceiverExtensionTests.cs index 767a72e10..f9e748e7a 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionReceiverExtensionTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionReceiverExtensionTests.cs @@ -83,11 +83,12 @@ public void ServiceCollection_VerifyDefaultInjectedObjects() Assert.IsTrue(primaryOptions.DeclarationOptions.AllowedOperations.Contains(GraphOperationType.Subscription)); - Assert.AreEqual(9, primaryOptions.ServiceCollection.Count); + Assert.AreEqual(10, primaryOptions.ServiceCollection.Count); // primary server objects Assert.IsNotNull(primaryOptions.ServiceCollection.SingleOrDefault(x => x.ServiceType == typeof(SubscriptionServerOptions))); Assert.IsNotNull(primaryOptions.ServiceCollection.SingleOrDefault(x => x.ImplementationType == typeof(SubscriptionEnabledGraphQLTypeMakerFactory))); + Assert.IsNotNull(primaryOptions.ServiceCollection.SingleOrDefault(x => x.ImplementationType == typeof(SubscriptionEnabledGraphQLSchemaFactory))); Assert.IsNotNull(primaryOptions.ServiceCollection.SingleOrDefault(x => x.ServiceType == typeof(ISubscriptionServerClientFactory))); Assert.IsNotNull(primaryOptions.ServiceCollection.SingleOrDefault(x => x.ServiceType == typeof(IGlobalSubscriptionClientProxyCollection))); Assert.IsNotNull(primaryOptions.ServiceCollection.SingleOrDefault(x => x.ServiceType == typeof(ISubscriptionEventDispatchQueue))); diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/SubscriptionClientDispatchQueueAlerterTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/SubscriptionClientDispatchQueueAlerterTests.cs index 5fd2d974e..d071d0c58 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/SubscriptionClientDispatchQueueAlerterTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/SubscriptionClientDispatchQueueAlerterTests.cs @@ -11,7 +11,6 @@ namespace GraphQL.AspNet.Tests.SubscriptionServer { using System; using System.Threading.Tasks; - using GraphQL.AspNet.Internal; using GraphQL.AspNet.Logging; using GraphQL.AspNet.Logging.SubscriptionEvents; using GraphQL.AspNet.SubscriptionServer; diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/SubscriptionClientDispatchQueueTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/SubscriptionClientDispatchQueueTests.cs index 1a685d03a..d779f9b0d 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/SubscriptionClientDispatchQueueTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/SubscriptionClientDispatchQueueTests.cs @@ -13,10 +13,8 @@ namespace GraphQL.AspNet.Tests.SubscriptionServer using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; - using GraphQL.AspNet.Common; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Subscriptions; - using GraphQL.AspNet.Internal; using GraphQL.AspNet.SubscriptionServer; using Microsoft.Extensions.Logging; using Moq; diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedDirectiveTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedDirectiveTemplateTests.cs index e3e1e3cd7..a0c588e82 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedDirectiveTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedDirectiveTemplateTests.cs @@ -58,7 +58,7 @@ public void MapDirective_WhenNameApplied_NameIsAttchedToFieldDeclaration() var directive = builderMock.Object .MapDirective("@myDirective") - .WithName("internalDirectiveName"); + .WithInternalName("internalDirectiveName"); Assert.AreEqual("internalDirectiveName", directive.InternalName); } diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedTypeExtensionTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedTypeExtensionTemplateTests.cs index 998c65580..dbeb13e05 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedTypeExtensionTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/MappedTypeExtensionTemplateTests.cs @@ -69,7 +69,6 @@ public void MapTypeExtension_ByOptions_AndTypeDeclaration_AddsTypeExtensionToOpt Assert.IsNotNull(typeExtensionAttrib); } - [Test] public void MapTypeExtension_ByOptions_WithTypeParameter_AddsTypeExtensionToOptions() { @@ -92,8 +91,6 @@ public void MapTypeExtension_ByOptions_WithTypeParameter_AddsTypeExtensionToOpti Assert.IsNotNull(typeExtensionAttrib); } - - [Test] public void MapTypeExtension_WithName_AddsInternalName() { @@ -104,7 +101,7 @@ public void MapTypeExtension_WithName_AddsInternalName() builderMock.Setup(x => x.Options).Returns(options); var typeExt = builderMock.Object.MapTypeExtension("mytypeExt") - .WithName("internaltypeExtName"); + .WithInternalName("internaltypeExtName"); Assert.AreEqual("internaltypeExtName", typeExt.InternalName); } @@ -278,7 +275,6 @@ public void MappedTypeExension_SwappingOutResolvers_RemovesUnion() Assert.AreEqual(0, typeExt.Attributes.Count(x => x is UnionAttribute)); } - [Test] public void MappedTypeExension_ViaOptions_WithUnion() { @@ -290,7 +286,6 @@ public void MappedTypeExension_ViaOptions_WithUnion() Assert.IsNotNull(typeExt.Resolver); } - [Test] public void MappedTypeExension_ViaBuilder_WithUnion() { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/ResolvedFieldTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/ResolvedFieldTemplateTests.cs index 33af8e048..7c3354b32 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/ResolvedFieldTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/RuntimeFieldDeclarations/ResolvedFieldTemplateTests.cs @@ -60,7 +60,7 @@ public void ResolvedField_WhenNameApplied_NameIsAttchedToFieldDeclaration() var field = options .MapQuery("/path1/path2", (string a) => 1) - .WithName("theName"); + .WithInternalName("theName"); Assert.AreEqual("theName", field.InternalName); } @@ -83,7 +83,6 @@ public void ResolvedField_WhenRequireAuthAdded_AddsAuthAttribute() Assert.AreEqual("roles1", attrib.Roles); } - [Test] public void ResolvedField_WhenRequireAuthAdded_AllowAnonIsRemoved() { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/RuntimeControllerActionTemplateTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/RuntimeControllerActionTemplateTests.cs index 73f98e354..1f2642204 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/RuntimeControllerActionTemplateTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/RuntimeControllerActionTemplateTests.cs @@ -9,7 +9,6 @@ namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates { - using System; using System.Linq; using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Schemas; @@ -18,7 +17,6 @@ namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates using GraphQL.AspNet.Tests.Common.Interfaces; using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; - using NUnit.Framework.Constraints; [TestFixture] public class RuntimeControllerActionTemplateTests @@ -53,7 +51,7 @@ public void MapQuery_InternalNameCheck() { var options = new SchemaOptions(new ServiceCollection()); var field = options.MapQuery("fieldName", (int a) => 0) - .WithName("internalFieldName"); + .WithInternalName("internalFieldName"); var template = new RuntimeGraphControllerTemplate(field); template.Parse(); diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/RuntimeFieldsGeneralTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/RuntimeFieldsGeneralTests.cs index 7cba10b84..b3e5a925c 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/RuntimeFieldsGeneralTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/RuntimeFieldsGeneralTests.cs @@ -27,7 +27,7 @@ public void InternalName_OnQueryField_IssCarriedToSchema() .AddGraphQL(o => { o.MapQuery("field1", () => 1) - .WithName("field1_internal_name"); + .WithInternalName("field1_internal_name"); }) .Build(); @@ -43,7 +43,7 @@ public void InternalName_OnMutationField_IssCarriedToSchema() .AddGraphQL(o => { o.MapMutation("field1", () => 1) - .WithName("field1_internal_name"); + .WithInternalName("field1_internal_name"); }) .Build(); @@ -60,7 +60,7 @@ public void InternalName_OnTypeExension_IssCarriedToSchema() { o.AddType(); o.MapTypeExtension("field1", () => 1) - .WithName("extension_field_Internal_Name"); + .WithInternalName("extension_field_Internal_Name"); }) .Build(); @@ -76,7 +76,7 @@ public void InternalName_OnDirective_IsCarriedToSchema() .AddGraphQL(o => { o.MapDirective("@myDirective", () => GraphActionResult.Ok()) - .WithName("directive_internal_name"); + .WithInternalName("directive_internal_name"); }) .Build(); From fff1f812ef7b3c41bee2609ea982d014edb7431f Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Sun, 30 Jul 2023 15:16:35 -0700 Subject: [PATCH 56/63] WIP, removed global schema registration variables --- ...untimeSubscriptionsDefinitionExtensions.cs | 2 + ...tionsDefinitionExtensions_VirtualFields.cs | 1 + .../ServiceCollectionExtensions.cs | 38 ++++++++ .../GraphQLSchemaBuilderExtensions.cs | 54 ++++------- .../Startup/GraphQLSchemaInjectorFactory.cs | 73 +++++++++++++- .../Startup/GraphQLSchemaInjector{TSchema}.cs | 13 ++- .../Configuration/ConfigurationSetupTests.cs | 16 --- .../SubscriptionQueryExecutionTests.cs | 42 ++++++++ .../Schemas/RuntimeFieldGeneralTests.cs | 97 ++++++++++++++++++- .../TestServerBuilder{TSchema}.cs | 11 ++- .../Configuration/ConfigurationSetupTests.cs | 11 +-- .../Configuration/StartupTests.cs | 60 ++++++++++++ 12 files changed, 350 insertions(+), 68 deletions(-) create mode 100644 src/graphql-aspnet-subscriptions/Configuration/ServiceCollectionExtensions.cs create mode 100644 src/unit-tests/graphql-aspnet-tests/Configuration/StartupTests.cs diff --git a/src/graphql-aspnet-subscriptions/Configuration/GraphQLRuntimeSubscriptionsDefinitionExtensions.cs b/src/graphql-aspnet-subscriptions/Configuration/GraphQLRuntimeSubscriptionsDefinitionExtensions.cs index 950ed71b7..41ebe64d6 100644 --- a/src/graphql-aspnet-subscriptions/Configuration/GraphQLRuntimeSubscriptionsDefinitionExtensions.cs +++ b/src/graphql-aspnet-subscriptions/Configuration/GraphQLRuntimeSubscriptionsDefinitionExtensions.cs @@ -159,6 +159,8 @@ public static IGraphQLSubscriptionEnabledRuntimeResolvedFieldDefinition MapSubsc resolvedField.AddAttribute(new UnionAttribute(unionName.Trim())); resolvedField.AddResolver(unionName, resolverMethod); + + schemaOptions.ServiceCollection?.AddSubscriptionRuntimeFieldExecutionSupport(); return resolvedField; } diff --git a/src/graphql-aspnet-subscriptions/Configuration/GraphQLRuntimeSubscriptionsDefinitionExtensions_VirtualFields.cs b/src/graphql-aspnet-subscriptions/Configuration/GraphQLRuntimeSubscriptionsDefinitionExtensions_VirtualFields.cs index 07dfaa360..f864ea604 100644 --- a/src/graphql-aspnet-subscriptions/Configuration/GraphQLRuntimeSubscriptionsDefinitionExtensions_VirtualFields.cs +++ b/src/graphql-aspnet-subscriptions/Configuration/GraphQLRuntimeSubscriptionsDefinitionExtensions_VirtualFields.cs @@ -39,6 +39,7 @@ public static IGraphQLRuntimeFieldGroupDefinition MapSubscriptionGroup(this ISch /// IGraphQLRuntimeFieldDefinition. public static IGraphQLRuntimeFieldGroupDefinition MapSubscriptionGroup(this SchemaOptions schemaOptions, string template) { + schemaOptions?.ServiceCollection?.AddSubscriptionRuntimeFieldExecutionSupport(); return new RuntimeSubscriptionEnabledFieldGroupTemplate(schemaOptions, template); } } diff --git a/src/graphql-aspnet-subscriptions/Configuration/ServiceCollectionExtensions.cs b/src/graphql-aspnet-subscriptions/Configuration/ServiceCollectionExtensions.cs new file mode 100644 index 000000000..f9c31dc87 --- /dev/null +++ b/src/graphql-aspnet-subscriptions/Configuration/ServiceCollectionExtensions.cs @@ -0,0 +1,38 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Configuration +{ + using GraphQL.AspNet.Controllers; + using Microsoft.Extensions.DependencyInjection; + using Microsoft.Extensions.DependencyInjection.Extensions; + + /// + /// Helpful extension methods for the + /// when dealing with subscriptions. + /// + public static class ServiceCollectionExtensions + { + /// + /// Adds support for the execution of runtime subscription field declarations (e.g. minimal api + /// defined fields). + /// + /// The service collection. + /// IServiceCollection. + public static IServiceCollection AddSubscriptionRuntimeFieldExecutionSupport(this IServiceCollection serviceCollection) + { + if (serviceCollection != null) + { + serviceCollection.TryAddTransient(); + } + + return serviceCollection; + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/GraphQLSchemaBuilderExtensions.cs b/src/graphql-aspnet/Configuration/GraphQLSchemaBuilderExtensions.cs index b4064ec0f..5c1399e01 100644 --- a/src/graphql-aspnet/Configuration/GraphQLSchemaBuilderExtensions.cs +++ b/src/graphql-aspnet/Configuration/GraphQLSchemaBuilderExtensions.cs @@ -10,12 +10,10 @@ namespace GraphQL.AspNet.Configuration { using System; - using System.Collections.Generic; using GraphQL.AspNet.Common; using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Configuration.Startup; using GraphQL.AspNet.Engine; - using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Interfaces.Configuration; using GraphQL.AspNet.Interfaces.Engine; using GraphQL.AspNet.Interfaces.Schema; @@ -28,25 +26,6 @@ namespace GraphQL.AspNet.Configuration /// public static class GraphQLSchemaBuilderExtensions { - private static readonly Dictionary SCHEMA_REGISTRATIONS; - - /// - /// Initializes static members of the class. - /// - static GraphQLSchemaBuilderExtensions() - { - SCHEMA_REGISTRATIONS = new Dictionary(); - } - - /// - /// Helper method to null out the schema registration references. Useful in testing and after setup is complete there is no - /// need to keep the reference chain in tact. - /// - public static void Clear() - { - SCHEMA_REGISTRATIONS.Clear(); - } - /// /// Enables the query cache locally, in memory, to retain parsed query plans. When enabled, use the configuration /// settings for each added schema to determine how each will interact with the cache. Implement your own cache provider @@ -75,18 +54,21 @@ public static ISchemaBuilder AddGraphQL( where TSchema : class, ISchema { Validation.ThrowIfNull(serviceCollection, nameof(serviceCollection)); - if (SCHEMA_REGISTRATIONS.ContainsKey(typeof(TSchema))) + + var wasFound = GraphQLSchemaInjectorFactory.TryGetOrCreate( + out var injector, + serviceCollection, + options); + + if (wasFound) { - throw new GraphTypeDeclarationException( + throw new InvalidOperationException( $"The schema type {typeof(TSchema).FriendlyName()} has already been registered. " + "Each schema type may only be registered once with GraphQL."); } - var schemaOptions = new SchemaOptions(serviceCollection); - var injector = new GraphQLSchemaInjector(schemaOptions, options); - SCHEMA_REGISTRATIONS.Add(typeof(TSchema), injector); - injector.ConfigureServices(); + return injector.SchemaBuilder; } @@ -111,12 +93,7 @@ public static ISchemaBuilder AddGraphQL( /// The application being constructed. public static void UseGraphQL(this IApplicationBuilder app) { - foreach (var injector in SCHEMA_REGISTRATIONS.Values) - { - injector.UseSchema(app); - } - - Clear(); + UseGraphQL(app?.ApplicationServices); } /// @@ -133,12 +110,15 @@ public static void UseGraphQL(this IApplicationBuilder app) /// graphql runtime. public static void UseGraphQL(this IServiceProvider serviceProvider) { - foreach (var injector in SCHEMA_REGISTRATIONS.Values) + Validation.ThrowIfNull(serviceProvider, nameof(serviceProvider)); + var allInjectors = serviceProvider.GetServices(); + if (allInjectors != null) { - injector.UseSchema(serviceProvider); + foreach (var injector in allInjectors) + { + injector.UseSchema(serviceProvider); + } } - - Clear(); } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/Startup/GraphQLSchemaInjectorFactory.cs b/src/graphql-aspnet/Configuration/Startup/GraphQLSchemaInjectorFactory.cs index f230994c8..e4fc23977 100644 --- a/src/graphql-aspnet/Configuration/Startup/GraphQLSchemaInjectorFactory.cs +++ b/src/graphql-aspnet/Configuration/Startup/GraphQLSchemaInjectorFactory.cs @@ -10,6 +10,7 @@ namespace GraphQL.AspNet.Configuration.Startup { using System; + using System.Linq; using GraphQL.AspNet.Common; using GraphQL.AspNet.Interfaces.Configuration; using GraphQL.AspNet.Interfaces.Schema; @@ -36,11 +37,46 @@ public static ISchemaInjector Create( where TSchema : class, ISchema { Validation.ThrowIfNull(schemaOptions, nameof(schemaOptions)); - var injector = new GraphQLSchemaInjector(schemaOptions, configurationDelegate); return injector; } + /// + /// Creates a new schema injector capable of configuring the provided + /// to properly serve schema dependencies. If an injector is already registered for the target + /// schema it is returned directly. + /// + /// The type of the schema being created. + /// Will be set to the instance that was located or created. + /// A set of schema options to use when generating entity + /// templates to be injected. + /// A configuration delegate to configure + /// schema specific settings. + /// true if this instance was successfully retrieved, false is the instance + /// was newly created. + public static bool TryGetOrCreate( + out ISchemaInjector instance, + SchemaOptions schemaOptions, + Action> configurationDelegate = null) + where TSchema : class, ISchema + { + instance = null; + Validation.ThrowIfNull(schemaOptions, nameof(schemaOptions)); + + var registeredInjector = schemaOptions.ServiceCollection? + .SingleOrDefault(x => x.ImplementationInstance is ISchemaInjector)? + .ImplementationInstance as ISchemaInjector; + + if (registeredInjector != null) + { + instance = registeredInjector; + return true; + } + + instance = Create(schemaOptions, configurationDelegate); + return false; + } + /// /// Creates a new schema injector capable of configuring the provided /// to properly serve schema dependencies. @@ -61,5 +97,40 @@ public static ISchemaInjector Create( var injector = new GraphQLSchemaInjector(schemaOptions, configurationDelegate); return injector; } + + /// + /// Creates a new schema injector capable of configuring the provided + /// to properly serve schema dependencies. If the provided service collection already contains + /// a registered instance of the target injector it is returned directly. + /// + /// The type of the schema being created. + /// Will be set to the instance that was located or created. + /// The service collection to populate. + /// A configuration delegate to configure + /// schema specific settings. + /// true if this instance was successfully retrieved, false is the instance + /// was newly created. + public static bool TryGetOrCreate( + out ISchemaInjector instance, + IServiceCollection serviceCollection, + Action> configurationDelegate = null) + where TSchema : class, ISchema + { + instance = null; + Validation.ThrowIfNull(serviceCollection, nameof(serviceCollection)); + + var registeredInjector = serviceCollection + .SingleOrDefault(x => x.ImplementationInstance is ISchemaInjector)? + .ImplementationInstance as ISchemaInjector; + + if (registeredInjector != null) + { + instance = registeredInjector; + return true; + } + + instance = Create(serviceCollection, configurationDelegate); + return false; + } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Configuration/Startup/GraphQLSchemaInjector{TSchema}.cs b/src/graphql-aspnet/Configuration/Startup/GraphQLSchemaInjector{TSchema}.cs index 9ce2e30b4..98f58c135 100644 --- a/src/graphql-aspnet/Configuration/Startup/GraphQLSchemaInjector{TSchema}.cs +++ b/src/graphql-aspnet/Configuration/Startup/GraphQLSchemaInjector{TSchema}.cs @@ -17,7 +17,7 @@ namespace GraphQL.AspNet.Configuration.Startup using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Engine; - using GraphQL.AspNet.Execution; + using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Interfaces.Configuration; using GraphQL.AspNet.Interfaces.Engine; using GraphQL.AspNet.Interfaces.Execution; @@ -29,7 +29,6 @@ namespace GraphQL.AspNet.Configuration.Startup using GraphQL.AspNet.Middleware.FieldExecution; using GraphQL.AspNet.Middleware.QueryExecution; using GraphQL.AspNet.Middleware.SchemaItemSecurity; - using GraphQL.AspNet.Schemas.Generation; using GraphQL.AspNet.Web; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; @@ -86,6 +85,13 @@ public GraphQLSchemaInjector(SchemaOptions options, Action public void ConfigureServices() { + if (_options.ServiceCollection.Any(x => x.ServiceType == typeof(TSchema))) + { + throw new InvalidOperationException( + $"The schema type {typeof(TSchema).FriendlyName()} has already been registered. " + + "Each schema type may only be registered once with GraphQL."); + } + // create the builder to guide the rest of the setup operations _configureOptions?.Invoke(_options); @@ -140,6 +146,9 @@ public void ConfigureServices() _options.ServiceCollection.TryAddSingleton(CreatePipelineFactory(_schemaBuilder.QueryExecutionPipeline)); _options.ServiceCollection.TryAddSingleton(CreatePipelineFactory(_schemaBuilder.DirectiveExecutionPipeline)); + // register self for final "using" extraction + _options.ServiceCollection.AddSingleton(this); + this.RegisterEngineComponents(); _options.FinalizeServiceRegistration(); diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Configuration/ConfigurationSetupTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Configuration/ConfigurationSetupTests.cs index 39b35af29..3ff9613cc 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Configuration/ConfigurationSetupTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Configuration/ConfigurationSetupTests.cs @@ -10,9 +10,7 @@ namespace GraphQL.AspNet.Tests.Configuration { using System; - using GraphQL.AspNet; using GraphQL.AspNet.Configuration; - using GraphQL.AspNet.Engine; using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Interfaces.Subscriptions; using GraphQL.AspNet.Schemas; @@ -21,7 +19,6 @@ namespace GraphQL.AspNet.Tests.Configuration using GraphQL.AspNet.SubscriptionServer; using GraphQL.AspNet.SubscriptionServer.BackgroundServices; using GraphQL.AspNet.SubscriptionServer.Exceptions; - using GraphQL.AspNet.Tests.Framework; using GraphQL.AspNet.Tests.Configuration.ConfigurationTestData; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; @@ -36,9 +33,6 @@ public void AddSubscriptions_RegistrationChecks() { using var restorePoint = new GraphQLGlobalSubscriptionRestorePoint(); - // ensure the runtime is in a default state (just in case the statics got messed up) - GraphQLSchemaBuilderExtensions.Clear(); - var serviceCollection = new ServiceCollection(); var returned = serviceCollection.AddGraphQL(options => { @@ -59,9 +53,6 @@ public void ExplicitDeclarationOfPerFieldAuthorizationFailsServerCreation() // setup the server with a hard declaration of nothing using var restorePoint = new GraphQLGlobalSubscriptionRestorePoint(); - // ensure the runtime is in a default state (just in case the statics got messed up) - GraphQLSchemaBuilderExtensions.Clear(); - var serviceCollection = new ServiceCollection(); var schemaBuilder = serviceCollection.AddGraphQL(options => { @@ -84,8 +75,6 @@ public void ExplicitDeclarationOfPerRequestAuthorizationAddsServerSuccessfully() using var restorePoint = new GraphQLGlobalSubscriptionRestorePoint(); // ensure the runtime is in a default state (just in case the statics got messed up) - GraphQLSchemaBuilderExtensions.Clear(); - var serviceCollection = new ServiceCollection(); var returned = serviceCollection.AddGraphQL(options => { @@ -102,7 +91,6 @@ public void NonExplicitDeclarationResultsInPerRequestAndAddsServerSuccessfully() { // setup the server with a hard declaration of nothing using var restorePoint = new GraphQLGlobalSubscriptionRestorePoint(); - GraphQLSchemaBuilderExtensions.Clear(); SchemaOptions optionsSaved = null; var serviceCollection = new ServiceCollection(); @@ -122,10 +110,6 @@ public void NonExplicitDeclarationResultsInPerRequestAndAddsServerSuccessfully() public void AddSubscriptionServer_RegistrationChecks() { using var restorePoint = new GraphQLGlobalSubscriptionRestorePoint(); - - // ensure the runtime is in a default state (just in case the statics got messed up) - GraphQLSchemaBuilderExtensions.Clear(); - var serviceCollection = new ServiceCollection(); var returned = serviceCollection.AddGraphQL(options => { diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Execution/SubscriptionQueryExecutionTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Execution/SubscriptionQueryExecutionTests.cs index e52428e63..519c080e7 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Execution/SubscriptionQueryExecutionTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Execution/SubscriptionQueryExecutionTests.cs @@ -18,6 +18,9 @@ namespace GraphQL.AspNet.Tests.Execution using GraphQL.AspNet.Tests.Mocks; using NuGet.Frameworks; using NUnit.Framework; + using GraphQL.AspNet.Schemas.Structural; + using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Schemas.TypeSystem; [TestFixture] public class SubscriptionQueryExecutionTests @@ -187,5 +190,44 @@ public async Task ExecutionOfQuery_WithCompleteEventResult_AddsError() Assert.IsNull(context.Result.Data); Assert.AreEqual(Constants.ErrorCodes.INVALID_ACTION_RESULT, context.Messages[0].Code); } + + [Test] + public async Task Execution_FromMinimalApi_ExecutesAsExpected() + { + var server = new TestServerBuilder() + .AddGraphQL(o => + { + o.MapSubscription("retrieveObject", (TwoPropertyObject sourceArg) => sourceArg) + .WithEventName("RetrieveObject") + .WithInternalName("RetrieveObject"); + }) + .AddSubscriptionServer() + .Build(); + + var operation = server.Schema.Operations[GraphOperationType.Subscription]; + var field = operation.Fields.FindField("retrieveObject"); + + var sourceObject = new TwoPropertyObject() + { + Property1 = "testA", + Property2 = 5, + }; + + var builder = server.CreateQueryContextBuilder() + .AddQueryText("subscription { retrieveObject { property1 } }") + .AddDefaultValue(field.Route, sourceObject); + + var result = await server.RenderResult(builder); + var expectedOutput = + @"{ + ""data"" : { + ""retrieveObject"" : { + ""property1"" : ""testA"" + } + } + }"; + + CommonAssertions.AreEqualJsonStrings(expectedOutput, result); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/RuntimeFieldGeneralTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/RuntimeFieldGeneralTests.cs index 0fdd52416..92c629645 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/RuntimeFieldGeneralTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Schemas/RuntimeFieldGeneralTests.cs @@ -9,7 +9,10 @@ namespace GraphQL.AspNet.Tests.Schemas { + using System; using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Execution.Exceptions; + using GraphQL.AspNet.Interfaces.Schema.TypeSystem; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.Framework; @@ -22,6 +25,7 @@ public class RuntimeFieldGeneralTests [Test] public void General_SubscriptionField_IsRegistered() { + using var restorePoint = new GraphQLGlobalSubscriptionRestorePoint(); var server = new TestServerBuilder() .AddGraphQL(o => { @@ -31,9 +35,100 @@ public void General_SubscriptionField_IsRegistered() .Build(); var operation = server.Schema.Operations[GraphOperationType.Subscription]; - var field = operation.Fields.FindField("field1"); + var field = operation.Fields.FindField("field1") as ISubscriptionGraphField; Assert.IsNotNull(field); Assert.AreEqual("field1", field.Name); + Assert.AreEqual("field1", field.EventName); + } + + [Test] + public void General_SubscriptionField_WithCustomEventName_IsRegistered() + { + using var restorePoint = new GraphQLGlobalSubscriptionRestorePoint(); + var server = new TestServerBuilder() + .AddGraphQL(o => + { + o.MapSubscription("field1", (TwoPropertyObject source, int param1) => source) + .WithEventName("myEvent"); + }) + .AddSubscriptionServer() + .Build(); + + var operation = server.Schema.Operations[GraphOperationType.Subscription]; + var field = operation.Fields.FindField("field1") as ISubscriptionGraphField; + Assert.IsNotNull(field); + Assert.AreEqual("field1", field.Name); + Assert.AreEqual("myEvent", field.EventName); + } + + [Test] + public void General_SubscriptionField_WithCustomInternalName_IsRegistered() + { + using var restorePoint = new GraphQLGlobalSubscriptionRestorePoint(); + var server = new TestServerBuilder() + .AddGraphQL(o => + { + o.MapSubscription("field1", (TwoPropertyObject source, int param1) => source) + .WithInternalName("myInternalName"); + }) + .AddSubscriptionServer() + .Build(); + + var operation = server.Schema.Operations[GraphOperationType.Subscription]; + var field = operation.Fields.FindField("field1") as ISubscriptionGraphField; + Assert.IsNotNull(field); + Assert.AreEqual("field1", field.Name); + Assert.AreEqual("myInternalName", field.InternalName); + } + + [Test] + public void AddSubscriptionField_WithoutRegistereingSubscriptionServer_ThrowsException() + { + using var restorePoint = new GraphQLGlobalSubscriptionRestorePoint(); + var serverBuilder = new TestServerBuilder() + .AddGraphQL(o => + { + o.MapSubscription("field1", (TwoPropertyObject source, int param1) => source); + }); + + Assert.Throws(() => + { + serverBuilder.Build(); + }); + } + + [Test] + public void AddSubscriptionField_NoApplicableSourceObject_ThrownException() + { + using var restorePoint = new GraphQLGlobalSubscriptionRestorePoint(); + var serverBuilder = new TestServerBuilder() + .AddGraphQL(o => + { + o.MapSubscription("field1", () => 0); + }) + .AddSubscriptionServer(); + + Assert.Throws(() => + { + serverBuilder.Build(); + }); + } + + [Test] + public void AddSubscriptionField_ViaBuilder_BeforeSubscriptionServer_RendersField() + { + using var restorePoint = new GraphQLGlobalSubscriptionRestorePoint(); + var serverBuilder = new TestServerBuilder(); + + var schemaBuilder = serverBuilder.AddGraphQL(); + schemaBuilder.MapSubscription("field1", (int arg1) => 0); + schemaBuilder.AddSubscriptions(); + + var server = serverBuilder.Build(); + + var operation = server.Schema.Operations[GraphOperationType.Subscription]; + var field = operation.Fields.FindField("field1") as ISubscriptionGraphField; + Assert.IsNotNull(field); } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-testframework/TestServerBuilder{TSchema}.cs b/src/unit-tests/graphql-aspnet-testframework/TestServerBuilder{TSchema}.cs index d25d24c31..b29fcae5d 100644 --- a/src/unit-tests/graphql-aspnet-testframework/TestServerBuilder{TSchema}.cs +++ b/src/unit-tests/graphql-aspnet-testframework/TestServerBuilder{TSchema}.cs @@ -227,8 +227,15 @@ public virtual TestServer Build() // perform a schema injection to setup all the registered // graph types for the schema in the DI container - var injector = GraphQLSchemaInjectorFactory.Create(this.SchemaOptions, masterConfigMethod); - injector.ConfigureServices(); + var wasFound = GraphQLSchemaInjectorFactory.TryGetOrCreate( + out var injector, + this.SchemaOptions, + masterConfigMethod); + + if (!wasFound) + { + injector.ConfigureServices(); + } // allow the typed test components to do their thing with the // schema builder diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/ConfigurationSetupTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/ConfigurationSetupTests.cs index d63a6531e..ec820c131 100644 --- a/src/unit-tests/graphql-aspnet-tests/Configuration/ConfigurationSetupTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/ConfigurationSetupTests.cs @@ -9,6 +9,7 @@ namespace GraphQL.AspNet.Tests.Configuration { + using System; using System.Linq; using System.Reflection; using System.Threading.Tasks; @@ -16,9 +17,7 @@ namespace GraphQL.AspNet.Tests.Configuration using GraphQL.AspNet.Engine; using GraphQL.AspNet.Execution.Contexts; using GraphQL.AspNet.Execution.Exceptions; - using GraphQL.AspNet.Execution.Parsing; using GraphQL.AspNet.Interfaces.Engine; - using GraphQL.AspNet.Interfaces.Execution; using GraphQL.AspNet.Interfaces.Middleware; using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Interfaces.Web; @@ -34,12 +33,6 @@ namespace GraphQL.AspNet.Tests.Configuration [TestFixture] public class ConfigurationSetupTests { - [TearDown] - public void TearDown() - { - GraphQLSchemaBuilderExtensions.Clear(); - } - [Test] public void AddGraphQL_AddingDefaultSchema_WithOneController_GeneratesAllDefaultEngineParts() { @@ -71,7 +64,7 @@ public void AddGraphQL_AttemptingToAddDefautSchemaAsTyped_ThrowsException() var serviceCollection = new ServiceCollection(); serviceCollection.AddGraphQL(); - Assert.Throws(() => + Assert.Throws(() => { serviceCollection.AddGraphQL(); }); diff --git a/src/unit-tests/graphql-aspnet-tests/Configuration/StartupTests.cs b/src/unit-tests/graphql-aspnet-tests/Configuration/StartupTests.cs new file mode 100644 index 000000000..3d9764f6a --- /dev/null +++ b/src/unit-tests/graphql-aspnet-tests/Configuration/StartupTests.cs @@ -0,0 +1,60 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Tests.Configuration +{ + using System; + using System.Linq; + using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Interfaces.Configuration; + using GraphQL.AspNet.Schemas; + using Microsoft.Extensions.DependencyInjection; + using NUnit.Framework; + + [TestFixture] + public class StartupTests + { + public class Schema2 : GraphSchema + { + } + + [Test] + public void AttemptingToAddGraphQL_ForDifferentSchemas_isFIne() + { + var collection = new ServiceCollection(); + collection.AddGraphQL(); + collection.AddGraphQL(); + } + + [Test] + public void AttemptingToAddGraphQL_TwiceForSameSchema_ThrowsException() + { + var collection = new ServiceCollection(); + collection.AddGraphQL(); + + Assert.Throws(() => + { + collection.AddGraphQL(); + }); + } + + [Test] + public void AttemptingToAddGraphQL_ForDifferentSchemas_YieldsTwoInjectorsInPRovider() + { + var collection = new ServiceCollection(); + collection.AddGraphQL(); + collection.AddGraphQL(); + + var provider = collection.BuildServiceProvider(); + + var services = provider.GetServices(); + Assert.AreEqual(2, services.Count()); + } + } +} \ No newline at end of file From 153711ce92b9d86087a8bb8330261b988d0ed74f Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Sun, 30 Jul 2023 16:53:15 -0700 Subject: [PATCH 57/63] WIP, setup static classes for subscription action results --- .../ActionResults/SubscriptionEvents.cs | 72 +++++++++++++++++++ .../SubscriptionGraphActionResult.cs | 59 +++++++++++++++ .../Controllers/GraphControllerExtensions.cs | 44 +----------- .../ActionResults/GraphActionResult.cs | 2 - 4 files changed, 134 insertions(+), 43 deletions(-) create mode 100644 src/graphql-aspnet-subscriptions/Controllers/ActionResults/SubscriptionEvents.cs create mode 100644 src/graphql-aspnet-subscriptions/Controllers/ActionResults/SubscriptionGraphActionResult.cs diff --git a/src/graphql-aspnet-subscriptions/Controllers/ActionResults/SubscriptionEvents.cs b/src/graphql-aspnet-subscriptions/Controllers/ActionResults/SubscriptionEvents.cs new file mode 100644 index 000000000..b4937248a --- /dev/null +++ b/src/graphql-aspnet-subscriptions/Controllers/ActionResults/SubscriptionEvents.cs @@ -0,0 +1,72 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Controllers.ActionResults +{ + using System.Collections.Generic; + using GraphQL.AspNet.Common; + using GraphQL.AspNet.Common.Extensions; + using GraphQL.AspNet.Execution.Contexts; + using GraphQL.AspNet.Execution.Exceptions; + using GraphQL.AspNet.Interfaces.Controllers; + using GraphQL.AspNet.SubscriptionServer; + + /// + /// A helper class to allow the use of common methods + /// with non-controller based resolvers for subscription related results. + /// + public static class SubscriptionEvents + { + /// + /// Publishes an instance of the internal event, informing all graphql-subscriptions that + /// are subscribed to the event. If the is + /// null the event is automatically canceled. + /// + /// The resolution context of the field where the event is being published. + /// Name of the well-known event to be raised. + /// The data object to pass with the event. + public static void PublishSubscriptionEvent(this SchemaItemResolutionContext context, string eventName, object dataObject) + { + Validation.ThrowIfNull(context, nameof(context)); + Validation.ThrowIfNull(dataObject, nameof(dataObject)); + eventName = Validation.ThrowIfNullWhiteSpaceOrReturn(eventName, nameof(eventName)); + + var contextData = context.Session.Items; + + // add or reference the list of events on the active context + var eventsCollectionFound = contextData + .TryGetValue( + SubscriptionConstants.ContextDataKeys.RAISED_EVENTS_COLLECTION, + out var listObject); + + if (!eventsCollectionFound) + { + listObject = new List(1); + contextData.TryAdd( + SubscriptionConstants.ContextDataKeys.RAISED_EVENTS_COLLECTION, + listObject); + } + + var eventList = listObject as IList; + if (eventList == null) + { + throw new GraphExecutionException( + $"Unable to cast the context data item '{SubscriptionConstants.ContextDataKeys.RAISED_EVENTS_COLLECTION}' " + + $"(type: {listObject?.GetType().FriendlyName() ?? "unknown"}), into " + + $"{typeof(IList).FriendlyName()}. Event '{eventName}' could not be published.", + context.Request.Origin); + } + + lock (eventList) + { + eventList.Add(new SubscriptionEventProxy(eventName, dataObject)); + } + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet-subscriptions/Controllers/ActionResults/SubscriptionGraphActionResult.cs b/src/graphql-aspnet-subscriptions/Controllers/ActionResults/SubscriptionGraphActionResult.cs new file mode 100644 index 000000000..56866ff92 --- /dev/null +++ b/src/graphql-aspnet-subscriptions/Controllers/ActionResults/SubscriptionGraphActionResult.cs @@ -0,0 +1,59 @@ +// ************************************************************* +// project: graphql-aspnet +// -- +// repo: https://github.com/graphql-aspnet +// docs: https://graphql-aspnet.github.io +// -- +// License: MIT +// ************************************************************* + +namespace GraphQL.AspNet.Controllers.ActionResults +{ + using GraphQL.AspNet.Interfaces.Controllers; + + /// + /// A helper class to allow the use of common methods + /// with non-controller based resolvers for subscription related results. + /// + public static class SubscriptionGraphActionResult + { + /// + /// When used as an action result from subscription, indicates that the subscription should be skipped + /// and the connected client should receive NO data, as if the event never occured. + /// + /// if set to true, instructs that the + /// subscription should also be gracefully end such that no additional events + /// are processed after the event is skipped. The client may be informed of this operation if + /// supported by its negotiated protocol. + /// + /// If used as an action result for a non-subscription action (i.e. a query or mutation) a critical + /// error will be added to the response and the query will end. + /// + /// An action result indicating that all field resolution results should be skipped + /// and no data should be sent to the connected client. + public static IGraphActionResult SkipSubscriptionEvent(bool completeSubscirption = false) + { + return new SkipSubscriptionEventGraphActionResult(completeSubscirption); + } + + /// + /// When used as an action result from subscription, resolves the field with the given object + /// and indicates that to the client that the subscription should gracefully end when this event completes. + /// Once completed, the subscription will be unregsitered and no additional events will + /// be raised to this client. The client will be informed of this operation if supported + /// by its negotiated protocol. + /// + /// The object to resolve the field with. + /// + /// If used as an action result for a non-subscription action (i.e. a query or mutation) a critical + /// error will be added to the response and the query will end. + /// + /// An action result indicating a successful field resolution with the supplied + /// and additional information to instruct the subscription server to close the subscription + /// once processing is completed. + public static IGraphActionResult OkAndComplete(object item = null) + { + return new CompleteSubscriptionGraphActionResult(item); + } + } +} \ No newline at end of file diff --git a/src/graphql-aspnet-subscriptions/Controllers/GraphControllerExtensions.cs b/src/graphql-aspnet-subscriptions/Controllers/GraphControllerExtensions.cs index 7a4b0d80f..63924231a 100644 --- a/src/graphql-aspnet-subscriptions/Controllers/GraphControllerExtensions.cs +++ b/src/graphql-aspnet-subscriptions/Controllers/GraphControllerExtensions.cs @@ -9,14 +9,8 @@ namespace GraphQL.AspNet.Controllers { - using System; - using System.Collections.Generic; - using GraphQL.AspNet.Common; - using GraphQL.AspNet.Common.Extensions; using GraphQL.AspNet.Controllers.ActionResults; - using GraphQL.AspNet.Execution.Exceptions; using GraphQL.AspNet.Interfaces.Controllers; - using GraphQL.AspNet.SubscriptionServer; /// /// Extension methods to expose subscription to graph controllers. @@ -33,39 +27,7 @@ public static class GraphControllerExtensions /// The data object to pass with the event. public static void PublishSubscriptionEvent(this GraphController controller, string eventName, object dataObject) { - Validation.ThrowIfNull(dataObject, nameof(dataObject)); - eventName = Validation.ThrowIfNullWhiteSpaceOrReturn(eventName, nameof(eventName)); - - var contextData = controller.Context.Session.Items; - - // add or reference the list of events on the active context - var eventsCollectionFound = contextData - .TryGetValue( - SubscriptionConstants.ContextDataKeys.RAISED_EVENTS_COLLECTION, - out var listObject); - - if (!eventsCollectionFound) - { - listObject = new List(1); - contextData.TryAdd( - SubscriptionConstants.ContextDataKeys.RAISED_EVENTS_COLLECTION, - listObject); - } - - var eventList = listObject as IList; - if (eventList == null) - { - throw new GraphExecutionException( - $"Unable to cast the context data item '{SubscriptionConstants.ContextDataKeys.RAISED_EVENTS_COLLECTION}' " + - $"(type: {listObject?.GetType().FriendlyName() ?? "unknown"}), into " + - $"{typeof(IList).FriendlyName()}. Event '{eventName}' could not be published.", - controller.Request.Origin); - } - - lock (eventList) - { - eventList.Add(new SubscriptionEventProxy(eventName, dataObject)); - } + controller?.Context?.PublishSubscriptionEvent(eventName, dataObject); } /// @@ -85,7 +47,7 @@ public static void PublishSubscriptionEvent(this GraphController controller, str /// and no data should be sent to the connected client. public static IGraphActionResult SkipSubscriptionEvent(this GraphController controller, bool completeSubscirption = false) { - return new SkipSubscriptionEventGraphActionResult(completeSubscirption); + return SubscriptionGraphActionResult.SkipSubscriptionEvent(completeSubscirption); } /// @@ -106,7 +68,7 @@ public static IGraphActionResult SkipSubscriptionEvent(this GraphController cont /// once processing is completed. public static IGraphActionResult OkAndComplete(this GraphController controller, object item = null) { - return new CompleteSubscriptionGraphActionResult(item); + return SubscriptionGraphActionResult.OkAndComplete(item); } } } \ No newline at end of file diff --git a/src/graphql-aspnet/Controllers/ActionResults/GraphActionResult.cs b/src/graphql-aspnet/Controllers/ActionResults/GraphActionResult.cs index eb37bf6f5..6caa217fc 100644 --- a/src/graphql-aspnet/Controllers/ActionResults/GraphActionResult.cs +++ b/src/graphql-aspnet/Controllers/ActionResults/GraphActionResult.cs @@ -10,12 +10,10 @@ namespace GraphQL.AspNet.Controllers.ActionResults { using System; - using GraphQL.AspNet.Common; using GraphQL.AspNet.Controllers.ActionResults.Batching; using GraphQL.AspNet.Execution; using GraphQL.AspNet.Interfaces.Controllers; using GraphQL.AspNet.Interfaces.Execution; - using GraphQL.AspNet.Interfaces.Schema; /// /// A helper class to allow the use of common methods From 3fb12dcef053f01b36d5b096623212371027d4ea Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Wed, 2 Aug 2023 17:21:19 -0700 Subject: [PATCH 58/63] WIP, more tests for subscriptions --- .../Controllers/GraphControllerBase.cs | 2 +- .../Controllers/ControllerExtensionTests.cs | 43 ++++++++++ .../SubscriptionQueryExecutionTests.cs | 43 ++++++++++ .../Integration/EventPublishingTests.cs | 24 ------ .../GqltwsClientProxyTests.cs | 78 +++++++++++++++++++ .../FieldContextBuilder.cs | 7 +- .../TestServer.cs | 55 +++++++++---- .../Execution/RuntimeFieldTests.cs | 29 +++++++ .../ControllerWithInheritedAction.cs | 1 - 9 files changed, 240 insertions(+), 42 deletions(-) delete mode 100644 src/unit-tests/graphql-aspnet-subscriptions-tests/Integration/EventPublishingTests.cs diff --git a/src/graphql-aspnet/Controllers/GraphControllerBase.cs b/src/graphql-aspnet/Controllers/GraphControllerBase.cs index 21998098a..c988d6297 100644 --- a/src/graphql-aspnet/Controllers/GraphControllerBase.cs +++ b/src/graphql-aspnet/Controllers/GraphControllerBase.cs @@ -1,4 +1,4 @@ -// ************************************************************* +// ************************************************************* // project: graphql-aspnet // -- // repo: https://github.com/graphql-aspnet diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Controllers/ControllerExtensionTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Controllers/ControllerExtensionTests.cs index 4b4d3a42c..29eba98ed 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Controllers/ControllerExtensionTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Controllers/ControllerExtensionTests.cs @@ -20,6 +20,9 @@ namespace GraphQL.AspNet.Tests.Controllers using GraphQL.AspNet.Tests.Framework; using GraphQL.AspNet.Tests.Controllers.ControllerTestData; using NUnit.Framework; + using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Execution.Contexts; + using GraphQL.AspNet.Controllers; [TestFixture] public class ControllerExtensionTests @@ -161,5 +164,45 @@ public void PublishSubEvent_NoEventNameFailsTheResolver_BubblesExceptionUp() var result = await controller.InvokeActionAsync(fieldContextBuilder.ResolverMetaData.Object, resolutionContext); }); } + + [Test] + public async Task PublishSubEvent_OnRuntimeFIeld_ExistingEventCollectionisAppendedTo() + { + var server = new TestServerBuilder(TestOptions.UseCodeDeclaredNames) + .AddGraphQL((o) => + { + o.MapMutation("field1") + .WithInternalName("Mutation1") + .AddPossibleTypes(typeof(string)) + .AddResolver( + (FieldResolutionContext context, string arg1) => + { + SubscriptionEvents.PublishSubscriptionEvent(context, "event1", new TwoPropertyObject() + { + Property1 = arg1, + }); + return GraphActionResult.Ok("data result"); + }); + }) + .Build(); + + var fieldContextBuilder = server.CreateFieldContextBuilder("Mutation1"); + + var arg1Value = "random string"; + fieldContextBuilder.AddInputArgument("arg1", arg1Value); + + var resolutionContext = fieldContextBuilder.CreateResolutionContext(); + var eventCollection = new List(); + resolutionContext.Session.Items.TryAdd(SubscriptionConstants.ContextDataKeys.RAISED_EVENTS_COLLECTION, eventCollection); + + var controller = new RuntimeFieldExecutionController(); + var result = await controller.InvokeActionAsync(fieldContextBuilder.ResolverMetaData.Object, resolutionContext); + + // ensure the method executed completely + Assert.IsNotNull(result); + Assert.IsTrue(result is OperationCompleteGraphActionResult); + + Assert.AreEqual(1, eventCollection.Count); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Execution/SubscriptionQueryExecutionTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Execution/SubscriptionQueryExecutionTests.cs index 519c080e7..3d46cabad 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Execution/SubscriptionQueryExecutionTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/Execution/SubscriptionQueryExecutionTests.cs @@ -229,5 +229,48 @@ public async Task Execution_FromMinimalApi_ExecutesAsExpected() CommonAssertions.AreEqualJsonStrings(expectedOutput, result); } + + [Test] + public async Task Execution_FromMinimalApi_AgainstAsyncResolver_ExecutesAsExpected() + { + var server = new TestServerBuilder() + .AddGraphQL(o => + { + o.MapSubscription("retrieveObject", async (TwoPropertyObject sourceArg) => + { + await Task.Yield(); + return sourceArg; + }) + .WithEventName("RetrieveObject") + .WithInternalName("RetrieveObject"); + }) + .AddSubscriptionServer() + .Build(); + + var operation = server.Schema.Operations[GraphOperationType.Subscription]; + var field = operation.Fields.FindField("retrieveObject"); + + var sourceObject = new TwoPropertyObject() + { + Property1 = "testA", + Property2 = 5, + }; + + var builder = server.CreateQueryContextBuilder() + .AddQueryText("subscription { retrieveObject { property1 } }") + .AddDefaultValue(field.Route, sourceObject); + + var result = await server.RenderResult(builder); + var expectedOutput = + @"{ + ""data"" : { + ""retrieveObject"" : { + ""property1"" : ""testA"" + } + } + }"; + + CommonAssertions.AreEqualJsonStrings(expectedOutput, result); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/Integration/EventPublishingTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/Integration/EventPublishingTests.cs deleted file mode 100644 index 68073473e..000000000 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/Integration/EventPublishingTests.cs +++ /dev/null @@ -1,24 +0,0 @@ -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - -namespace GraphQL.AspNet.Tests.Integration -{ - using System.Threading.Tasks; - using NUnit.Framework; - - [TestFixture] - public class EventPublishingTests - { - [Test] - public Task EventPublishedToServer_IsTransmittedToListeningClient() - { - return Task.CompletedTask; - } - } -} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlTransportWs/GqltwsClientProxyTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlTransportWs/GqltwsClientProxyTests.cs index 9fb6e0a09..7f99ac53e 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlTransportWs/GqltwsClientProxyTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionServer/Protocols/GraphqlTransportWs/GqltwsClientProxyTests.cs @@ -746,5 +746,83 @@ public async Task Deserialize_InvalidMessage_ProcessesUnknownMessage() connection.AssertServerClosedConnection((ConnectionCloseStatus)GqltwsConstants.CustomCloseEventIds.InvalidMessageType); graphqlWsClient.Dispose(); } + + [Test] + public async Task ReceiveEvent_OnStartedSubscription_AgainstMinimalApiSubscription_YieldsNEXTMessage() + { + using var restorePoint = new GraphQLGlobalSubscriptionRestorePoint(); + + var server = new TestServerBuilder() + .AddGraphQL(o => + { + o.MapSubscription("watchForPropObject") + .WithEventName("watchForPropObject") + .AddResolver(async (TwoPropertyObject obj) => + { + await Task.Yield(); + return obj; + }); + }) + .AddSubscriptionServer((options) => + { + options.ConnectionKeepAliveInterval = TimeSpan.FromMinutes(15); + options.AuthenticatedRequestsOnly = false; + }) + .Build(); + + var router = new Mock(); + + var connection = server.CreateClientConnection(GqltwsConstants.PROTOCOL_NAME); + var serverOptions = server.ServiceProvider.GetRequiredService>(); + + var subClient = new GqltwsClientProxy( + connection, + server.Schema, + router.Object, + server.ServiceProvider.GetService>()); + + var startMessage = new GqltwsClientSubscribeMessage() + { + Id = "abc", + Payload = new GraphQueryData() + { + Query = "subscription { watchForPropObject { property1 } } ", + }, + }; + + await connection.OpenAsync(GqltwsConstants.PROTOCOL_NAME); + await subClient.ProcessMessageAsync(startMessage); + + // mimic new data for the registered subscription being processed by some + // other mutation + var evt = new SubscriptionEvent() + { + Id = Guid.NewGuid().ToString(), + DataTypeName = typeof(TwoPropertyObject).Name, + Data = new TwoPropertyObject() + { + Property1 = "value1", + Property2 = 33, + }, + EventName = "watchForPropObject", + SchemaTypeName = new GraphSchema().FullyQualifiedSchemaTypeName(), + }; + + await subClient.ReceiveEventAsync(evt); + + // the connection should receive a data package + connection.AssertGqltwsResponse( + GqltwsMessageType.NEXT, + "abc", + @"{ + ""data"" : { + ""watchForPropObject"" : { + ""property1"" : ""value1"", + } + } + }"); + + subClient.Dispose(); + } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/FieldContextBuilder.cs b/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/FieldContextBuilder.cs index f27306bcc..7ba421eaf 100644 --- a/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/FieldContextBuilder.cs +++ b/src/unit-tests/graphql-aspnet-testframework/PipelineContextBuilders/FieldContextBuilder.cs @@ -112,6 +112,7 @@ public FieldContextBuilder( _mockResolverMetaData.Setup(x => x.InternalName).Returns(resolverMetadata.InternalName); _mockResolverMetaData.Setup(x => x.InternalName).Returns(resolverMetadata.InternalName); _mockResolverMetaData.Setup(x => x.Parameters).Returns(resolverMetadata.Parameters); + _mockResolverMetaData.Setup(x => x.DefinitionSource).Returns(resolverMetadata.DefinitionSource); } /// @@ -144,7 +145,7 @@ public FieldContextBuilder AddOrigin(SourceOrigin origin) /// /// Adds a value for a given input argument to this field. It is assumed the value will cast correctly. /// - /// Name of the input field, as declared in the schema, on the field being mocked. + /// Name of the argument, as declared in the schema, on the field. /// A fully resolved value to use. /// MockFieldRequest. public FieldContextBuilder AddInputArgument(string argumentName, object value) @@ -157,9 +158,9 @@ public FieldContextBuilder AddInputArgument(string argumentName, object value) } /// - /// Alters the security context to be different than that provided by the server that created this builder. + /// Alters the security context to be different than that provided by the test server that created this builder. /// - /// The security context. + /// The user security context. /// MockFieldRequest. public FieldContextBuilder AddSecurityContext(IUserSecurityContext securityContext) { diff --git a/src/unit-tests/graphql-aspnet-testframework/TestServer.cs b/src/unit-tests/graphql-aspnet-testframework/TestServer.cs index 9688f1cab..de04582c9 100644 --- a/src/unit-tests/graphql-aspnet-testframework/TestServer.cs +++ b/src/unit-tests/graphql-aspnet-testframework/TestServer.cs @@ -11,7 +11,6 @@ namespace GraphQL.AspNet.Tests.Framework { using System; using System.IO; - using System.Linq; using System.Text.Encodings.Web; using System.Text.Json; using System.Threading; @@ -21,31 +20,21 @@ namespace GraphQL.AspNet.Tests.Framework using GraphQL.AspNet.Controllers; using GraphQL.AspNet.Directives; using GraphQL.AspNet.Engine; - using GraphQL.AspNet.Execution; using GraphQL.AspNet.Execution.Contexts; - using GraphQL.AspNet.Execution.FieldResolution; - using GraphQL.AspNet.Execution.QueryPlans.InputArguments; using GraphQL.AspNet.Execution.Response; using GraphQL.AspNet.Execution.Source; - using GraphQL.AspNet.Execution.Variables; using GraphQL.AspNet.Interfaces.Engine; using GraphQL.AspNet.Interfaces.Execution; using GraphQL.AspNet.Interfaces.Execution.QueryPlans.DocumentParts; - using GraphQL.AspNet.Interfaces.Execution.QueryPlans.InputArguments; - using GraphQL.AspNet.Interfaces.Internal; - using GraphQL.AspNet.Interfaces.Logging; using GraphQL.AspNet.Interfaces.Middleware; using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Interfaces.Security; using GraphQL.AspNet.Interfaces.Web; - using GraphQL.AspNet.Schemas; - using GraphQL.AspNet.Schemas.Generation; using GraphQL.AspNet.Schemas.Generation.TypeMakers; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Tests.Framework.PipelineContextBuilders; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; - using Moq; /// /// A mocked server instance built for a given schema and with a service provider (such as would exist at runtime) @@ -225,12 +214,41 @@ public virtual FieldContextBuilder CreateActionMethodFieldContextBuilderName of the field as it appears in the graph or the name of the action, method or property /// as it appears on the . This parameter is case sensitive. /// (optional) A source data object to supply to the builder. - /// FieldContextBuilder. + /// A builder that can be invoked against a controller to resolve a field. public virtual FieldContextBuilder CreateFieldContextBuilder(string fieldOrActionName, object sourceData = null) { return this.CreateFieldContextBuilder(typeof(TEntity), fieldOrActionName, sourceData); } + /// + /// Attempts to search the schema for a field with the given internal name. If more than one field + /// with the same name is found, the first instance is used. A context builder is then created + /// for the found field. + /// + /// The internal name assigned to the fild. + /// The source data. + /// A builder that can be invoked against a controller to resolve a field. + public virtual FieldContextBuilder CreateFieldContextBuilder(string internalName, object sourceData = null) + { + IGraphField field = null; + foreach (var f in this.Schema.AllSchemaItems()) + { + if (f is IGraphField gf && gf.InternalName == internalName) + { + field = gf; + break; + } + } + + if (field == null) + { + throw new InvalidOperationException($"A field with the internal name of '{internalName}' was not found. " + + $"Internal names for fields are case sensitive."); + } + + return this.CreateFieldContextBuilder(field, sourceData); + } + /// /// Creates a builder targeting the field owned the the combination entity and field, method or property name. /// @@ -239,7 +257,7 @@ public virtual FieldContextBuilder CreateFieldContextBuilder(string fie /// Name of the field as it appears in the graph or the name of the action, method or property /// as it appears on the . This parameter is case sensitive. /// (optional) A source data object to supply to the builder. - /// FieldContextBuilder. + /// A builder that can be invoked against a controller to resolve a field. public virtual FieldContextBuilder CreateFieldContextBuilder(Type entityType, string fieldOrActionName, object sourceData = null) { Validation.ThrowIfNull(entityType, nameof(entityType)); @@ -296,6 +314,17 @@ public virtual FieldContextBuilder CreateFieldContextBuilder(Type entityType, st $"Field names are case sensitive."); } + return this.CreateFieldContextBuilder(field, sourceData); + } + + /// + /// Creates a builder targeting the supplied field. + /// + /// The field to create a context builder for. + /// (optional) A source data object to supply to the builder. + /// A builder that can be invoked against a controller to resolve a field. + public FieldContextBuilder CreateFieldContextBuilder(IGraphField field, object sourceData = null) + { var metaData = field.Resolver.MetaData; var builder = new FieldContextBuilder( this.ServiceProvider, diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeFieldTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeFieldTests.cs index 0af778e90..9764e0e52 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeFieldTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/RuntimeFieldTests.cs @@ -60,6 +60,35 @@ public async Task BasicMappedQuery_ExecutesMethod() result); } + [Test] + public async Task BasicMappedQuery_AsAsyncMethod_ExecutesMethod() + { + var serverBuilder = new TestServerBuilder() + .AddGraphQL(o => + { + o.MapQuery("/field1/field2", async (int a, int b) => + { + await Task.Yield(); + return a + b; + }); + }); + + var server = serverBuilder.Build(); + var builder = server.CreateQueryContextBuilder(); + builder.AddQueryText(@"query { field1 { field2(a: 5, b: 33 } } }"); + + var result = await server.RenderResult(builder); + CommonAssertions.AreEqualJsonStrings( + @"{ + ""data"": { + ""field1"": { + ""field2"" : 38 + } + } + }", + result); + } + [Test] public async Task BasicMappedQuery_AddingResolverAfter_ExecutesMethod() { diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/ControllerWithInheritedAction.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/ControllerWithInheritedAction.cs index e494d8663..a784cb405 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/ControllerWithInheritedAction.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/ControllerWithInheritedAction.cs @@ -7,7 +7,6 @@ // License: MIT // ************************************************************* - namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeTemplates.ControllerTestData { using GraphQL.AspNet.Attributes; From d67f2f62c20c601e1276a0e570a84b449ad9cced Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Fri, 4 Aug 2023 15:30:22 -0700 Subject: [PATCH 59/63] WIP --- ...SubscriptionEnabledGraphQLSchemaFactory.cs | 9 +- ...bscriptionEnabledGraphTypeMakerFactory.cs} | 20 +++-- .../SubscriptionPublisherSchemaExtension.cs | 20 +---- .../SubscriptionReceiverSchemaExtension.cs | 23 ++--- .../Startup/GraphQLSchemaInjector{TSchema}.cs | 1 - .../Engine/DefaultGraphQLSchemaFactory.cs | 28 +++--- .../Engine/IGraphQLTypeMakerFactory.cs | 73 --------------- .../IGraphQLTypeMakerFactory{TSchema}.cs | 23 ----- .../TypeMakers/GraphTypeMakerFactory.cs} | 90 +++++++++++-------- .../SubscriptionReceiverExtensionTests.cs | 3 +- .../TestServer.cs | 12 ++- .../CommonHelpers/TestServerExtensions.cs | 35 -------- .../Engine/DefaultSchemaFactoryTests.cs | 2 - .../DirectiveProcessorTypeSystemTests.cs | 1 - .../TypeMakers/DirectiveTypeMakerTests.cs | 2 - .../TypeMakers/ObjectGraphTypeMakerTests.cs | 6 +- 16 files changed, 109 insertions(+), 239 deletions(-) rename src/graphql-aspnet-subscriptions/{Engine/SubscriptionEnabledGraphQLTypeMakerFactory.cs => Schemas/TypeMakers/SubscriptionEnabledGraphTypeMakerFactory.cs} (67%) delete mode 100644 src/graphql-aspnet/Interfaces/Engine/IGraphQLTypeMakerFactory.cs delete mode 100644 src/graphql-aspnet/Interfaces/Engine/IGraphQLTypeMakerFactory{TSchema}.cs rename src/graphql-aspnet/{Engine/DefaultGraphQLTypeMakerFactory.cs => Schemas/Generation/TypeMakers/GraphTypeMakerFactory.cs} (52%) delete mode 100644 src/unit-tests/graphql-aspnet-tests/CommonHelpers/TestServerExtensions.cs diff --git a/src/graphql-aspnet-subscriptions/Engine/SubscriptionEnabledGraphQLSchemaFactory.cs b/src/graphql-aspnet-subscriptions/Engine/SubscriptionEnabledGraphQLSchemaFactory.cs index c39c31ee1..184172912 100644 --- a/src/graphql-aspnet-subscriptions/Engine/SubscriptionEnabledGraphQLSchemaFactory.cs +++ b/src/graphql-aspnet-subscriptions/Engine/SubscriptionEnabledGraphQLSchemaFactory.cs @@ -12,8 +12,9 @@ namespace GraphQL.AspNet.Engine using GraphQL.AspNet.Common; using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; + using GraphQL.AspNet.Schemas.Generation.TypeMakers; using GraphQL.AspNet.Schemas.Generation.TypeTemplates; - using GraphQL.AspNet.Schemas.TypeSystem; + using GraphQL.AspNet.Schemas.TypeMakers; /// /// A schema creation factory that understands and can generate subscription types. @@ -22,6 +23,12 @@ namespace GraphQL.AspNet.Engine public class SubscriptionEnabledGraphQLSchemaFactory : DefaultGraphQLSchemaFactory where TSchema : class, ISchema { + /// + protected override GraphTypeMakerFactory CreateMakerFactory() + { + return new SubscriptionEnabledGraphTypeMakerFactory(this.Schema); + } + /// protected override void AddRuntimeFieldDefinition(IGraphQLRuntimeResolvedFieldDefinition fieldDefinition) { diff --git a/src/graphql-aspnet-subscriptions/Engine/SubscriptionEnabledGraphQLTypeMakerFactory.cs b/src/graphql-aspnet-subscriptions/Schemas/TypeMakers/SubscriptionEnabledGraphTypeMakerFactory.cs similarity index 67% rename from src/graphql-aspnet-subscriptions/Engine/SubscriptionEnabledGraphQLTypeMakerFactory.cs rename to src/graphql-aspnet-subscriptions/Schemas/TypeMakers/SubscriptionEnabledGraphTypeMakerFactory.cs index 3abffd1d3..61df8b054 100644 --- a/src/graphql-aspnet-subscriptions/Engine/SubscriptionEnabledGraphQLTypeMakerFactory.cs +++ b/src/graphql-aspnet-subscriptions/Schemas/TypeMakers/SubscriptionEnabledGraphTypeMakerFactory.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Engine +namespace GraphQL.AspNet.Schemas.TypeMakers { using System; using GraphQL.AspNet.Common; @@ -15,23 +15,27 @@ namespace GraphQL.AspNet.Engine using GraphQL.AspNet.Interfaces.Engine; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; + using GraphQL.AspNet.Schemas.Generation.TypeMakers; using GraphQL.AspNet.Schemas.Generation.TypeTemplates; - using GraphQL.AspNet.Schemas.TypeMakers; using GraphQL.AspNet.Schemas.TypeSystem; /// /// An upgraded "type maker" factory that adds low level subscription field support /// to the type system. /// - /// The type of the schema this maker factory is registered to handle. - public class SubscriptionEnabledGraphQLTypeMakerFactory : DefaultGraphQLTypeMakerFactory - where TSchema : class, ISchema + public class SubscriptionEnabledGraphTypeMakerFactory : GraphTypeMakerFactory { + private readonly ISchema _schemaInstance; + /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - public SubscriptionEnabledGraphQLTypeMakerFactory() + /// The schema instance to reference when making + /// types. + public SubscriptionEnabledGraphTypeMakerFactory(ISchema schemaInstance) + : base(schemaInstance) { + _schemaInstance = Validation.ThrowIfNullOrReturn(schemaInstance, nameof(schemaInstance)); } /// @@ -51,7 +55,7 @@ public override IGraphTypeTemplate MakeTemplate(Type objectType, TypeKind? kind /// public override IGraphFieldMaker CreateFieldMaker() { - return new SubscriptionEnabledGraphFieldMaker(this.Schema, this.CreateArgumentMaker()); + return new SubscriptionEnabledGraphFieldMaker(_schemaInstance, this.CreateArgumentMaker()); } } } \ No newline at end of file diff --git a/src/graphql-aspnet-subscriptions/SubscriptionServer/SubscriptionPublisherSchemaExtension.cs b/src/graphql-aspnet-subscriptions/SubscriptionServer/SubscriptionPublisherSchemaExtension.cs index 706039016..6cfb7236d 100644 --- a/src/graphql-aspnet-subscriptions/SubscriptionServer/SubscriptionPublisherSchemaExtension.cs +++ b/src/graphql-aspnet-subscriptions/SubscriptionServer/SubscriptionPublisherSchemaExtension.cs @@ -54,24 +54,8 @@ public void Configure(SchemaOptions options) // support for the subscription action type // swap out the master templating provider for the schema to one that includes - // support for the subscription action type if and only if the developer has not - // already registered their own custom one - var existing = options.ServiceCollection.FirstOrDefault(x => x.ServiceType == typeof(IGraphQLTypeMakerFactory)); - if (existing != null) - { - options - .ServiceCollection - .RemoveAll(typeof(IGraphQLTypeMakerFactory)); - } - - options - .ServiceCollection - .TryAdd( - new ServiceDescriptor( - typeof(IGraphQLTypeMakerFactory), - typeof(SubscriptionEnabledGraphQLTypeMakerFactory), - ServiceLifetime.Transient)); - } + // support for the subscription action type + } /// /// Invokes this instance to perform any final setup requirements as part of diff --git a/src/graphql-aspnet-subscriptions/SubscriptionServer/SubscriptionReceiverSchemaExtension.cs b/src/graphql-aspnet-subscriptions/SubscriptionServer/SubscriptionReceiverSchemaExtension.cs index a340fda73..bdefe3bee 100644 --- a/src/graphql-aspnet-subscriptions/SubscriptionServer/SubscriptionReceiverSchemaExtension.cs +++ b/src/graphql-aspnet-subscriptions/SubscriptionServer/SubscriptionReceiverSchemaExtension.cs @@ -92,26 +92,13 @@ public void Configure(SchemaOptions options) $"authorization method. (Current authorization method is \"{_schemaBuilder.Options.AuthorizationOptions.Method}\")"); } - // swap out the master templating provider for the schema to one that includes - // support for the subscription action type if and only if the developer has not - // already registered their own custom one - var existingTypeMakers = _schemaBuilder.Options.ServiceCollection.FirstOrDefault(x => x.ServiceType == typeof(IGraphQLTypeMakerFactory)); - if (existingTypeMakers != null) - { - _schemaBuilder.Options - .ServiceCollection - .RemoveAll(typeof(IGraphQLTypeMakerFactory)); - } - - _schemaBuilder.Options + // swap out the master schema factory to one that includes + // support for the subscription action type + var existingFactories = _schemaBuilder + .Options .ServiceCollection - .TryAdd( - new ServiceDescriptor( - typeof(IGraphQLTypeMakerFactory), - typeof(SubscriptionEnabledGraphQLTypeMakerFactory), - ServiceLifetime.Transient)); + .FirstOrDefault(x => x.ServiceType == typeof(IGraphQLSchemaFactory)); - var existingFactories = _schemaBuilder.Options.ServiceCollection.FirstOrDefault(x => x.ServiceType == typeof(IGraphQLSchemaFactory)); if (existingFactories != null) { _schemaBuilder.Options diff --git a/src/graphql-aspnet/Configuration/Startup/GraphQLSchemaInjector{TSchema}.cs b/src/graphql-aspnet/Configuration/Startup/GraphQLSchemaInjector{TSchema}.cs index 98f58c135..0c71df359 100644 --- a/src/graphql-aspnet/Configuration/Startup/GraphQLSchemaInjector{TSchema}.cs +++ b/src/graphql-aspnet/Configuration/Startup/GraphQLSchemaInjector{TSchema}.cs @@ -171,7 +171,6 @@ private void RegisterEngineComponents() // "per request per schema" components _options.ServiceCollection.TryAddTransient(typeof(IGraphQLHttpProcessor), _options.QueryHandler.HttpProcessorType); _options.ServiceCollection.TryAddTransient, DefaultGraphQLSchemaFactory>(); - _options.ServiceCollection.TryAddTransient, DefaultGraphQLTypeMakerFactory>(); // "per application server" instance _options.ServiceCollection.TryAddScoped(sp => sp?.GetService()); diff --git a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory.cs b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory.cs index 42ad498ae..0be37837e 100644 --- a/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory.cs +++ b/src/graphql-aspnet/Engine/DefaultGraphQLSchemaFactory.cs @@ -19,10 +19,9 @@ namespace GraphQL.AspNet.Engine using GraphQL.AspNet.Interfaces.Engine; using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Interfaces.Schema.RuntimeDefinitions; - using GraphQL.AspNet.Schemas.Generation; + using GraphQL.AspNet.Schemas.Generation.TypeMakers; using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.TypeSystem; - using GraphQL.AspNet.Schemas.TypeSystem.Scalars; using Microsoft.Extensions.DependencyInjection; /// @@ -37,7 +36,7 @@ public partial class DefaultGraphQLSchemaFactory : IGraphQLSchemaFactor /// Initializes a new instance of the class. /// public DefaultGraphQLSchemaFactory() - : this(true, true, null) + : this(true, true) { } @@ -49,16 +48,12 @@ public DefaultGraphQLSchemaFactory() /// created schema instance. /// if set to true any discovered /// type system directives will be applied to their target schema items. - /// A type factory instance to use. When null, one will attempt to be created - /// from the schema's service scope. public DefaultGraphQLSchemaFactory( bool includeBuiltInDirectives = true, - bool processTypeSystemDirectives = true, - IGraphQLTypeMakerFactory factory = null) + bool processTypeSystemDirectives = true) { this.IncludeBuiltInDirectives = includeBuiltInDirectives; this.ProcessTypeSystemDirectives = processTypeSystemDirectives; - this.MakerFactory = factory; } /// @@ -84,10 +79,7 @@ public virtual TSchema CreateInstance( return this.Schema; this.Schema.Configuration.Merge(configuration); - if (this.MakerFactory == null) - this.MakerFactory = this.ServiceProvider.GetRequiredService>(); - - this.MakerFactory.Initialize(this.Schema); + this.MakerFactory = this.CreateMakerFactory(); // Step 1: Ensure all the bare bones requirements are set // -------------------------------------- @@ -154,6 +146,16 @@ public virtual TSchema CreateInstance( return this.Schema; } + /// + /// Creates a new maker factory that will supply templates and graph type + /// makers during the schema generation process. + /// + /// DefaultGraphQLTypeMakerFactory. + protected virtual GraphTypeMakerFactory CreateMakerFactory() + { + return new GraphTypeMakerFactory(this.Schema); + } + /// /// Ensures the target schema has all the "specification required" pieces and dependencies /// accounted for. @@ -212,7 +214,7 @@ protected virtual void EnsureBaseLineDependencies() /// makers to generate graph types for the building . /// /// The maker factory to use in this instance. - protected virtual IGraphQLTypeMakerFactory MakerFactory { get; set; } + protected virtual GraphTypeMakerFactory MakerFactory { get; set; } /// /// Gets a value indicating whether the specification-defined, built-in directives (e.g. skip, include etc.) diff --git a/src/graphql-aspnet/Interfaces/Engine/IGraphQLTypeMakerFactory.cs b/src/graphql-aspnet/Interfaces/Engine/IGraphQLTypeMakerFactory.cs deleted file mode 100644 index b85ddf261..000000000 --- a/src/graphql-aspnet/Interfaces/Engine/IGraphQLTypeMakerFactory.cs +++ /dev/null @@ -1,73 +0,0 @@ -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - -namespace GraphQL.AspNet.Interfaces.Engine -{ - using System; - using GraphQL.AspNet.Interfaces.Internal; - using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Schemas.TypeSystem; - - /// - /// A factory used during schema generation to create templates and makers for creating - /// instances used to populate a schema. - /// - public interface IGraphQLTypeMakerFactory - { - /// - /// Initializes the maker for the given schema instance providing necessary contextual information - /// for any makers created by this factory. Not all implementers may use the provided schema. - /// - /// The schema instance to initialize for. - void Initialize(ISchema schemaInstance); - - /// - /// Creates a new template from the given type. This template is consumed during type generation. - /// - /// Type of the object to templatize. - /// The typekind of template to be created. If the kind can be - /// determined from the alone, this value is ignored. Largely used to seperate - /// an OBJECT template from an INPUT_OBJECT template for the same .NET type. - /// IGraphTypeTemplate. - IGraphTypeTemplate MakeTemplate(Type objectType, TypeKind? kind = null); - - /// - /// Parses the provided type, extracting the metadata used in type generation for the object graph. - /// - /// The type of the object to inspect and determine a valid type maker. - /// The graph to create a template for. If not supplied the template provider - /// will attempt to assign the best graph type possible for the supplied . - /// IGraphTypeTemplate. - IGraphTypeMaker CreateTypeMaker(Type objectType = null, TypeKind? kind = null); - - /// - /// Creates a maker that can generate valid graph fields - /// - /// IGraphFieldMaker. - IGraphFieldMaker CreateFieldMaker(); - - /// - /// Creates a maker that can generate arguments for fields or directives. - /// - /// IGraphArgumentMaker. - IGraphArgumentMaker CreateArgumentMaker(); - - /// - /// Creates a maker that can generate special union graph types. - /// - /// IUnionGraphTypeMaker. - IUnionGraphTypeMaker CreateUnionMaker(); - - /// - /// Gets the schema this factory works against. - /// - /// The schema. - ISchema Schema { get; } - } -} \ No newline at end of file diff --git a/src/graphql-aspnet/Interfaces/Engine/IGraphQLTypeMakerFactory{TSchema}.cs b/src/graphql-aspnet/Interfaces/Engine/IGraphQLTypeMakerFactory{TSchema}.cs deleted file mode 100644 index f0085f553..000000000 --- a/src/graphql-aspnet/Interfaces/Engine/IGraphQLTypeMakerFactory{TSchema}.cs +++ /dev/null @@ -1,23 +0,0 @@ -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - -namespace GraphQL.AspNet.Interfaces.Engine -{ - using GraphQL.AspNet.Interfaces.Schema; - - /// - /// A factory used during schema generation to create templates and makers for creating - /// instances used to populate a schema. - /// - /// The type of the schema this maker factory is registered to . - public interface IGraphQLTypeMakerFactory : IGraphQLTypeMakerFactory - where TSchema : class, ISchema - { - } -} \ No newline at end of file diff --git a/src/graphql-aspnet/Engine/DefaultGraphQLTypeMakerFactory.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphTypeMakerFactory.cs similarity index 52% rename from src/graphql-aspnet/Engine/DefaultGraphQLTypeMakerFactory.cs rename to src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphTypeMakerFactory.cs index 871263bdf..63934debf 100644 --- a/src/graphql-aspnet/Engine/DefaultGraphQLTypeMakerFactory.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/GraphTypeMakerFactory.cs @@ -7,7 +7,7 @@ // License: MIT // ************************************************************* -namespace GraphQL.AspNet.Engine +namespace GraphQL.AspNet.Schemas.Generation.TypeMakers { using System; using GraphQL.AspNet.Common; @@ -16,7 +16,6 @@ namespace GraphQL.AspNet.Engine using GraphQL.AspNet.Interfaces.Engine; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Schemas.Generation.TypeMakers; using GraphQL.AspNet.Schemas.Generation.TypeTemplates; using GraphQL.AspNet.Schemas.TypeSystem; @@ -24,17 +23,42 @@ namespace GraphQL.AspNet.Engine /// An object used during schema generation to organize and expose the various /// template objects to the schema. /// - /// The type of the schema this maker factory is registered to handle. - public class DefaultGraphQLTypeMakerFactory : IGraphQLTypeMakerFactory - where TSchema : class, ISchema + public class GraphTypeMakerFactory { - /// + private ISchema _schemaInstance; + + /// + /// Initializes a new instance of the class. + /// + /// The schema instance to reference when making + /// types. + public GraphTypeMakerFactory(ISchema schemaInstance) + { + Validation.ThrowIfNull(schemaInstance, nameof(schemaInstance)); + + _schemaInstance = schemaInstance; + } + + /// + /// Creates a new template from the given type. This template is consumed during type generation. + /// + /// Type of the object to templatize. + /// The typekind of template to be created. If the kind can be + /// determined from the alone, this value is ignored. Largely used to seperate + /// an OBJECT template from an INPUT_OBJECT template for the same .NET type. + /// IGraphTypeTemplate. public virtual IGraphTypeTemplate MakeTemplate(Type objectType, TypeKind? kind = null) { return GraphTypeTemplates.CreateTemplate(objectType, kind); } - /// + /// + /// Parses the provided type, extracting the metadata used in type generation for the object graph. + /// + /// The type of the object to inspect and determine a valid type maker. + /// The graph to create a template for. If not supplied the template provider + /// will attempt to assign the best graph type possible for the supplied . + /// IGraphTypeTemplate. public virtual IGraphTypeMaker CreateTypeMaker(Type objectType = null, TypeKind? kind = null) { if (objectType == null) @@ -65,29 +89,29 @@ public virtual IGraphTypeMaker CreateTypeMaker(Type objectType = null, TypeKind? switch (kind.Value) { case TypeKind.SCALAR: - return new ScalarGraphTypeMaker(this.Schema.Configuration); + return new ScalarGraphTypeMaker(_schemaInstance.Configuration); case TypeKind.INTERFACE: - return new InterfaceGraphTypeMaker(this.Schema.Configuration, this.CreateFieldMaker()); + return new InterfaceGraphTypeMaker(_schemaInstance.Configuration, this.CreateFieldMaker()); case TypeKind.UNION: - return new UnionGraphTypeMaker(this.Schema.Configuration); + return new UnionGraphTypeMaker(_schemaInstance.Configuration); case TypeKind.ENUM: - return new EnumGraphTypeMaker(this.Schema.Configuration); + return new EnumGraphTypeMaker(_schemaInstance.Configuration); case TypeKind.INPUT_OBJECT: return new InputObjectGraphTypeMaker( - this.Schema.Configuration, + _schemaInstance.Configuration, this.CreateFieldMaker()); case TypeKind.OBJECT: return new ObjectGraphTypeMaker( - this.Schema.Configuration, + _schemaInstance.Configuration, this.CreateFieldMaker()); case TypeKind.DIRECTIVE: - return new DirectiveMaker(this.Schema, this.CreateArgumentMaker()); + return new DirectiveMaker(_schemaInstance, this.CreateArgumentMaker()); case TypeKind.CONTROLLER: default: @@ -95,39 +119,31 @@ public virtual IGraphTypeMaker CreateTypeMaker(Type objectType = null, TypeKind? } } - /// + /// + /// Creates a maker that can generate valid graph fields + /// + /// IGraphFieldMaker. public virtual IGraphFieldMaker CreateFieldMaker() { - return new GraphFieldMaker(this.Schema, this.CreateArgumentMaker()); + return new GraphFieldMaker(_schemaInstance, this.CreateArgumentMaker()); } - /// + /// + /// Creates a maker that can generate arguments for fields or directives. + /// + /// IGraphArgumentMaker. public virtual IGraphArgumentMaker CreateArgumentMaker() { - return new GraphArgumentMaker(this.Schema); + return new GraphArgumentMaker(_schemaInstance); } - /// + /// + /// Creates a maker that can generate special union graph types. + /// + /// IUnionGraphTypeMaker. public virtual IUnionGraphTypeMaker CreateUnionMaker() { - return new UnionGraphTypeMaker(this.Schema.Configuration); + return new UnionGraphTypeMaker(_schemaInstance.Configuration); } - - /// - public void Initialize(ISchema schemaInstance) - { - Validation.ThrowIfNull(schemaInstance, nameof(schemaInstance)); - - if (this.Schema != null) - throw new InvalidOperationException("This instance has already been initialized with a schema"); - - this.Schema = schemaInstance; - } - - /// - /// Gets the schema this factory works against. - /// - /// The schema. - public ISchema Schema { get; private set; } } } \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionReceiverExtensionTests.cs b/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionReceiverExtensionTests.cs index f9e748e7a..c8089a660 100644 --- a/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionReceiverExtensionTests.cs +++ b/src/unit-tests/graphql-aspnet-subscriptions-tests/SubscriptionReceiverExtensionTests.cs @@ -83,11 +83,10 @@ public void ServiceCollection_VerifyDefaultInjectedObjects() Assert.IsTrue(primaryOptions.DeclarationOptions.AllowedOperations.Contains(GraphOperationType.Subscription)); - Assert.AreEqual(10, primaryOptions.ServiceCollection.Count); + Assert.AreEqual(9, primaryOptions.ServiceCollection.Count); // primary server objects Assert.IsNotNull(primaryOptions.ServiceCollection.SingleOrDefault(x => x.ServiceType == typeof(SubscriptionServerOptions))); - Assert.IsNotNull(primaryOptions.ServiceCollection.SingleOrDefault(x => x.ImplementationType == typeof(SubscriptionEnabledGraphQLTypeMakerFactory))); Assert.IsNotNull(primaryOptions.ServiceCollection.SingleOrDefault(x => x.ImplementationType == typeof(SubscriptionEnabledGraphQLSchemaFactory))); Assert.IsNotNull(primaryOptions.ServiceCollection.SingleOrDefault(x => x.ServiceType == typeof(ISubscriptionServerClientFactory))); Assert.IsNotNull(primaryOptions.ServiceCollection.SingleOrDefault(x => x.ServiceType == typeof(IGlobalSubscriptionClientProxyCollection))); diff --git a/src/unit-tests/graphql-aspnet-testframework/TestServer.cs b/src/unit-tests/graphql-aspnet-testframework/TestServer.cs index de04582c9..058bb493e 100644 --- a/src/unit-tests/graphql-aspnet-testframework/TestServer.cs +++ b/src/unit-tests/graphql-aspnet-testframework/TestServer.cs @@ -169,8 +169,7 @@ public virtual Task CreateQueryPlan(string queryText, strin /// GraphTypeCreationResult. public virtual GraphTypeCreationResult CreateGraphType(Type concreteType, TypeKind kind) { - var factory = new DefaultGraphQLTypeMakerFactory(); - factory.Initialize(this.Schema); + var factory = new GraphTypeMakerFactory(this.Schema); var maker = factory.CreateTypeMaker(concreteType, kind); var template = factory.MakeTemplate(concreteType); @@ -601,6 +600,15 @@ protected virtual async Task RenderResult(IQueryExecutionResult result) } } + /// + /// Creates a factory object that can generate templates and graph types. + /// + /// DefaultGraphQLTypeMakerFactory. + public GraphTypeMakerFactory CreateMakerFactory() + { + return new GraphTypeMakerFactory(this.Schema); + } + /// /// Gets a reference to the schema this test server is hosting. /// diff --git a/src/unit-tests/graphql-aspnet-tests/CommonHelpers/TestServerExtensions.cs b/src/unit-tests/graphql-aspnet-tests/CommonHelpers/TestServerExtensions.cs deleted file mode 100644 index 1b701a260..000000000 --- a/src/unit-tests/graphql-aspnet-tests/CommonHelpers/TestServerExtensions.cs +++ /dev/null @@ -1,35 +0,0 @@ -// ************************************************************* -// project: graphql-aspnet -// -- -// repo: https://github.com/graphql-aspnet -// docs: https://graphql-aspnet.github.io -// -- -// License: MIT -// ************************************************************* - -namespace GraphQL.AspNet.Tests.CommonHelpers -{ - using GraphQL.AspNet.Engine; - using GraphQL.AspNet.Interfaces.Engine; - using GraphQL.AspNet.Interfaces.Schema; - using GraphQL.AspNet.Schemas.Generation; - using GraphQL.AspNet.Tests.Framework; - - public static class TestServerExtensions - { - /// - /// Creates a new maker factory that the test server can use. - /// - /// The type of the schema to render the factory for. - /// The server instance. - /// GraphQL.AspNet.Interfaces.Engine.IGraphQLTypeMakerFactory<TSchema>. - public static IGraphQLTypeMakerFactory CreateMakerFactory(this TestServer serverInstance) - where TSchema : class, ISchema - { - var factory = new DefaultGraphQLTypeMakerFactory(); - factory.Initialize(serverInstance.Schema); - - return factory; - } - } -} \ No newline at end of file diff --git a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTests.cs b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTests.cs index 355166b94..a431b6839 100644 --- a/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Engine/DefaultSchemaFactoryTests.cs @@ -15,7 +15,6 @@ namespace GraphQL.AspNet.Tests.Engine using GraphQL.AspNet.Configuration; using GraphQL.AspNet.Engine; using GraphQL.AspNet.Execution.Exceptions; - using GraphQL.AspNet.Interfaces.Engine; using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Schemas; using GraphQL.AspNet.Schemas.Structural; @@ -33,7 +32,6 @@ public class DefaultSchemaFactoryTests private IServiceCollection SetupCollection() { var collection = new ServiceCollection(); - collection.AddTransient, DefaultGraphQLTypeMakerFactory>(); return collection; } diff --git a/src/unit-tests/graphql-aspnet-tests/Execution/DirectiveProcessorTypeSystemTests.cs b/src/unit-tests/graphql-aspnet-tests/Execution/DirectiveProcessorTypeSystemTests.cs index df9d41f1e..3ec38ad0e 100644 --- a/src/unit-tests/graphql-aspnet-tests/Execution/DirectiveProcessorTypeSystemTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Execution/DirectiveProcessorTypeSystemTests.cs @@ -46,7 +46,6 @@ public class DirectiveProcessorTypeSystemTests public DirectiveProcessorTypeSystemTests() { _serviceCollection = new ServiceCollection(); - _serviceCollection.AddTransient, DefaultGraphQLTypeMakerFactory>(); _itemsExecuted = new List(); _typesToAdd = new List(); diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/DirectiveTypeMakerTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/DirectiveTypeMakerTests.cs index e9252dc7f..6d8efde15 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/DirectiveTypeMakerTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/DirectiveTypeMakerTests.cs @@ -32,8 +32,6 @@ public void Directive_BasicPropertyCheck() var builder = new TestServerBuilder(); var server = builder.Build(); - var factory = server.CreateMakerFactory(); - var template = new GraphDirectiveTemplate(typeof(MultiMethodDirective)); template.Parse(); template.ValidateOrThrow(); diff --git a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/ObjectGraphTypeMakerTests.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/ObjectGraphTypeMakerTests.cs index 83eda91ae..b3f30aa88 100644 --- a/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/ObjectGraphTypeMakerTests.cs +++ b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeMakers/ObjectGraphTypeMakerTests.cs @@ -11,9 +11,11 @@ namespace GraphQL.AspNet.Tests.Schemas.Generation.TypeMakers { using System.Linq; using GraphQL.AspNet.Configuration; + using GraphQL.AspNet.Engine; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; using GraphQL.AspNet.Schemas; + using GraphQL.AspNet.Schemas.Generation.TypeMakers; using GraphQL.AspNet.Schemas.TypeSystem; using GraphQL.AspNet.Tests.Common.CommonHelpers; using GraphQL.AspNet.Tests.CommonHelpers; @@ -46,9 +48,7 @@ public void Object_CreateGraphType_ParsesCorrectly() var server = new TestServerBuilder(TestOptions.UseCodeDeclaredNames).Build(); var template = GraphQLTemplateHelper.CreateGraphTypeTemplate(TypeKind.OBJECT); - var factory = server.CreateMakerFactory(); - - var objectGraphType = factory + var objectGraphType = new GraphTypeMakerFactory(server.Schema) .CreateTypeMaker(typeof(TypeCreationItem)) .CreateGraphType(template).GraphType as IObjectGraphType; From b6e8ec770b2df62e0af86c69802fa67a84dbeffd Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Fri, 4 Aug 2023 15:57:29 -0700 Subject: [PATCH 60/63] WIP --- .../Configuration/GraphQLSchemaBuilderExtensions.cs | 10 +++++++++- .../Configuration/IGraphQLServerExtension.cs | 2 +- .../GraphDirectiveMethodTemplateContainer.cs | 1 - 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/graphql-aspnet/Configuration/GraphQLSchemaBuilderExtensions.cs b/src/graphql-aspnet/Configuration/GraphQLSchemaBuilderExtensions.cs index 5c1399e01..e338d1f39 100644 --- a/src/graphql-aspnet/Configuration/GraphQLSchemaBuilderExtensions.cs +++ b/src/graphql-aspnet/Configuration/GraphQLSchemaBuilderExtensions.cs @@ -93,7 +93,15 @@ public static ISchemaBuilder AddGraphQL( /// The application being constructed. public static void UseGraphQL(this IApplicationBuilder app) { - UseGraphQL(app?.ApplicationServices); + Validation.ThrowIfNull(app, nameof(app)); + var allInjectors = app.ApplicationServices.GetServices(); + if (allInjectors != null) + { + foreach (var injector in allInjectors) + { + injector.UseSchema(app); + } + } } /// diff --git a/src/graphql-aspnet/Interfaces/Configuration/IGraphQLServerExtension.cs b/src/graphql-aspnet/Interfaces/Configuration/IGraphQLServerExtension.cs index 2fd69ce5f..9f6c9e65e 100644 --- a/src/graphql-aspnet/Interfaces/Configuration/IGraphQLServerExtension.cs +++ b/src/graphql-aspnet/Interfaces/Configuration/IGraphQLServerExtension.cs @@ -87,7 +87,7 @@ public void UseExtension(IServiceProvider serviceProvider) /// The configured service provider created during setup. In /// most instances, this will be the instances /// from . - public void UseExtension(IApplicationBuilder app = null, IServiceProvider serviceProvider = null) + public void UseExtension(IApplicationBuilder app, IServiceProvider serviceProvider) { } diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveMethodTemplateContainer.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveMethodTemplateContainer.cs index 46a326fa0..2a93a7eb3 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveMethodTemplateContainer.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveMethodTemplateContainer.cs @@ -43,7 +43,6 @@ public IEnumerable RetrieveRequiredTypes() { // all methods are required to be the same signatured // we can just pull the dependnent types on the first - var list = new List(); if (_templateMap.Count > 0) return _templateMap.Values.First().RetrieveRequiredTypes(); From 019566780d6963be0c6ae81a76f4f51b377b5bf0 Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Sat, 5 Aug 2023 13:57:49 -0700 Subject: [PATCH 61/63] WIP --- .../Generation/TypeMakers/DirectiveMaker.cs | 4 +++- .../TypeTemplates/GraphDirectiveMethodTemplate.cs | 14 +++++++------- .../GraphDirectiveMethodTemplateContainer.cs | 3 ++- src/graphql-aspnet/graphql-aspnet.csproj | 6 ++++-- 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/graphql-aspnet/Schemas/Generation/TypeMakers/DirectiveMaker.cs b/src/graphql-aspnet/Schemas/Generation/TypeMakers/DirectiveMaker.cs index 9fb4b9068..133ba2c75 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeMakers/DirectiveMaker.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeMakers/DirectiveMaker.cs @@ -12,7 +12,6 @@ namespace GraphQL.AspNet.Schemas.Generation.TypeMakers using System.Collections.Generic; using GraphQL.AspNet.Common; using GraphQL.AspNet.Controllers; - using GraphQL.AspNet.Interfaces.Configuration; using GraphQL.AspNet.Interfaces.Engine; using GraphQL.AspNet.Interfaces.Internal; using GraphQL.AspNet.Interfaces.Schema; @@ -86,6 +85,9 @@ public virtual GraphTypeCreationResult CreateGraphType(IGraphTypeTemplate typeTe if (template.ObjectType != typeof(RuntimeExecutionDirective)) result.ConcreteType = template.ObjectType; + // account for any potential type dependencies (input objects etc) + result.AddDependentRange(template.RetrieveRequiredTypes()); + return result; } } diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveMethodTemplate.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveMethodTemplate.cs index 5c5abfbe7..0f105ab49 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveMethodTemplate.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveMethodTemplate.cs @@ -149,14 +149,14 @@ public virtual void ValidateOrThrow() if (this.Method.SingleAttributeOrDefault() != null) { throw new GraphTypeDeclarationException( - $"The directive method {this.InternalName} defines a {nameof(GraphSkipAttribute)}. It cannot be parsed or added " + + $"The directive resolver {this.InternalName} defines a {nameof(GraphSkipAttribute)}. It cannot be parsed or added " + "to the object graph."); } if (this.AppliedDirectives.Any()) { throw new GraphTypeDeclarationException( - $"The directive method {this.InternalName} defines an {nameof(ApplyDirectiveAttribute)}. " + + $"The directive resolver {this.InternalName} defines an {nameof(ApplyDirectiveAttribute)}. " + $"Directive methods cannot have applied directives."); } @@ -169,9 +169,9 @@ public virtual void ValidateOrThrow() if (genericArgs.Length != 1) { throw new GraphTypeDeclarationException( - $"The directive method '{this.InternalName}' defines a return type of'{typeof(Task).Name}' but " + + $"The directive resolver '{this.InternalName}' defines a return type of'{typeof(Task).Name}' but " + "defines no contained return type for the resultant model object yielding a void return after " + - "completion of the task. All graph methods must return a single model object. Consider using " + + "completion of the task. All resolvers must return a single model object. Consider using " + $"'{typeof(Task<>).Name}' instead for asyncronous methods"); } } @@ -179,14 +179,14 @@ public virtual void ValidateOrThrow() if (this.ExpectedReturnType != typeof(IGraphActionResult)) { throw new GraphTypeDeclarationException( - $"The directive method '{this.InternalName}' does not return a {nameof(IGraphActionResult)}. " + - $"All directive methods must return a {nameof(IGraphActionResult)} or {typeof(Task).FriendlyName()}"); + $"The directive resolver '{this.InternalName}' does not return a {nameof(IGraphActionResult)}. " + + $"All directive resolvers must return a {nameof(IGraphActionResult)} or {typeof(Task).FriendlyName()}"); } if (string.IsNullOrWhiteSpace(this.InternalName)) { throw new GraphTypeDeclarationException( - $"The directive method template identified by `{this.Method.Name}` does not declare a valid internal name."); + $"The directive resolver template identified by `{this.Method.Name}` does not declare a valid internal name."); } foreach (var argument in _arguments) diff --git a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveMethodTemplateContainer.cs b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveMethodTemplateContainer.cs index 2a93a7eb3..34e661268 100644 --- a/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveMethodTemplateContainer.cs +++ b/src/graphql-aspnet/Schemas/Generation/TypeTemplates/GraphDirectiveMethodTemplateContainer.cs @@ -76,7 +76,8 @@ public void RegisterMethod(GraphDirectiveMethodTemplate methodTemplate) } /// - /// Retrieves the method template mapped to the given lifecycle and location. Returns null if nothing is registered. + /// Retrieves the resolver data mapped to the given location usage. Returns null if nothing is registered + /// for the provided location. /// /// A valid graphql directive location. /// IGraphMethod. diff --git a/src/graphql-aspnet/graphql-aspnet.csproj b/src/graphql-aspnet/graphql-aspnet.csproj index 221d0a47d..f8b4e8493 100644 --- a/src/graphql-aspnet/graphql-aspnet.csproj +++ b/src/graphql-aspnet/graphql-aspnet.csproj @@ -9,11 +9,13 @@ - + + + - + \ No newline at end of file From f308248eacf5e02197e8bca3a10daae8a538ec62 Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Sat, 5 Aug 2023 15:41:06 -0700 Subject: [PATCH 62/63] WIP, added release branch as PR target --- .github/workflows/ci-build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index d2d3f6b80..1941af606 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -17,6 +17,7 @@ on: pull_request: branches: - master + - 'release/**' env: SLN_PATH: ./src/graphql-aspnet.sln From e6aef96004fa35d223620ee41fc8e812e15ee8fc Mon Sep 17 00:00:00 2001 From: Kevin Carroll Date: Fri, 24 Nov 2023 10:13:49 -0700 Subject: [PATCH 63/63] WIP, fix location of new test data objects from merge --- .../ControllerWithActionAsTypeExtensionForCustomNamedObject.cs | 0 .../TypeTemplates}/ExtensionMethodTestData/CustomNamedObject.cs | 0 .../TypeTemplates}/InterfaceTestData/IInterfaceWithOverloads.cs | 0 .../Generation/TypeTemplates}/ObjectTypeTests/InputRecord.cs | 0 .../Generation/TypeTemplates}/ObjectTypeTests/ObjectRecord.cs | 0 .../TypeTemplates}/ObjectTypeTests/ObjectWithInternalFields.cs | 0 .../ObjectTypeTests/ObjectWithInternalInheritedFields.cs | 0 .../ObjectTypeTests/SimpleScalarStructWithTypeOverride.cs | 0 8 files changed, 0 insertions(+), 0 deletions(-) rename src/unit-tests/graphql-aspnet-tests/{Internal/Templating => Schemas/Generation/TypeTemplates}/ControllerTestData/ControllerWithActionAsTypeExtensionForCustomNamedObject.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal/Templating => Schemas/Generation/TypeTemplates}/ExtensionMethodTestData/CustomNamedObject.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal/Templating => Schemas/Generation/TypeTemplates}/InterfaceTestData/IInterfaceWithOverloads.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal/Templating => Schemas/Generation/TypeTemplates}/ObjectTypeTests/InputRecord.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal/Templating => Schemas/Generation/TypeTemplates}/ObjectTypeTests/ObjectRecord.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal/Templating => Schemas/Generation/TypeTemplates}/ObjectTypeTests/ObjectWithInternalFields.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal/Templating => Schemas/Generation/TypeTemplates}/ObjectTypeTests/ObjectWithInternalInheritedFields.cs (100%) rename src/unit-tests/graphql-aspnet-tests/{Internal/Templating => Schemas/Generation/TypeTemplates}/ObjectTypeTests/SimpleScalarStructWithTypeOverride.cs (100%) diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ControllerTestData/ControllerWithActionAsTypeExtensionForCustomNamedObject.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/ControllerWithActionAsTypeExtensionForCustomNamedObject.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ControllerTestData/ControllerWithActionAsTypeExtensionForCustomNamedObject.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ControllerTestData/ControllerWithActionAsTypeExtensionForCustomNamedObject.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ExtensionMethodTestData/CustomNamedObject.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ExtensionMethodTestData/CustomNamedObject.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ExtensionMethodTestData/CustomNamedObject.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ExtensionMethodTestData/CustomNamedObject.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/InterfaceTestData/IInterfaceWithOverloads.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceTestData/IInterfaceWithOverloads.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/InterfaceTestData/IInterfaceWithOverloads.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/InterfaceTestData/IInterfaceWithOverloads.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/InputRecord.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/InputRecord.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/InputRecord.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/InputRecord.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/ObjectRecord.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ObjectRecord.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/ObjectRecord.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ObjectRecord.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/ObjectWithInternalFields.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ObjectWithInternalFields.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/ObjectWithInternalFields.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ObjectWithInternalFields.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/ObjectWithInternalInheritedFields.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ObjectWithInternalInheritedFields.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/ObjectWithInternalInheritedFields.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/ObjectWithInternalInheritedFields.cs diff --git a/src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/SimpleScalarStructWithTypeOverride.cs b/src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/SimpleScalarStructWithTypeOverride.cs similarity index 100% rename from src/unit-tests/graphql-aspnet-tests/Internal/Templating/ObjectTypeTests/SimpleScalarStructWithTypeOverride.cs rename to src/unit-tests/graphql-aspnet-tests/Schemas/Generation/TypeTemplates/ObjectTypeTests/SimpleScalarStructWithTypeOverride.cs