Skip to content

Commit b4c3ac0

Browse files
authored
Added File Upload Support to Fusion. (#6359)
1 parent 8f5e864 commit b4c3ac0

File tree

98 files changed

+6212
-1651
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

98 files changed

+6212
-1651
lines changed

src/HotChocolate/Core/src/Types/Types/Extensions/TypeExtensions.cs

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ internal static IInputType EnsureInputType(this IType type)
272272
throw InputTypeExpected(type);
273273
}
274274

275-
return (IInputType)type;
275+
return (IInputType) type;
276276
}
277277

278278
public static bool IsOutputType(this IType type)
@@ -297,7 +297,7 @@ internal static IOutputType EnsureOutputType(this IType type)
297297
throw OutputTypeExpected(type);
298298
}
299299

300-
return (IOutputType)type;
300+
return (IOutputType) type;
301301
}
302302

303303
public static bool IsUnionType(this IType type)
@@ -345,7 +345,7 @@ internal static bool IsType(this IType type, TypeKind kind)
345345
return true;
346346
}
347347

348-
if (type.Kind == TypeKind.NonNull && ((NonNullType)type).Type.Kind == kind)
348+
if (type.Kind == TypeKind.NonNull && ((NonNullType) type).Type.Kind == kind)
349349
{
350350
return true;
351351
}
@@ -363,7 +363,8 @@ private static bool IsType(this IType type, TypeKind kind1, TypeKind kind2)
363363

364364
if (type.Kind == TypeKind.NonNull)
365365
{
366-
var innerKind = ((NonNullType)type).Type.Kind;
366+
var innerKind = ((NonNullType) type).Type.Kind;
367+
367368
if (innerKind == kind1 || innerKind == kind2)
368369
{
369370
return true;
@@ -383,7 +384,8 @@ internal static bool IsType(this IType type, TypeKind kind1, TypeKind kind2, Typ
383384

384385
if (type.Kind == TypeKind.NonNull)
385386
{
386-
var innerKind = ((NonNullType)type).Type.Kind;
387+
var innerKind = ((NonNullType) type).Type.Kind;
388+
387389
if (innerKind == kind1 || innerKind == kind2 || type.Kind == kind3)
388390
{
389391
return true;
@@ -402,12 +404,12 @@ public static IType InnerType(this IType type)
402404

403405
if (type.Kind == TypeKind.NonNull)
404406
{
405-
return ((NonNullType)type).Type;
407+
return ((NonNullType) type).Type;
406408
}
407409

408410
if (type.Kind == TypeKind.List)
409411
{
410-
return ((ListType)type).ElementType;
412+
return ((ListType) type).ElementType;
411413
}
412414

413415
return type;
@@ -422,7 +424,7 @@ public static IType NullableType(this IType type)
422424

423425
return type.Kind != TypeKind.NonNull
424426
? type
425-
: ((NonNullType)type).Type;
427+
: ((NonNullType) type).Type;
426428
}
427429

428430
public static string TypeName(this IType type)
@@ -444,16 +446,16 @@ public static ListType ListType(this IType type)
444446

445447
if (type.Kind == TypeKind.List)
446448
{
447-
return (ListType)type;
449+
return (ListType) type;
448450
}
449451

450452
if (type.Kind == TypeKind.NonNull)
451453
{
452-
var innerType = ((NonNullType)type).Type;
454+
var innerType = ((NonNullType) type).Type;
453455

454456
if (innerType.Kind == TypeKind.List)
455457
{
456-
return (ListType)innerType;
458+
return (ListType) innerType;
457459
}
458460
}
459461

@@ -471,7 +473,7 @@ public static INamedType NamedType(this IType type)
471473

472474
if (IsNamed(current))
473475
{
474-
return (INamedType)current;
476+
return (INamedType) current;
475477
}
476478

477479
for (var i = 0; i < 6; i++)
@@ -480,7 +482,7 @@ public static INamedType NamedType(this IType type)
480482

481483
if (IsNamed(current))
482484
{
483-
return (INamedType)current;
485+
return (INamedType) current;
484486
}
485487
}
486488

@@ -648,6 +650,15 @@ public static IType ToType(
648650
TypeResources.TypeExtensions_KindIsNotSupported);
649651
}
650652

653+
public static ITypeNode RenameName(this ITypeNode typeNode, string name)
654+
=> typeNode switch
655+
{
656+
NonNullTypeNode nonNull => new NonNullTypeNode((INullableTypeNode)RenameName(nonNull.Type, name)),
657+
ListTypeNode list => new ListTypeNode(RenameName(list.Type, name)),
658+
NamedTypeNode named => named.WithName(named.Name.WithValue(name)),
659+
_ => throw new NotSupportedException(TypeResources.TypeExtensions_KindIsNotSupported)
660+
};
661+
651662
public static bool IsInstanceOfType(this IInputType type, IValueNode literal)
652663
{
653664
while (true)
@@ -670,14 +681,14 @@ public static bool IsInstanceOfType(this IInputType type, IValueNode literal)
670681
switch (type.Kind)
671682
{
672683
case TypeKind.NonNull:
673-
type = (IInputType)((NonNullType)type).Type;
684+
type = (IInputType) ((NonNullType) type).Type;
674685
continue;
675686

676687
case TypeKind.List:
677688
{
678689
if (literal.Kind is SyntaxKind.ListValue)
679690
{
680-
var list = (ListValueNode)literal;
691+
var list = (ListValueNode) literal;
681692

682693
if (list.Items.Count == 0)
683694
{
@@ -687,15 +698,15 @@ public static bool IsInstanceOfType(this IInputType type, IValueNode literal)
687698
literal = list.Items[0];
688699
}
689700

690-
type = (IInputType)((ListType)type).ElementType;
701+
type = (IInputType) ((ListType) type).ElementType;
691702
continue;
692703
}
693704

694705
case TypeKind.InputObject:
695706
return literal.Kind == SyntaxKind.ObjectValue;
696707

697708
default:
698-
return ((ILeafType)type).IsInstanceOfType(literal);
709+
return ((ILeafType) type).IsInstanceOfType(literal);
699710
}
700711
}
701712
}
@@ -752,4 +763,4 @@ public static IType RewriteNullability(this IType type, INullabilityNode? nullab
752763
throw RewriteNullability_InvalidNullabilityStructure();
753764
}
754765
}
755-
}
766+
}

src/HotChocolate/Core/src/Types/Types/InputParser.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -467,12 +467,14 @@ private object ParseDirective(
467467

468468
return null;
469469
}
470+
471+
if(type.Kind == TypeKind.NonNull)
472+
{
473+
type = ((NonNullType)type).Type;
474+
}
470475

471476
switch (type.Kind)
472477
{
473-
case TypeKind.NonNull:
474-
return Deserialize(resultValue, ((NonNullType)type).Type, path, field);
475-
476478
case TypeKind.List:
477479
return DeserializeList(resultValue, (ListType)type, path, field);
478480

src/HotChocolate/Fusion/src/Core/Clients/DefaultHttpGraphQLClient.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System.Text.Json;
22
using HotChocolate.Fusion.Metadata;
33
using HotChocolate.Transport.Http;
4+
using static HotChocolate.Fusion.Clients.TransportFeatures;
45

56
namespace HotChocolate.Fusion.Clients;
67

@@ -40,6 +41,12 @@ private async Task<GraphQLResponse> ExecuteInternalAsync(SubgraphGraphQLRequest
4041
try
4142
{
4243
var request = new GraphQLHttpRequest(subgraphRequest, _config.EndpointUri);
44+
45+
if((subgraphRequest.TransportFeatures & FileUpload) == FileUpload)
46+
{
47+
request.EnableFileUploads = true;
48+
}
49+
4350
using var response = await _client.SendAsync(request, ct).ConfigureAwait(false);
4451
var result = await response.ReadAsResultAsync(ct).ConfigureAwait(false);
4552
return new GraphQLResponse(result);

src/HotChocolate/Fusion/src/Core/Clients/SubgraphGraphQLRequest.cs

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,77 @@
33

44
namespace HotChocolate.Fusion.Clients;
55

6+
/// <summary>
7+
/// Represents a GraphQL request that is sent to a subgraph.
8+
/// </summary>
69
public sealed class SubgraphGraphQLRequest
710
{
11+
/// <summary>
12+
/// Initializes a new instance of <see cref="SubgraphGraphQLRequest"/>.
13+
/// </summary>
14+
/// <param name="subgraph">
15+
/// The name of the subgraph.
16+
/// </param>
17+
/// <param name="document">
18+
/// A GraphQL document string.
19+
/// </param>
20+
/// <param name="variableValues">
21+
/// The variable values.
22+
/// </param>
23+
/// <param name="extensions">
24+
/// The extensions.
25+
/// </param>
26+
/// <param name="transportFeatures">
27+
/// The transport features that are needed for this GraphQL request.
28+
/// </param>
829
public SubgraphGraphQLRequest(
930
string subgraph,
1031
string document,
1132
ObjectValueNode? variableValues,
12-
ObjectValueNode? extensions)
33+
ObjectValueNode? extensions,
34+
TransportFeatures transportFeatures = TransportFeatures.Standard)
1335
{
1436
Subgraph = subgraph;
1537
Document = document;
1638
VariableValues = variableValues;
1739
Extensions = extensions;
40+
TransportFeatures = transportFeatures;
1841
}
1942

43+
/// <summary>
44+
/// Gets the name of the subgraph.
45+
/// </summary>
2046
public string Subgraph { get; }
2147

48+
/// <summary>
49+
/// Gets a GraphQL document string.
50+
/// </summary>
2251
public string Document { get; }
2352

53+
/// <summary>
54+
/// Gets the variable values.
55+
/// </summary>
2456
public ObjectValueNode? VariableValues { get; }
2557

58+
/// <summary>
59+
/// Gets the extensions.
60+
/// </summary>
2661
public ObjectValueNode? Extensions { get; }
2762

28-
public static implicit operator OperationRequest(SubgraphGraphQLRequest method)
29-
=> new(method.Document, null, null, method.VariableValues, method.Extensions);
30-
}
63+
/// <summary>
64+
/// Gets the transport features that are needed for this GraphQL request.
65+
/// </summary>
66+
public TransportFeatures TransportFeatures { get; }
67+
68+
/// <summary>
69+
/// Implicitly converts <see cref="SubgraphGraphQLRequest"/>s to <see cref="OperationRequest"/>s.
70+
/// </summary>
71+
/// <param name="request">
72+
/// The <see cref="SubgraphGraphQLRequest"/> to convert.
73+
/// </param>
74+
/// <returns>
75+
/// The converted <see cref="OperationRequest"/>.
76+
/// </returns>
77+
public static implicit operator OperationRequest(SubgraphGraphQLRequest request)
78+
=> new(request.Document, null, null, request.VariableValues, request.Extensions);
79+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
namespace HotChocolate.Fusion.Clients;
2+
3+
/// <summary>
4+
/// Specifies the transport features that are needed for a GraphQL request.
5+
/// </summary>
6+
[Flags]
7+
public enum TransportFeatures
8+
{
9+
/// <summary>
10+
/// Standard GraphQL over HTTP POST request.
11+
/// </summary>
12+
Standard = 0,
13+
14+
/// <summary>
15+
/// GraphQL multipart request.
16+
/// </summary>
17+
FileUpload = 1,
18+
19+
/// <summary>
20+
/// All Features.
21+
/// </summary>
22+
All = Standard | FileUpload
23+
}

src/HotChocolate/Fusion/src/Core/DependencyInjection/GatewayConfigurationTypeModule.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
using HotChocolate.Fusion.Configuration;
55
using HotChocolate.Fusion.Metadata;
66
using HotChocolate.Language;
7+
using HotChocolate.Types;
8+
using HotChocolate.Types.Descriptors.Definitions;
79
using static System.Threading.Tasks.TaskCreationOptions;
810

911
namespace Microsoft.Extensions.DependencyInjection;
@@ -78,5 +80,10 @@ private static void ApplyConfiguration(ISchemaBuilder schemaBuilder, DocumentNod
7880
schemaBuilder
7981
.AddDocument(schemaDoc)
8082
.SetFusionGraphConfig(fusionGraphConfig);
83+
84+
if (schemaDoc.Definitions.Any(t => t is ScalarTypeDefinitionNode { Name.Value: "Upload" }))
85+
{
86+
schemaBuilder.AddType<UploadType>();
87+
}
8188
}
8289
}

src/HotChocolate/Fusion/src/Core/Execution/ExecutorUtils.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ private static void ComposeResult(
303303
else
304304
{
305305
var typeInfo = selectionData.GetTypeName();
306-
var typeMetadata = context.Configuration.GetType<ObjectTypeInfo>(typeInfo);
306+
var typeMetadata = context.Configuration.GetType<ObjectTypeMetadata>(typeInfo);
307307
type = context.Schema.GetType<ObjectType>(typeMetadata.Name);
308308
}
309309

src/HotChocolate/Fusion/src/Core/FusionResources.Designer.cs

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/HotChocolate/Fusion/src/Core/FusionResources.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,7 @@
6666
<data name="ExecutionState_RegisterState_StateImmutable" xml:space="preserve">
6767
<value>The state for the selection set `{0}` is immutable.</value>
6868
</data>
69+
<data name="ExecutionNodeBuilderMiddleware_CreateResolveByKeyBatchNode_StateInconsistent" xml:space="preserve">
70+
<value>The state is inconsistent.</value>
71+
</data>
6972
</root>

0 commit comments

Comments
 (0)