-
Notifications
You must be signed in to change notification settings - Fork 49
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for OneOf input type #161
Comments
Note that querying the |
Added some new extension points that help to achieve what you need: class OneOfDirectiveGenerationContext(GraphQlSchema schema, TextWriter writer, GeneratedObjectType objectTypes = GeneratedObjectType.All, byte indentationSize = 0)
: SingleFileGenerationContext(schema, writer, objectTypes, indentationSize)
{
private readonly string _indentation = GraphQlGenerator.GetIndentation(indentationSize);
public override void OnDataClassConstructorGeneration(ObjectGenerationContext context)
{
if (!IsOneOfInput(context.GraphQlType))
return;
Writer.WriteLine($"{_indentation} private {context.CSharpTypeName}()");
Writer.WriteLine($"{_indentation} {{");
Writer.WriteLine($"{_indentation} }}");
Writer.WriteLine();
}
public override void BeforeDataPropertyGeneration(PropertyGenerationContext context) =>
context.SetterAccessibility =
IsOneOfInput(context.ObjectContext.GraphQlType)
? PropertyAccessibility.Private
: PropertyAccessibility.Public;
public override void AfterDataPropertyGeneration(PropertyGenerationContext context)
{
if (!IsOneOfInput(context.ObjectContext.GraphQlType))
return;
var parameterName = $"{Char.ToLowerInvariant(context.PropertyName[0])}{context.PropertyName[1..]}";
Writer.WriteLine($"{_indentation} public static {context.ObjectContext.CSharpTypeName} From{context.PropertyName}({context.PropertyCSharpTypeName} {parameterName})");
Writer.WriteLine($"{_indentation} => new() {{ {context.PropertyName} = {parameterName} }};");
Writer.WriteLine();
}
private static bool IsOneOfInput(GraphQlType graphQlType)
{
// TODO: use graphQlType.Extensions to determine if the type is annotaded with @oneOf
}
}
var generator = new GraphQlGenerator(configuration);
var builder = new StringBuilder();
using var writer = new StringWriter(builder);
generator.Generate(new OneOfDirectiveGenerationContext(schema, writer, GeneratedObjectType.All, 0)); |
Hey @Husqvik, sorry for the late response. Will try it next week. Thank you! |
Hey @Husqvik. I'm trying to sync your repo with our private fork to try out the solution, but I encountered a couple of problems:
isTypeNotNull ? null : "?" Otherwise, it generates the wrong enum nullability in
WARNING: duplicate union "DereferenceValue" possible type "User"
WARNING: duplicate union "DereferenceValue" possible type "UsersGroup"
WARNING: duplicate union "Identity" possible type "User"
WARNING: duplicate union "Identity" possible type "UsersGroup"
WARNING: duplicate union "NotificationSubscriptionIdentity" possible type "User"
WARNING: duplicate union "NotificationSubscriptionIdentity" possible type "UsersGroup" Also, the generated types don't implement all the union interfaces. See what we had with our private implementation and what we have with the latest code - public class User : IAssignee, IDereferenceValue, IIdentity, INotificationSubscriptionIdentity
+ public class User : IAssignee
- public class UsersGroup : IAssignee, IDereferenceValue, IIdentity, INotificationSubscriptionIdentity
+ public class UsersGroup : IAssignee
|
|
This is not a duplicate but a legal use case. Consider these union definitions union Assignee = User | UsersGroup
union NotificationSubscriptionIdentity = User | UsersGroup | Department Both GraphQlClientGenerator/src/GraphQlClientGenerator/GenerationContext.cs Lines 489 to 497 in fb7f360
|
Ok fixed that one too. I encountered a real duplicate within single UNION possible types from some server. |
Yeah, that works too. Thanks! |
Is there anything left open on this issue? |
I didn't test the extension points yet, sorry. Will test it tomorrow and reply. |
I checked the extension points. Unfortunately, to use |
Moved the generation part from |
That did the job! Thanks! public class OneOfDirectiveGenerationContext(GraphQlSchema schema, TextWriter writer, string @namespace, GeneratedObjectType objectTypes = GeneratedObjectType.All)
: SingleFileGenerationContext(schema, writer, @namespace, objectTypes)
{
private string Indentation => GraphQlGenerator.GetIndentation(IndentationSize);
public override void OnDataClassConstructorGeneration(ObjectGenerationContext context)
{
if (!IsOneOfInput(context.GraphQlType))
return;
Writer.WriteLine($"{Indentation} private {context.CSharpTypeName}()");
Writer.WriteLine($"{Indentation} {{");
Writer.WriteLine($"{Indentation} }}");
Writer.WriteLine();
}
public override void BeforeDataPropertyGeneration(PropertyGenerationContext context) =>
context.SetterAccessibility =
IsOneOfInput(context.ObjectContext.GraphQlType)
? PropertyAccessibility.Private
: PropertyAccessibility.Public;
public override void AfterDataPropertyGeneration(PropertyGenerationContext context)
{
if (!IsOneOfInput(context.ObjectContext.GraphQlType))
return;
var parameterName = $"{char.ToLowerInvariant(context.PropertyName[0])}{context.PropertyName[1..]}";
Writer.WriteLine($"{Indentation} public static {context.ObjectContext.CSharpTypeName} From{context.PropertyName}({context.PropertyCSharpTypeName} {parameterName})");
Writer.WriteLine($"{Indentation} => new() {{ {context.PropertyName} = {parameterName} }};");
Writer.WriteLine();
}
private static bool IsOneOfInput(GraphQlType graphQlType)
{
return graphQlType.Extensions.TryGetValue("isOneOf", out var isOneOf)
&& isOneOf is true;
}
} |
This is a request to add support for OneOf Input Objects. Note that even though this is still in draft, many graphql servers already implement this feature, and it will be merged without further changes. Implementing this feature requires adding the
isOneOf
field under theFullType
fragment in the introspection query.Simple Sdl schema for example (note the
@oneOf
onUserSearchCriteriaInput
):Introspection result
Note the
"isOneOf": true
underUserSearchCriteriaInput
typeWhat's the expected result?
I expect the generator to create a type that can be instantiated by providing one and only one of the possible fields. For example, using static factory methods:
The text was updated successfully, but these errors were encountered: