Skip to content

Commit

Permalink
Mutation Conventions Refinements (ChilliCream#4519)
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelstaib authored Dec 8, 2021
1 parent 9be1421 commit f77a2be
Show file tree
Hide file tree
Showing 145 changed files with 2,851 additions and 2,683 deletions.
14 changes: 7 additions & 7 deletions src/HotChocolate/Core/src/Abstractions/AttributeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public static string GetGraphQLName(this Type type)
}

TypeInfo typeInfo = type.GetTypeInfo();
string name = typeInfo.IsDefined(typeof(GraphQLNameAttribute), false)
var name = typeInfo.IsDefined(typeof(GraphQLNameAttribute), false)
? typeInfo.GetCustomAttribute<GraphQLNameAttribute>()!.Name
: GetFromType(typeInfo);

Expand All @@ -36,7 +36,7 @@ public static string GetGraphQLName(this PropertyInfo property)
throw new ArgumentNullException(nameof(property));
}

string name = property.IsDefined(
var name = property.IsDefined(
typeof(GraphQLNameAttribute), false)
? property.GetCustomAttribute<GraphQLNameAttribute>()!.Name
: NormalizeName(property.Name);
Expand All @@ -51,7 +51,7 @@ public static string GetGraphQLName(this MethodInfo method)
throw new ArgumentNullException(nameof(method));
}

string name = method.IsDefined(
var name = method.IsDefined(
typeof(GraphQLNameAttribute), false)
? method.GetCustomAttribute<GraphQLNameAttribute>()!.Name
: NormalizeMethodName(method);
Expand All @@ -66,7 +66,7 @@ public static string GetGraphQLName(this ParameterInfo parameter)
throw new ArgumentNullException(nameof(parameter));
}

string name = parameter.IsDefined(
var name = parameter.IsDefined(
typeof(GraphQLNameAttribute), false)
? parameter.GetCustomAttribute<GraphQLNameAttribute>()!.Name
: NormalizeName(parameter.Name!);
Expand Down Expand Up @@ -97,7 +97,7 @@ public static string GetGraphQLName(this MemberInfo member)

private static string NormalizeMethodName(MethodInfo method)
{
string name = method.Name;
var name = method.Name;

if (name.StartsWith(_get, StringComparison.Ordinal)
&& name.Length > _get.Length)
Expand Down Expand Up @@ -140,7 +140,7 @@ private static bool IsAsyncMethod(Type returnType)
typeof(GraphQLDescriptionAttribute),
false))
{
GraphQLDescriptionAttribute attribute =
var attribute =
(GraphQLDescriptionAttribute)
attributeProvider.GetCustomAttributes(
typeof(GraphQLDescriptionAttribute),
Expand Down Expand Up @@ -181,7 +181,7 @@ private static string GetFromType(Type type)
{
if (type.GetTypeInfo().IsGenericType)
{
string name = type.GetTypeInfo()
var name = type.GetTypeInfo()
.GetGenericTypeDefinition()
.Name;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

namespace HotChocolate.Execution;

// todo : deprecate this interface and use IQueryResult
public interface IReadOnlyQueryResult
: IQueryResult
public interface IReadOnlyQueryResult : IQueryResult
{
}
3 changes: 1 addition & 2 deletions src/HotChocolate/Core/src/Abstractions/Path.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@ public virtual IndexerPathSegment Append(int index)
{
if (index < 0)
{
// TODO : ThrowHelper
throw new ArgumentException();
throw new ArgumentOutOfRangeException(nameof(index));
}

return new IndexerPathSegment(this, index);
Expand Down
10 changes: 10 additions & 0 deletions src/HotChocolate/Core/src/Abstractions/WellKnownMiddleware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,14 @@ public static class WellKnownMiddleware
/// This key identifies a resolver service middleware.
/// </summary>
public const string ResolverService = "HotChocolate.Resolvers.ResolverService";

/// <summary>
/// This key identifies the mutation convention middleware.
/// </summary>
public const string MutationArguments = "HotChocolate.Types.Mutations.Arguments";

/// <summary>
/// This key identifies the mutation convention middleware.
/// </summary>
public const string MutationErrors = "HotChocolate.Types.Mutations.Errors";
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
<RootNamespace>HotChocolate.Execution</RootNamespace>
</PropertyGroup>

<ItemGroup>
<InternalsVisibleTo Include="HotChocolate.Types.Mutations" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Abstractions\HotChocolate.Abstractions.csproj" />
<ProjectReference Include="..\Fetching\HotChocolate.Fetching.csproj" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,18 @@ public static bool TryCoerceArguments(
{
if (argument.IsFinal)
{
args.Add(argument.Argument.Name, argument);
args.Add(argument.Name, argument);
}
else
{
IValueNode literal = VariableRewriter.Rewrite(
argument.ValueLiteral!,
argument.Type,
argument.Argument.DefaultValue,
argument.DefaultValue,
resolverContext.Variables);

args.Add(argument.Argument.Name, new ArgumentValue(
argument.Argument,
args.Add(argument.Name, new ArgumentValue(
argument,
literal.TryGetValueKind(out ValueKind kind)
? kind
: ValueKind.Unknown,
Expand Down
59 changes: 51 additions & 8 deletions src/HotChocolate/Core/src/Execution/Processing/ArgumentValue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,19 @@

namespace HotChocolate.Execution.Processing;

public sealed class ArgumentValue
public sealed class ArgumentValue : IInputFieldInfo
{
private readonly IInputFieldInfo _argument;

public ArgumentValue(
IInputField argument,
IInputFieldInfo argument,
ValueKind kind,
bool isFinal,
bool isImplicit,
object? value,
IValueNode valueLiteral)
{
Argument = argument ?? throw new ArgumentNullException(nameof(argument));
_argument = argument ?? throw new ArgumentNullException(nameof(argument));
Kind = kind;
IsFinal = isFinal;
IsImplicit = isImplicit;
Expand All @@ -24,9 +26,9 @@ public ArgumentValue(
ValueLiteral = valueLiteral ?? throw new ArgumentNullException(nameof(valueLiteral));
}

public ArgumentValue(IInputField argument, IError error)
public ArgumentValue(IInputFieldInfo argument, IError error)
{
Argument = argument ?? throw new ArgumentNullException(nameof(argument));
_argument = argument ?? throw new ArgumentNullException(nameof(argument));
Error = error ?? throw new ArgumentNullException(nameof(error));
HasError = true;
IsFinal = true;
Expand All @@ -35,23 +37,64 @@ public ArgumentValue(IInputField argument, IError error)
ValueLiteral = null;
}

public IInputField Argument { get; }
/// <summary>
/// Gets the argument name.
/// </summary>
public NameString Name => _argument.Name;

/// <summary>
/// Gets the argument field coordinate.
/// </summary>
public FieldCoordinate Coordinate => _argument.Coordinate;

/// <summary>
/// Gets the argument type.
/// </summary>
public IInputType Type => _argument.Type;

public IInputType Type => Argument.Type;
/// <summary>
/// Gets the argument runtime type.
/// </summary>
public Type RuntimeType => _argument.RuntimeType;

public IInputValueFormatter? Formatter => Argument.Formatter;
/// <summary>
/// Gets the argument default value.
/// </summary>
public IValueNode? DefaultValue => _argument.DefaultValue;

/// <summary>
/// Return an optional input value formatter.
/// </summary>
public IInputValueFormatter? Formatter => _argument.Formatter;

public ValueKind? Kind { get; }

/// <summary>
/// Defines if this argument value is fully coerced and
/// need no post processing.
/// </summary>
public bool IsFinal { get; }

/// <summary>
/// Defines if this argument value has errors.
/// </summary>
public bool HasError { get; }

public bool IsImplicit { get; }

/// <summary>
/// Gets the runtime value representation of this argument.
/// </summary>
public object? Value { get; }

/// <summary>
/// Gets the value literal of this argument value.
/// </summary>
public IValueNode? ValueLiteral { get; }

/// <summary>
/// If this argument has error this represents the argument error.
/// </summary>
public IError? Error { get; }

}
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ private T CoerceArgumentValue<T>(ArgumentValue argument)
// runtime version we can skip over parsing it.
if (!argument.IsFinal)
{
value = _parser.ParseLiteral(argument.ValueLiteral!, argument.Argument, typeof(T));
value = _parser.ParseLiteral(argument.ValueLiteral!, argument, typeof(T));
}

if (value is null)
Expand All @@ -111,15 +111,15 @@ private T CoerceArgumentValue<T>(ArgumentValue argument)
throw ResolverContext_LiteralsNotSupported(
_selection.SyntaxNode,
Path,
argument.Argument.Name,
argument.Name,
typeof(T));
}

// we are unable to convert the argument to the request type.
throw ResolverContext_CannotConvertArgument(
_selection.SyntaxNode,
Path,
argument.Argument.Name,
argument.Name,
typeof(T));
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System;
using System.Collections.Generic;
using HotChocolate.Language;
using HotChocolate.Resolvers;
Expand Down Expand Up @@ -155,7 +154,7 @@ private T CoerceArgumentValue<T>(ArgumentValue argument)
{
value = _parentContext._parser.ParseLiteral(
argument.ValueLiteral!,
argument.Argument,
argument,
typeof(T));
}

Expand All @@ -177,7 +176,7 @@ private T CoerceArgumentValue<T>(ArgumentValue argument)
if (typeof(IValueNode).IsAssignableFrom(typeof(T)))
{
throw ResolverContext_LiteralsNotSupported(
_selection.SyntaxNode, _path, argument.Argument.Name, typeof(T));
_selection.SyntaxNode, _path, argument.Name, typeof(T));
}

// If the object is internally held as a dictionary structure we will try to
Expand All @@ -204,7 +203,7 @@ private T CoerceArgumentValue<T>(ArgumentValue argument)

// we are unable to convert the argument to the request type.
throw ResolverContext_CannotConvertArgument(
_selection.SyntaxNode, _path, argument.Argument.Name, typeof(T));
_selection.SyntaxNode, _path, argument.Name, typeof(T));
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
using HotChocolate.Execution.Configuration;
using HotChocolate.Types;

namespace Microsoft.Extensions.DependencyInjection;

/// <summary>
/// Provides global configuration methods for mutation conventions to the
/// <see cref="IRequestExecutorBuilder"/>.
/// </summary>
public static class MutationRequestExecutorBuilderExtensions
{
/// <summary>
Expand All @@ -10,27 +15,52 @@ public static class MutationRequestExecutorBuilderExtensions
/// <param name="builder">
/// The request executor builder
/// </param>
/// <param name="applyToAllMutations">
/// Defines if the mutation convention defaults shall be applied to all mutations.
/// </param>
/// <returns>
/// The request executor builder
/// </returns>
/// <exception cref="ArgumentNullException">
/// The <paramref name="builder"/> is null.
/// </exception>
public static IRequestExecutorBuilder EnableMutationConventions(
this IRequestExecutorBuilder builder)
public static IRequestExecutorBuilder AddMutationConventions(
this IRequestExecutorBuilder builder,
bool applyToAllMutations = false)
=> AddMutationConventions(
builder,
new MutationConventionOptions
{
ApplyToAllMutations = applyToAllMutations
});

/// <summary>
/// Enables mutation conventions which will simplify creating GraphQL mutations.
/// </summary>
/// <param name="builder">
/// The request executor builder
/// </param>
/// <param name="options">
/// The mutation convention options.
/// </param>
/// <returns>
/// The request executor builder
/// </returns>
/// <exception cref="ArgumentNullException">
/// The <paramref name="builder"/> is null.
/// </exception>
public static IRequestExecutorBuilder AddMutationConventions(
this IRequestExecutorBuilder builder,
MutationConventionOptions options)
{
if (builder is null)
{
throw new ArgumentNullException(nameof(builder));
}

builder
.TryAddTypeInterceptor<ErrorTypeInterceptor>()
.TryAddTypeInterceptor<InputArgumentTypeInterceptor>()
.TryAddTypeInterceptor<PayloadTypeInterceptor>()
.Services
.AddSingleton<IParameterExpressionBuilder, InputParameterExpressionBuilder>()
.AddSingleton<IParameterExpressionBuilder, InputArgumentParameterExpressionBuilder>();
.ConfigureSchema(c => c.ContextData[MutationContextDataKeys.Options] = options)
.TryAddTypeInterceptor<MutationConventionTypeInterceptor>();

return builder;
}
Expand All @@ -41,7 +71,7 @@ public static IRequestExecutorBuilder EnableMutationConventions(
/// interface schema type.
///
/// This has to be used together with <see cref="ErrorAttribute"/> or
/// <see cref="ErrorObjectFieldDescriptorExtensions.Error"/>
/// <see cref="MutationObjectFieldDescriptorExtensions.Error"/>
/// </summary>
/// <param name="builder">
/// The request executor builder
Expand All @@ -62,7 +92,7 @@ public static IRequestExecutorBuilder AddErrorInterfaceType<T>(
/// interface schema type.
///
/// This has to be used together with <see cref="ErrorAttribute"/> or
/// <see cref="ErrorObjectFieldDescriptorExtensions.Error"/>
/// <see cref="MutationObjectFieldDescriptorExtensions.Error"/>
/// </summary>
/// <param name="builder">
/// The request executor builder
Expand Down
Loading

0 comments on commit f77a2be

Please sign in to comment.