Skip to content

Commit b8209ef

Browse files
committed
Mutation Convention Type Inference Issue. (#6004)
* Added a test that shows an inssue in the type inference for mutation conventions. * Fixed List Handling * trailing ,
1 parent 0407e34 commit b8209ef

File tree

4 files changed

+96
-33
lines changed

4 files changed

+96
-33
lines changed

src/HotChocolate/Core/src/Types.Mutations/MutationConventionTypeInterceptor.cs

Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,7 @@ private void TryApplyPayloadConvention(
453453

454454
var type = CreatePayloadType(
455455
payloadTypeName,
456-
new(payloadFieldName, EnsureNullable(mutation.Type!)),
456+
new(payloadFieldName, EnsureNullable(NormalizeTypeRef(mutation.Type!))),
457457
errorField);
458458
RegisterType(type);
459459

@@ -826,7 +826,7 @@ private TypeReference EnsureNonNull(TypeReference typeRef)
826826
return Create(CreateTypeNode(new NonNullType(type)));
827827
}
828828

829-
private ITypeNode CreateTypeNode(IType type)
829+
private static ITypeNode CreateTypeNode(IType type)
830830
=> type switch
831831
{
832832
NonNullType nnt => new NonNullTypeNode((INullableTypeNode) CreateTypeNode(nnt.Type)),
@@ -835,41 +835,42 @@ private ITypeNode CreateTypeNode(IType type)
835835
_ => throw new NotSupportedException("Type is not supported.")
836836
};
837837

838-
private readonly ref struct Options
838+
private static TypeReference NormalizeTypeRef(TypeReference typeRef)
839839
{
840-
public Options(
841-
string? inputTypeNamePattern,
842-
string? inputArgumentName,
843-
string? payloadTypeNamePattern,
844-
string? payloadErrorTypeNamePattern,
845-
string? payloadErrorsFieldName,
846-
bool? apply)
840+
if (typeRef is ExtendedTypeReference { Type.IsGeneric: true } extendedTypeRef &&
841+
typeof(IMutationResult).IsAssignableFrom(extendedTypeRef.Type.Type))
847842
{
848-
InputTypeNamePattern = inputTypeNamePattern ??
849-
MutationConventionOptionDefaults.InputTypeNamePattern;
850-
InputArgumentName = inputArgumentName ??
851-
MutationConventionOptionDefaults.InputArgumentName;
852-
PayloadTypeNamePattern = payloadTypeNamePattern ??
853-
MutationConventionOptionDefaults.PayloadTypeNamePattern;
854-
PayloadErrorsFieldName = payloadErrorsFieldName ??
855-
MutationConventionOptionDefaults.PayloadErrorsFieldName;
856-
PayloadErrorTypeNamePattern = payloadErrorTypeNamePattern ??
857-
MutationConventionOptionDefaults.ErrorTypeNamePattern;
858-
Apply = apply ??
859-
MutationConventionOptionDefaults.ApplyToAllMutations;
843+
return extendedTypeRef.WithType(extendedTypeRef.Type.TypeArguments[0]);
860844
}
861845

862-
public string InputTypeNamePattern { get; }
846+
return typeRef;
847+
}
848+
849+
private readonly ref struct Options(
850+
string? inputTypeNamePattern,
851+
string? inputArgumentName,
852+
string? payloadTypeNamePattern,
853+
string? payloadErrorTypeNamePattern,
854+
string? payloadErrorsFieldName,
855+
bool? apply)
856+
{
857+
public string InputTypeNamePattern { get; } = inputTypeNamePattern ??
858+
MutationConventionOptionDefaults.InputTypeNamePattern;
863859

864-
public string InputArgumentName { get; }
860+
public string InputArgumentName { get; } = inputArgumentName ??
861+
MutationConventionOptionDefaults.InputArgumentName;
865862

866-
public string PayloadTypeNamePattern { get; }
863+
public string PayloadTypeNamePattern { get; } = payloadTypeNamePattern ??
864+
MutationConventionOptionDefaults.PayloadTypeNamePattern;
867865

868-
public string PayloadErrorTypeNamePattern { get; }
866+
public string PayloadErrorTypeNamePattern { get; } = payloadErrorTypeNamePattern ??
867+
MutationConventionOptionDefaults.ErrorTypeNamePattern;
869868

870-
public string PayloadErrorsFieldName { get; }
869+
public string PayloadErrorsFieldName { get; } = payloadErrorsFieldName ??
870+
MutationConventionOptionDefaults.PayloadErrorsFieldName;
871871

872-
public bool Apply { get; }
872+
public bool Apply { get; } = apply ??
873+
MutationConventionOptionDefaults.ApplyToAllMutations;
873874

874875
public string FormatInputTypeName(string mutationName)
875876
=> InputTypeNamePattern.Replace(

src/HotChocolate/Core/src/Types.Mutations/MutationResultTypeDiscoveryHandler.cs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@ namespace HotChocolate.Types;
44

55
internal sealed class MutationResultTypeDiscoveryHandler(ITypeInspector typeInspector) : TypeDiscoveryHandler
66
{
7-
private readonly ITypeInspector _typeInspector = typeInspector ??
8-
throw new ArgumentNullException(nameof(typeInspector));
9-
107
public override bool TryInferType(
118
TypeReference typeReference,
129
TypeDiscoveryInfo typeInfo,
@@ -18,15 +15,15 @@ public override bool TryInferType(
1815
typeof(IMutationResult).IsAssignableFrom(runtimeType) &&
1916
typeReference is ExtendedTypeReference typeRef)
2017
{
21-
var type = _typeInspector.GetType(runtimeType.GenericTypeArguments[0]);
18+
var type = GetNamedType(typeInspector.GetType(runtimeType.GenericTypeArguments[0]));
2219
schemaTypeRefs = new TypeReference[runtimeType.GenericTypeArguments.Length];
2320
schemaTypeRefs[0] = typeRef.WithType(type);
2421

2522
for (var i = 1; i < runtimeType.GenericTypeArguments.Length; i++)
2623
{
2724
var errorType = runtimeType.GenericTypeArguments[i];
2825

29-
type = _typeInspector.GetType(
26+
type = typeInspector.GetType(
3027
typeof(Exception).IsAssignableFrom(errorType)
3128
? typeof(ExceptionObjectType<>).MakeGenericType(errorType)
3229
: typeof(ErrorObjectType<>).MakeGenericType(errorType));
@@ -40,4 +37,10 @@ public override bool TryInferType(
4037
schemaTypeRefs = null;
4138
return false;
4239
}
40+
41+
private IExtendedType GetNamedType(IExtendedType extendedType)
42+
{
43+
var typeInfo = typeInspector.CreateTypeInfo(extendedType);
44+
return typeInspector.GetType(typeInfo.NamedType);
45+
}
4346
}

src/HotChocolate/Core/test/Types.Mutations.Tests/AnnotationBasedMutations.cs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1114,6 +1114,20 @@ public async Task Query_Filed_Stays_NonNull()
11141114
schema.MatchSnapshot();
11151115
}
11161116

1117+
[Fact]
1118+
public async Task List_Return_Type()
1119+
{
1120+
var schema =
1121+
await new ServiceCollection()
1122+
.AddGraphQL()
1123+
.AddQueryType(d => d.Field("abc").Resolve("def"))
1124+
.AddMutationType<ListReturnMutation>()
1125+
.AddMutationConventions()
1126+
.BuildSchemaAsync();
1127+
1128+
schema.MatchSnapshot();
1129+
}
1130+
11171131
[Fact]
11181132
public async Task Mutation_Aggregate_Error_Not_Mapped()
11191133
{
@@ -1641,6 +1655,27 @@ public string DoSomething(string something)
16411655

16421656
public record DoSomething2Payload(int? UserId);
16431657

1658+
public class ListReturnMutation
1659+
{
1660+
public MutationResult<List<ResultItem>> AddItem(AddItemInput input)
1661+
=> new List<ResultItem>
1662+
{
1663+
new(),
1664+
new(),
1665+
new(),
1666+
};
1667+
1668+
public class AddItemInput
1669+
{
1670+
public int Count { get; set; }
1671+
}
1672+
1673+
public class ResultItem
1674+
{
1675+
public string Name { get; set; } = "Test";
1676+
}
1677+
}
1678+
16441679
public record SomeNewError(string Message);
16451680

16461681
public class CustomErrorConfig : MutationErrorConfiguration
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
schema {
2+
query: Query
3+
mutation: ListReturnMutation
4+
}
5+
6+
type AddItemPayload {
7+
resultItem: [ResultItem!]
8+
}
9+
10+
type ListReturnMutation {
11+
addItem(input: AddItemInput!): AddItemPayload!
12+
}
13+
14+
type Query {
15+
abc: String
16+
}
17+
18+
type ResultItem {
19+
name: String!
20+
}
21+
22+
input AddItemInput {
23+
count: Int!
24+
}

0 commit comments

Comments
 (0)