Skip to content

Commit d022df3

Browse files
[Fusion] Support union and input object type in composite schema (#8283)
1 parent 7604371 commit d022df3

File tree

7 files changed

+282
-48
lines changed

7 files changed

+282
-48
lines changed

src/HotChocolate/Fusion-vnext/src/Fusion.Execution.Types/Completion/CompletionTools.cs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public static FusionInterfaceTypeDefinitionCollection CreateInterfaceTypeCollect
6262
IReadOnlyList<NamedTypeNode> interfaceTypes,
6363
CompositeSchemaContext context)
6464
{
65-
if(interfaceTypes.Count == 0)
65+
if (interfaceTypes.Count == 0)
6666
{
6767
return FusionInterfaceTypeDefinitionCollection.Empty;
6868
}
@@ -77,6 +77,20 @@ public static FusionInterfaceTypeDefinitionCollection CreateInterfaceTypeCollect
7777
return new FusionInterfaceTypeDefinitionCollection(temp);
7878
}
7979

80+
public static FusionObjectTypeDefinitionCollection CreateObjectTypeCollection(
81+
IReadOnlyList<NamedTypeNode> types,
82+
CompositeSchemaContext context)
83+
{
84+
var temp = new FusionObjectTypeDefinition[types.Count];
85+
86+
for (var i = 0; i < types.Count; i++)
87+
{
88+
temp[i] = (FusionObjectTypeDefinition)context.GetType(types[i]);
89+
}
90+
91+
return new FusionObjectTypeDefinitionCollection(temp);
92+
}
93+
8094
public static SourceObjectTypeCollection CreateSourceObjectTypeCollection(
8195
ObjectTypeDefinitionNode typeDef,
8296
CompositeSchemaContext context)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using HotChocolate.Features;
2+
using HotChocolate.Fusion.Types.Collections;
3+
4+
namespace HotChocolate.Fusion.Types.Completion;
5+
6+
internal ref struct CompositeInputObjectTypeCompletionContext(
7+
FusionDirectiveCollection directives,
8+
IFeatureCollection features)
9+
{
10+
public FusionDirectiveCollection Directives { get; } = directives;
11+
12+
public IFeatureCollection Features { get; } = features;
13+
}

src/HotChocolate/Fusion-vnext/src/Fusion.Execution.Types/Completion/CompositeSchemaBuilder.cs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,16 @@ private static CompositeSchemaContext CreateTypes(DocumentNode schema)
4949
typeDefinitions.Add(interfaceType.Name.Value, interfaceType);
5050
break;
5151

52+
case UnionTypeDefinitionNode unionType:
53+
types.Add(CreateUnionType(unionType));
54+
typeDefinitions.Add(unionType.Name.Value, unionType);
55+
break;
56+
57+
case InputObjectTypeDefinitionNode inputObjectType:
58+
types.Add(CreateInputObjectType(inputObjectType));
59+
typeDefinitions.Add(inputObjectType.Name.Value, inputObjectType);
60+
break;
61+
5262
case ScalarTypeDefinitionNode scalarType:
5363
types.Add(CreateScalarType(scalarType));
5464
typeDefinitions.Add(scalarType.Name.Value, scalarType);
@@ -112,6 +122,23 @@ private static FusionInterfaceTypeDefinition CreateInterfaceType(
112122
CreateOutputFields(definition.Fields));
113123
}
114124

125+
private static FusionUnionTypeDefinition CreateUnionType(
126+
UnionTypeDefinitionNode definition)
127+
{
128+
return new FusionUnionTypeDefinition(
129+
definition.Name.Value,
130+
definition.Description?.Value);
131+
}
132+
133+
private static FusionInputObjectTypeDefinition CreateInputObjectType(
134+
InputObjectTypeDefinitionNode definition)
135+
{
136+
return new FusionInputObjectTypeDefinition(
137+
definition.Name.Value,
138+
definition.Description?.Value,
139+
CreateInputFields(definition.Fields));
140+
}
141+
115142
private static FusionOutputFieldDefinitionCollection CreateOutputFields(
116143
IReadOnlyList<FieldDefinitionNode> fields)
117144
{
@@ -223,6 +250,20 @@ private static FusionSchemaDefinition CompleteTypes(CompositeSchemaContext schem
223250
schemaContext);
224251
break;
225252

253+
case FusionUnionTypeDefinition unionType:
254+
CompleteUnionType(
255+
unionType,
256+
schemaContext.GetTypeDefinition<UnionTypeDefinitionNode>(unionType.Name),
257+
schemaContext);
258+
break;
259+
260+
case FusionInputObjectTypeDefinition inputObjectType:
261+
CompleteInputObjectType(
262+
inputObjectType,
263+
schemaContext.GetTypeDefinition<InputObjectTypeDefinitionNode>(inputObjectType.Name),
264+
schemaContext);
265+
break;
266+
226267
case FusionScalarTypeDefinition scalarType:
227268
CompleteScalarType(
228269
scalarType,
@@ -301,6 +342,16 @@ private static void CompleteInterfaceType(
301342
FeatureCollection.Empty));
302343
}
303344

345+
private static void CompleteUnionType(
346+
FusionUnionTypeDefinition type,
347+
UnionTypeDefinitionNode typeDef,
348+
CompositeSchemaContext schemaContext)
349+
{
350+
var directives = CompletionTools.CreateDirectiveCollection(typeDef.Directives, schemaContext);
351+
var types = CompletionTools.CreateObjectTypeCollection(typeDef.Types, schemaContext);
352+
type.Complete(new CompositeUnionTypeCompletionContext(types, directives, FeatureCollection.Empty));
353+
}
354+
304355
private static void CompleteOutputField(
305356
FusionComplexTypeDefinition declaringType,
306357
FusionOutputFieldDefinition fieldDefinition,
@@ -393,6 +444,20 @@ static IType CompleteType(
393444
}
394445
}
395446

447+
private static void CompleteInputObjectType(
448+
FusionInputObjectTypeDefinition inputObjectType,
449+
InputObjectTypeDefinitionNode inputObjectTypeDef,
450+
CompositeSchemaContext schemaContext)
451+
{
452+
foreach (var fieldDef in inputObjectTypeDef.Fields)
453+
{
454+
CompleteInputField(inputObjectType, inputObjectType.Fields[fieldDef.Name.Value], fieldDef, schemaContext);
455+
}
456+
457+
var directives = CompletionTools.CreateDirectiveCollection(inputObjectTypeDef.Directives, schemaContext);
458+
inputObjectType.Complete(new CompositeInputObjectTypeCompletionContext(directives, FeatureCollection.Empty));
459+
}
460+
396461
private static void CompleteInputField(
397462
ITypeSystemMember declaringMember,
398463
FusionInputFieldDefinition inputField,
Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
1+
using HotChocolate.Features;
2+
using HotChocolate.Fusion.Types.Collections;
3+
14
namespace HotChocolate.Fusion.Types.Completion;
25

36
internal ref struct CompositeUnionTypeCompletionContext(
4-
FusionDirective[] directives,
5-
FusionObjectTypeDefinition[] types)
7+
FusionObjectTypeDefinitionCollection types,
8+
FusionDirectiveCollection directives,
9+
IFeatureCollection features)
610
{
7-
public FusionDirective[] Directives { get; } = directives;
11+
public FusionDirectiveCollection Directives { get; } = directives;
12+
13+
public FusionObjectTypeDefinitionCollection Types { get; } = types;
814

9-
public FusionObjectTypeDefinition[] Types { get; } = types;
15+
public IFeatureCollection Features { get; } = features;
1016
}

src/HotChocolate/Fusion-vnext/src/Fusion.Execution.Types/FusionComplexTypeDefinition.cs

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,7 @@ public FusionDirectiveCollection Directives
4040
get => _directives;
4141
private protected set
4242
{
43-
if (_completed)
44-
{
45-
throw new NotSupportedException(
46-
"The type definition is sealed and cannot be modified.");
47-
}
43+
ThrowHelper.EnsureNotSealed(_completed);
4844

4945
_directives = value;
5046
}
@@ -61,11 +57,7 @@ public FusionInterfaceTypeDefinitionCollection Implements
6157
get => _implements;
6258
private protected set
6359
{
64-
if (_completed)
65-
{
66-
throw new NotSupportedException(
67-
"The type definition is sealed and cannot be modified.");
68-
}
60+
ThrowHelper.EnsureNotSealed(_completed);
6961

7062
_implements = value;
7163
}
@@ -96,11 +88,7 @@ public ISourceComplexTypeCollection<ISourceComplexType> Sources
9688
get;
9789
private protected set
9890
{
99-
if (_completed)
100-
{
101-
throw new NotSupportedException(
102-
"The type definition is sealed and cannot be modified.");
103-
}
91+
ThrowHelper.EnsureNotSealed(_completed);
10492

10593
field = value;
10694
}
@@ -123,11 +111,7 @@ private protected set
123111

124112
private protected void Complete()
125113
{
126-
if (_completed)
127-
{
128-
throw new NotSupportedException(
129-
"The type definition is sealed and cannot be modified.");
130-
}
114+
ThrowHelper.EnsureNotSealed(_completed);
131115

132116
_completed = true;
133117
}
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
using HotChocolate.Features;
2+
using HotChocolate.Fusion.Types.Collections;
3+
using HotChocolate.Fusion.Types.Completion;
4+
using HotChocolate.Language;
5+
using HotChocolate.Serialization;
6+
using HotChocolate.Types;
7+
using static HotChocolate.Fusion.Types.ThrowHelper;
8+
9+
namespace HotChocolate.Fusion.Types;
10+
11+
public sealed class FusionInputObjectTypeDefinition : IInputObjectTypeDefinition
12+
{
13+
private bool _completed;
14+
15+
public FusionInputObjectTypeDefinition(
16+
string name,
17+
string? description,
18+
FusionInputFieldDefinitionCollection fields)
19+
{
20+
Name = name;
21+
Description = description;
22+
Fields = fields;
23+
24+
// these properties are initialized
25+
// in the type complete step.
26+
Directives = null!;
27+
Features = null!;
28+
}
29+
30+
/// <inheritdoc />
31+
public TypeKind Kind => TypeKind.InputObject;
32+
33+
/// <inheritdoc />
34+
public SchemaCoordinate Coordinate => new(Name, ofDirective: false);
35+
36+
public string Name { get; }
37+
38+
public string? Description { get; }
39+
40+
public FusionInputFieldDefinitionCollection Fields { get; }
41+
42+
IReadOnlyFieldDefinitionCollection<IInputValueDefinition> IInputObjectTypeDefinition.Fields => Fields;
43+
44+
public FusionDirectiveCollection Directives
45+
{
46+
get;
47+
private set
48+
{
49+
EnsureNotSealed(_completed);
50+
field = value;
51+
}
52+
}
53+
54+
IReadOnlyDirectiveCollection IDirectivesProvider.Directives
55+
=> Directives;
56+
57+
public IFeatureCollection Features
58+
{
59+
get;
60+
private set
61+
{
62+
EnsureNotSealed(_completed);
63+
field = value;
64+
}
65+
}
66+
67+
internal void Complete(CompositeInputObjectTypeCompletionContext context)
68+
{
69+
EnsureNotSealed(_completed);
70+
71+
Directives = context.Directives;
72+
Features = context.Features;
73+
74+
_completed = true;
75+
}
76+
77+
/// <summary>
78+
/// Gets the string representation of this instance.
79+
/// </summary>
80+
/// <returns>
81+
/// The string representation of this instance.
82+
/// </returns>
83+
public override string ToString()
84+
=> SchemaDebugFormatter.Format(this).ToString(true);
85+
86+
/// <summary>
87+
/// Creates a <see cref="InputObjectTypeDefinitionNode"/>
88+
/// from a <see cref="FusionInputObjectTypeDefinition"/>.
89+
/// </summary>
90+
public InputObjectTypeDefinitionNode ToSyntaxNode()
91+
=> SchemaDebugFormatter.Format(this);
92+
93+
ISyntaxNode ISyntaxNodeProvider.ToSyntaxNode()
94+
=> SchemaDebugFormatter.Format(this);
95+
96+
/// <inheritdoc />
97+
public bool Equals(IType? other)
98+
=> Equals(other, TypeComparison.Reference);
99+
100+
public bool Equals(IType? other, TypeComparison comparison)
101+
{
102+
if (comparison is TypeComparison.Reference)
103+
{
104+
return ReferenceEquals(this, other);
105+
}
106+
107+
return other is FusionInputObjectTypeDefinition otherInputObject
108+
&& otherInputObject.Name.Equals(Name, StringComparison.Ordinal);
109+
}
110+
111+
/// <inheritdoc />
112+
public bool IsAssignableFrom(ITypeDefinition type)
113+
{
114+
if (type.Kind == TypeKind.InputObject)
115+
{
116+
return Equals(type, TypeComparison.Reference);
117+
}
118+
119+
return false;
120+
}
121+
}

0 commit comments

Comments
 (0)