diff --git a/src/HotChocolate/Core/src/Execution.Projections/Extensions/HotChocolateExecutionSelectionExtensions.cs b/src/HotChocolate/Core/src/Execution.Projections/Extensions/HotChocolateExecutionSelectionExtensions.cs index 652dedfb075..3edbb876545 100644 --- a/src/HotChocolate/Core/src/Execution.Projections/Extensions/HotChocolateExecutionSelectionExtensions.cs +++ b/src/HotChocolate/Core/src/Execution.Projections/Extensions/HotChocolateExecutionSelectionExtensions.cs @@ -40,6 +40,24 @@ public static Expression> AsSelector( return AsSelector(casted); } + /// + /// Creates a selector expression from a GraphQL selection and applies + /// runtime include/skip directive flags. + /// + public static Expression> AsSelector( + this ISelection selection, + ulong includeFlags) + { + if (selection is not Selection casted) + { + throw new ArgumentException( + $"Expected {typeof(Selection).FullName!}.", + nameof(selection)); + } + + return AsSelector(casted, includeFlags); + } + /// /// Creates a selector expression from a GraphQL selection. /// @@ -54,10 +72,17 @@ public static Expression> AsSelector( /// public static Expression> AsSelector( this Selection selection) + => AsSelector(selection, 0); + + public static Expression> AsSelector( + this Selection selection, + ulong includeFlags) { + var isConditional = selection.DeclaringOperation.RootSelectionSet.IsConditional; + // we first check if we already have an expression for this selection, // this would be the cheapest way to get the expression. - if (TryGetExpression(selection, out var expression)) + if (!isConditional && TryGetExpression(selection, out var expression)) { return expression; } @@ -74,10 +99,15 @@ public static Expression> AsSelector( var count = GetConnectionSelections(selection, buffer); for (var i = 0; i < count; i++) { - builder.Add(buffer[i].GetOrCreateExpression()); + builder.Add( + isConditional + ? buffer[i].GetExpression(includeFlags) + : buffer[i].GetOrCreateExpression()); } ArrayPool.Shared.Return(buffer); - return selection.GetOrCreateExpression(builder); + return isConditional + ? selection.GetExpression(builder) + : selection.GetOrCreateExpression(builder); } if ((flags & CoreFieldFlags.CollectionSegment) == CoreFieldFlags.CollectionSegment) @@ -87,19 +117,28 @@ public static Expression> AsSelector( var count = GetCollectionSelections(selection, buffer); for (var i = 0; i < count; i++) { - builder.Add(buffer[i].GetOrCreateExpression()); + builder.Add( + isConditional + ? buffer[i].GetExpression(includeFlags) + : buffer[i].GetOrCreateExpression()); } ArrayPool.Shared.Return(buffer); - return selection.GetOrCreateExpression(builder); + return isConditional + ? selection.GetExpression(builder) + : selection.GetOrCreateExpression(builder); } if ((flags & CoreFieldFlags.GlobalIdNodeField) == CoreFieldFlags.GlobalIdNodeField || (flags & CoreFieldFlags.GlobalIdNodesField) == CoreFieldFlags.GlobalIdNodesField) { - return selection.GetOrCreateNodeExpression(); + return isConditional + ? selection.GetNodeExpression(includeFlags) + : selection.GetOrCreateNodeExpression(); } - return selection.GetOrCreateExpression(); + return isConditional + ? selection.GetExpression(includeFlags) + : selection.GetOrCreateExpression(); } private static bool TryGetExpression( @@ -179,10 +218,19 @@ file static class Extensions public Expression> GetOrCreateExpression() => selection.Features.GetOrSetSafe(() => s_builder.BuildExpression(selection)); + public Expression> GetExpression(ulong includeFlags) + => s_builder.BuildExpression(selection, includeFlags); + public Expression> GetOrCreateExpression(ISelectorBuilder expressionBuilder) => selection.Features.GetOrSetSafe(() => expressionBuilder.TryCompile()!); + public Expression> GetExpression(ISelectorBuilder expressionBuilder) + => expressionBuilder.TryCompile()!; + public Expression> GetOrCreateNodeExpression() => selection.Features.GetOrSetSafe(() => s_builder.BuildNodeExpression(selection)); + + public Expression> GetNodeExpression(ulong includeFlags) + => s_builder.BuildNodeExpression(selection, includeFlags); } } diff --git a/src/HotChocolate/Core/src/Execution.Projections/SelectionExpressionBuilder.cs b/src/HotChocolate/Core/src/Execution.Projections/SelectionExpressionBuilder.cs index 2e511cff998..7bd1728467c 100644 --- a/src/HotChocolate/Core/src/Execution.Projections/SelectionExpressionBuilder.cs +++ b/src/HotChocolate/Core/src/Execution.Projections/SelectionExpressionBuilder.cs @@ -36,12 +36,14 @@ internal sealed class SelectionExpressionBuilder typeof(char?) ]; - public Expression> BuildExpression(Selection selection) + public Expression> BuildExpression( + Selection selection, + ulong includeFlags = 0) { var rootType = typeof(TRoot); var parameter = Expression.Parameter(rootType, "root"); var requirements = selection.DeclaringOperation.Schema.Features.GetRequired(); - var context = new Context(parameter, rootType, requirements, new NullabilityInfoContext()); + var context = new Context(parameter, rootType, requirements, new NullabilityInfoContext(), includeFlags); var root = new TypeContainer(); CollectTypes(context, selection, root); @@ -56,12 +58,14 @@ public Expression> BuildExpression(Selection selection return Expression.Lambda>(selectionSetExpression, parameter); } - public Expression> BuildNodeExpression(Selection selection) + public Expression> BuildNodeExpression( + Selection selection, + ulong includeFlags = 0) { var rootType = typeof(TRoot); var parameter = Expression.Parameter(rootType, "root"); var requirements = selection.DeclaringOperation.Schema.Features.GetRequired(); - var context = new Context(parameter, rootType, requirements, new NullabilityInfoContext()); + var context = new Context(parameter, rootType, requirements, new NullabilityInfoContext(), includeFlags); var root = new TypeContainer(); var entityType = selection.DeclaringOperation @@ -272,6 +276,11 @@ private void CollectSelections( { foreach (var selection in selectionSet.Selections) { + if (!selection.IsIncluded(context.IncludeFlags)) + { + continue; + } + var requirements = context.GetRequirements(selection); if (requirements is not null) { @@ -342,7 +351,8 @@ private readonly record struct Context( Expression Parent, Type ParentType, FieldRequirementsMetadata Requirements, - NullabilityInfoContext NullabilityInfoContext) + NullabilityInfoContext NullabilityInfoContext, + ulong IncludeFlags) { public TypeNode? GetRequirements(Selection selection) { diff --git a/src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/TypeFileBuilderBase.cs b/src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/TypeFileBuilderBase.cs index b116bbde798..5c17de7f8b1 100644 --- a/src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/TypeFileBuilderBase.cs +++ b/src/HotChocolate/Core/src/Types.Analyzers/FileBuilders/TypeFileBuilderBase.cs @@ -1210,7 +1210,7 @@ private void WriteResolverArguments(Resolver resolver, IMethodSymbol resolverMet using (Writer.IncreaseIndent()) { Writer.WriteIndentedLine( - "global::{0}.AsSelector<{1}>(args{2}_selection),", + "global::{0}.AsSelector<{1}>(args{2}_selection, context.IncludeFlags),", WellKnownTypes.HotChocolateExecutionSelectionExtensions, entityType, i); diff --git a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/NodeResolverIdParameterAnalyzerTests.FirstParameter_NamedId_NoError.md b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/NodeResolverIdParameterAnalyzerTests.FirstParameter_NamedId_NoError.md index 2e053667a16..ad43bec8f35 100644 --- a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/NodeResolverIdParameterAnalyzerTests.FirstParameter_NamedId_NoError.md +++ b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/NodeResolverIdParameterAnalyzerTests.FirstParameter_NamedId_NoError.md @@ -95,7 +95,7 @@ namespace TestNamespace var args2_filter = global::HotChocolate.Data.Filters.FilterContextResolverContextExtensions.GetFilterContext(context); var args2_sorting = global::HotChocolate.Data.Sorting.SortingContextResolverContextExtensions.GetSortingContext(context); var args2 = new global::GreenDonut.Data.QueryContext( - global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args2_selection), + global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args2_selection, context.IncludeFlags), args2_filter?.AsPredicate(), args2_sorting?.AsSortDefinition()); var args3 = context.RequestAborted; diff --git a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/NodeResolverIdParameterAnalyzerTests.FirstParameter_NamedId_WithString_NoError.md b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/NodeResolverIdParameterAnalyzerTests.FirstParameter_NamedId_WithString_NoError.md index 2c1bf62f24f..82abbc70f04 100644 --- a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/NodeResolverIdParameterAnalyzerTests.FirstParameter_NamedId_WithString_NoError.md +++ b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/NodeResolverIdParameterAnalyzerTests.FirstParameter_NamedId_WithString_NoError.md @@ -95,7 +95,7 @@ namespace TestNamespace var args2_filter = global::HotChocolate.Data.Filters.FilterContextResolverContextExtensions.GetFilterContext(context); var args2_sorting = global::HotChocolate.Data.Sorting.SortingContextResolverContextExtensions.GetSortingContext(context); var args2 = new global::GreenDonut.Data.QueryContext( - global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args2_selection), + global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args2_selection, context.IncludeFlags), args2_filter?.AsPredicate(), args2_sorting?.AsSortDefinition()); var args3 = context.RequestAborted; diff --git a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/NodeResolverIdParameterAnalyzerTests.FirstParameter_NotNamedId_NoFixableParameter_RaisesError.md b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/NodeResolverIdParameterAnalyzerTests.FirstParameter_NotNamedId_NoFixableParameter_RaisesError.md index 63197fa69d5..cec4af85bcc 100644 --- a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/NodeResolverIdParameterAnalyzerTests.FirstParameter_NotNamedId_NoFixableParameter_RaisesError.md +++ b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/NodeResolverIdParameterAnalyzerTests.FirstParameter_NotNamedId_NoFixableParameter_RaisesError.md @@ -94,7 +94,7 @@ namespace TestNamespace var args1_filter = global::HotChocolate.Data.Filters.FilterContextResolverContextExtensions.GetFilterContext(context); var args1_sorting = global::HotChocolate.Data.Sorting.SortingContextResolverContextExtensions.GetSortingContext(context); var args1 = new global::GreenDonut.Data.QueryContext( - global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args1_selection), + global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args1_selection, context.IncludeFlags), args1_filter?.AsPredicate(), args1_sorting?.AsSortDefinition()); var args2 = context.RequestAborted; diff --git a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/NodeResolverIdParameterAnalyzerTests.GuidIdParameter_NotInFirstPosition_RaisesError.md b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/NodeResolverIdParameterAnalyzerTests.GuidIdParameter_NotInFirstPosition_RaisesError.md index d2df904194c..139c7bc8227 100644 --- a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/NodeResolverIdParameterAnalyzerTests.GuidIdParameter_NotInFirstPosition_RaisesError.md +++ b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/NodeResolverIdParameterAnalyzerTests.GuidIdParameter_NotInFirstPosition_RaisesError.md @@ -103,7 +103,7 @@ namespace TestNamespace var args2_filter = global::HotChocolate.Data.Filters.FilterContextResolverContextExtensions.GetFilterContext(context); var args2_sorting = global::HotChocolate.Data.Sorting.SortingContextResolverContextExtensions.GetSortingContext(context); var args2 = new global::GreenDonut.Data.QueryContext( - global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args2_selection), + global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args2_selection, context.IncludeFlags), args2_filter?.AsPredicate(), args2_sorting?.AsSortDefinition()); var args3 = context.RequestAborted; diff --git a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/NodeResolverIdParameterAnalyzerTests.IdParameter_NotInFirstPosition_RaisesError.md b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/NodeResolverIdParameterAnalyzerTests.IdParameter_NotInFirstPosition_RaisesError.md index 4362cac1db4..9d2b311c38b 100644 --- a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/NodeResolverIdParameterAnalyzerTests.IdParameter_NotInFirstPosition_RaisesError.md +++ b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/NodeResolverIdParameterAnalyzerTests.IdParameter_NotInFirstPosition_RaisesError.md @@ -95,7 +95,7 @@ namespace TestNamespace var args2_filter = global::HotChocolate.Data.Filters.FilterContextResolverContextExtensions.GetFilterContext(context); var args2_sorting = global::HotChocolate.Data.Sorting.SortingContextResolverContextExtensions.GetSortingContext(context); var args2 = new global::GreenDonut.Data.QueryContext( - global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args2_selection), + global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args2_selection, context.IncludeFlags), args2_filter?.AsPredicate(), args2_sorting?.AsSortDefinition()); var args3 = context.RequestAborted; diff --git a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/NodeResolverIdParameterAnalyzerTests.MethodWithoutNodeResolver_NoError.md b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/NodeResolverIdParameterAnalyzerTests.MethodWithoutNodeResolver_NoError.md index af1245579f5..4006b645056 100644 --- a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/NodeResolverIdParameterAnalyzerTests.MethodWithoutNodeResolver_NoError.md +++ b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/NodeResolverIdParameterAnalyzerTests.MethodWithoutNodeResolver_NoError.md @@ -154,7 +154,7 @@ namespace TestNamespace var args2_filter = global::HotChocolate.Data.Filters.FilterContextResolverContextExtensions.GetFilterContext(context); var args2_sorting = global::HotChocolate.Data.Sorting.SortingContextResolverContextExtensions.GetSortingContext(context); var args2 = new global::GreenDonut.Data.QueryContext( - global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args2_selection), + global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args2_selection, context.IncludeFlags), args2_filter?.AsPredicate(), args2_sorting?.AsSortDefinition()); var args3 = context.RequestAborted; diff --git a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/NodeResolverIdParameterAnalyzerTests.ParameterEndingWithId_NotInFirstPosition_RaisesError.md b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/NodeResolverIdParameterAnalyzerTests.ParameterEndingWithId_NotInFirstPosition_RaisesError.md index ec524ee1f4a..ffcab2fc4fb 100644 --- a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/NodeResolverIdParameterAnalyzerTests.ParameterEndingWithId_NotInFirstPosition_RaisesError.md +++ b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/NodeResolverIdParameterAnalyzerTests.ParameterEndingWithId_NotInFirstPosition_RaisesError.md @@ -103,7 +103,7 @@ namespace TestNamespace var args2_filter = global::HotChocolate.Data.Filters.FilterContextResolverContextExtensions.GetFilterContext(context); var args2_sorting = global::HotChocolate.Data.Sorting.SortingContextResolverContextExtensions.GetSortingContext(context); var args2 = new global::GreenDonut.Data.QueryContext( - global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args2_selection), + global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args2_selection, context.IncludeFlags), args2_filter?.AsPredicate(), args2_sorting?.AsSortDefinition()); var args3 = context.RequestAborted; diff --git a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/NodeResolverIdParameterAnalyzerTests.StringIdParameter_NotInFirstPosition_RaisesError.md b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/NodeResolverIdParameterAnalyzerTests.StringIdParameter_NotInFirstPosition_RaisesError.md index 2e94f375e9f..45d2c3dfc49 100644 --- a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/NodeResolverIdParameterAnalyzerTests.StringIdParameter_NotInFirstPosition_RaisesError.md +++ b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/NodeResolverIdParameterAnalyzerTests.StringIdParameter_NotInFirstPosition_RaisesError.md @@ -103,7 +103,7 @@ namespace TestNamespace var args2_filter = global::HotChocolate.Data.Filters.FilterContextResolverContextExtensions.GetFilterContext(context); var args2_sorting = global::HotChocolate.Data.Sorting.SortingContextResolverContextExtensions.GetSortingContext(context); var args2 = new global::GreenDonut.Data.QueryContext( - global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args2_selection), + global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args2_selection, context.IncludeFlags), args2_filter?.AsPredicate(), args2_sorting?.AsSortDefinition()); var args3 = context.RequestAborted; diff --git a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/OperationTests.Root_Projection_Single_Entity.md b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/OperationTests.Root_Projection_Single_Entity.md index 7e82144e28e..06fbaef2ea8 100644 --- a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/OperationTests.Root_Projection_Single_Entity.md +++ b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/OperationTests.Root_Projection_Single_Entity.md @@ -111,7 +111,7 @@ namespace TestNamespace var args0_filter = global::HotChocolate.Data.Filters.FilterContextResolverContextExtensions.GetFilterContext(context); var args0_sorting = global::HotChocolate.Data.Sorting.SortingContextResolverContextExtensions.GetSortingContext(context); var args0 = new global::GreenDonut.Data.QueryContext( - global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args0_selection), + global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args0_selection, context.IncludeFlags), args0_filter?.AsPredicate(), args0_sorting?.AsSortDefinition()); var result = global::TestNamespace.Query.GetTest(args0); diff --git a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextConnectionAnalyzerTests.CorrectGenericTypeMatch_NoError.md b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextConnectionAnalyzerTests.CorrectGenericTypeMatch_NoError.md index 1886873d4ec..7411cd19c2a 100644 --- a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextConnectionAnalyzerTests.CorrectGenericTypeMatch_NoError.md +++ b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextConnectionAnalyzerTests.CorrectGenericTypeMatch_NoError.md @@ -446,7 +446,7 @@ namespace TestNamespace var args1_filter = global::HotChocolate.Data.Filters.FilterContextResolverContextExtensions.GetFilterContext(context); var args1_sorting = global::HotChocolate.Data.Sorting.SortingContextResolverContextExtensions.GetSortingContext(context); var args1 = new global::GreenDonut.Data.QueryContext( - global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args1_selection), + global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args1_selection, context.IncludeFlags), args1_filter?.AsPredicate(), args1_sorting?.AsSortDefinition()); var args2 = _binding_GetProductsAsync_productService.Execute(context); diff --git a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextConnectionAnalyzerTests.CorrectGenericTypeMatch_WithConnection_NoError.md b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextConnectionAnalyzerTests.CorrectGenericTypeMatch_WithConnection_NoError.md index c5a6409a6b9..16e352f3f5c 100644 --- a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextConnectionAnalyzerTests.CorrectGenericTypeMatch_WithConnection_NoError.md +++ b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextConnectionAnalyzerTests.CorrectGenericTypeMatch_WithConnection_NoError.md @@ -163,7 +163,7 @@ namespace TestNamespace var args1_filter = global::HotChocolate.Data.Filters.FilterContextResolverContextExtensions.GetFilterContext(context); var args1_sorting = global::HotChocolate.Data.Sorting.SortingContextResolverContextExtensions.GetSortingContext(context); var args1 = new global::GreenDonut.Data.QueryContext( - global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args1_selection), + global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args1_selection, context.IncludeFlags), args1_filter?.AsPredicate(), args1_sorting?.AsSortDefinition()); var args2 = _binding_GetProductsAsync_productService.Execute(context); diff --git a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextConnectionAnalyzerTests.NoConnectionReturnType_NoError.md b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextConnectionAnalyzerTests.NoConnectionReturnType_NoError.md index 12bb63ac7b5..5d161cd1e32 100644 --- a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextConnectionAnalyzerTests.NoConnectionReturnType_NoError.md +++ b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextConnectionAnalyzerTests.NoConnectionReturnType_NoError.md @@ -130,7 +130,7 @@ namespace TestNamespace var args0_filter = global::HotChocolate.Data.Filters.FilterContextResolverContextExtensions.GetFilterContext(context); var args0_sorting = global::HotChocolate.Data.Sorting.SortingContextResolverContextExtensions.GetSortingContext(context); var args0 = new global::GreenDonut.Data.QueryContext( - global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args0_selection), + global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args0_selection, context.IncludeFlags), args0_filter?.AsPredicate(), args0_sorting?.AsSortDefinition()); var args1 = _binding_GetProductsAsync_productService.Execute(context); diff --git a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextConnectionAnalyzerTests.TypeMismatch_WithConnection_RaisesError.md b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextConnectionAnalyzerTests.TypeMismatch_WithConnection_RaisesError.md index 58c087abe60..56176c0ec32 100644 --- a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextConnectionAnalyzerTests.TypeMismatch_WithConnection_RaisesError.md +++ b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextConnectionAnalyzerTests.TypeMismatch_WithConnection_RaisesError.md @@ -163,7 +163,7 @@ namespace TestNamespace var args1_filter = global::HotChocolate.Data.Filters.FilterContextResolverContextExtensions.GetFilterContext(context); var args1_sorting = global::HotChocolate.Data.Sorting.SortingContextResolverContextExtensions.GetSortingContext(context); var args1 = new global::GreenDonut.Data.QueryContext( - global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args1_selection), + global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args1_selection, context.IncludeFlags), args1_filter?.AsPredicate(), args1_sorting?.AsSortDefinition()); var args2 = _binding_GetProductsAsync_productService.Execute(context); diff --git a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextConnectionAnalyzerTests.TypeMismatch_WithInterfaceType_RaisesError.md b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextConnectionAnalyzerTests.TypeMismatch_WithInterfaceType_RaisesError.md index 54d70cbad34..f8c241add77 100644 --- a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextConnectionAnalyzerTests.TypeMismatch_WithInterfaceType_RaisesError.md +++ b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextConnectionAnalyzerTests.TypeMismatch_WithInterfaceType_RaisesError.md @@ -163,7 +163,7 @@ namespace TestNamespace var args1_filter = global::HotChocolate.Data.Filters.FilterContextResolverContextExtensions.GetFilterContext(context); var args1_sorting = global::HotChocolate.Data.Sorting.SortingContextResolverContextExtensions.GetSortingContext(context); var args1 = new global::GreenDonut.Data.QueryContext( - global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args1_selection), + global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args1_selection, context.IncludeFlags), args1_filter?.AsPredicate(), args1_sorting?.AsSortDefinition()); var args2 = _binding_GetProductsAsync_productService.Execute(context); diff --git a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextConnectionAnalyzerTests.TypeMismatch_WithMutationType_RaisesError.md b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextConnectionAnalyzerTests.TypeMismatch_WithMutationType_RaisesError.md index 60bb6b7b20f..5e521c7ce31 100644 --- a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextConnectionAnalyzerTests.TypeMismatch_WithMutationType_RaisesError.md +++ b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextConnectionAnalyzerTests.TypeMismatch_WithMutationType_RaisesError.md @@ -179,7 +179,7 @@ namespace TestNamespace var args1_filter = global::HotChocolate.Data.Filters.FilterContextResolverContextExtensions.GetFilterContext(context); var args1_sorting = global::HotChocolate.Data.Sorting.SortingContextResolverContextExtensions.GetSortingContext(context); var args1 = new global::GreenDonut.Data.QueryContext( - global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args1_selection), + global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args1_selection, context.IncludeFlags), args1_filter?.AsPredicate(), args1_sorting?.AsSortDefinition()); var args2 = _binding_AddProductsAsync_productService.Execute(context); diff --git a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextConnectionAnalyzerTests.TypeMismatch_WithObjectType_RaisesError.md b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextConnectionAnalyzerTests.TypeMismatch_WithObjectType_RaisesError.md index ed56eba0d9b..baafb279918 100644 --- a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextConnectionAnalyzerTests.TypeMismatch_WithObjectType_RaisesError.md +++ b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextConnectionAnalyzerTests.TypeMismatch_WithObjectType_RaisesError.md @@ -446,7 +446,7 @@ namespace TestNamespace var args1_filter = global::HotChocolate.Data.Filters.FilterContextResolverContextExtensions.GetFilterContext(context); var args1_sorting = global::HotChocolate.Data.Sorting.SortingContextResolverContextExtensions.GetSortingContext(context); var args1 = new global::GreenDonut.Data.QueryContext( - global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args1_selection), + global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args1_selection, context.IncludeFlags), args1_filter?.AsPredicate(), args1_sorting?.AsSortDefinition()); var args2 = _binding_GetProductsAsync_productService.Execute(context); diff --git a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextConnectionAnalyzerTests.TypeMismatch_WithQueryType_RaisesError.md b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextConnectionAnalyzerTests.TypeMismatch_WithQueryType_RaisesError.md index 3b102cfc5ab..6f85410313a 100644 --- a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextConnectionAnalyzerTests.TypeMismatch_WithQueryType_RaisesError.md +++ b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextConnectionAnalyzerTests.TypeMismatch_WithQueryType_RaisesError.md @@ -458,7 +458,7 @@ namespace TestNamespace var args1_filter = global::HotChocolate.Data.Filters.FilterContextResolverContextExtensions.GetFilterContext(context); var args1_sorting = global::HotChocolate.Data.Sorting.SortingContextResolverContextExtensions.GetSortingContext(context); var args1 = new global::GreenDonut.Data.QueryContext( - global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args1_selection), + global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args1_selection, context.IncludeFlags), args1_filter?.AsPredicate(), args1_sorting?.AsSortDefinition()); var args2 = _binding_GetProductsAsync_productService.Execute(context); diff --git a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextConnectionAnalyzerTests.TypeMismatch_WithSubscriptionType_RaisesError.md b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextConnectionAnalyzerTests.TypeMismatch_WithSubscriptionType_RaisesError.md index c65b0067825..4955e7a7d8a 100644 --- a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextConnectionAnalyzerTests.TypeMismatch_WithSubscriptionType_RaisesError.md +++ b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextConnectionAnalyzerTests.TypeMismatch_WithSubscriptionType_RaisesError.md @@ -458,7 +458,7 @@ namespace TestNamespace var args1_filter = global::HotChocolate.Data.Filters.FilterContextResolverContextExtensions.GetFilterContext(context); var args1_sorting = global::HotChocolate.Data.Sorting.SortingContextResolverContextExtensions.GetSortingContext(context); var args1 = new global::GreenDonut.Data.QueryContext( - global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args1_selection), + global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args1_selection, context.IncludeFlags), args1_filter?.AsPredicate(), args1_sorting?.AsSortDefinition()); var args2 = _binding_OnProductAddedAsync_productService.Execute(context); diff --git a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextProjectionAnalyzerTests.QueryContext_MultipleAttributes_OnlyUseProjectionFlagged.md b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextProjectionAnalyzerTests.QueryContext_MultipleAttributes_OnlyUseProjectionFlagged.md index 6dde5f7b7ed..68afee3c0f2 100644 --- a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextProjectionAnalyzerTests.QueryContext_MultipleAttributes_OnlyUseProjectionFlagged.md +++ b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextProjectionAnalyzerTests.QueryContext_MultipleAttributes_OnlyUseProjectionFlagged.md @@ -185,7 +185,7 @@ namespace TestNamespace var args1_filter = global::HotChocolate.Data.Filters.FilterContextResolverContextExtensions.GetFilterContext(context); var args1_sorting = global::HotChocolate.Data.Sorting.SortingContextResolverContextExtensions.GetSortingContext(context); var args1 = new global::GreenDonut.Data.QueryContext( - global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args1_selection), + global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args1_selection, context.IncludeFlags), args1_filter?.AsPredicate(), args1_sorting?.AsSortDefinition()); var args2 = _binding_GetProductsAsync_productService.Execute(context); diff --git a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextProjectionAnalyzerTests.QueryContext_WithUseProjection_RaisesError.md b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextProjectionAnalyzerTests.QueryContext_WithUseProjection_RaisesError.md index badfbcf403a..690abdf1b93 100644 --- a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextProjectionAnalyzerTests.QueryContext_WithUseProjection_RaisesError.md +++ b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextProjectionAnalyzerTests.QueryContext_WithUseProjection_RaisesError.md @@ -185,7 +185,7 @@ namespace TestNamespace var args1_filter = global::HotChocolate.Data.Filters.FilterContextResolverContextExtensions.GetFilterContext(context); var args1_sorting = global::HotChocolate.Data.Sorting.SortingContextResolverContextExtensions.GetSortingContext(context); var args1 = new global::GreenDonut.Data.QueryContext( - global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args1_selection), + global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args1_selection, context.IncludeFlags), args1_filter?.AsPredicate(), args1_sorting?.AsSortDefinition()); var args2 = _binding_GetProductsAsync_productService.Execute(context); diff --git a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextProjectionAnalyzerTests.QueryContext_WithUseProjections_RaisesError.md b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextProjectionAnalyzerTests.QueryContext_WithUseProjections_RaisesError.md index 37c143d71a8..728d03e07e0 100644 --- a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextProjectionAnalyzerTests.QueryContext_WithUseProjections_RaisesError.md +++ b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextProjectionAnalyzerTests.QueryContext_WithUseProjections_RaisesError.md @@ -184,7 +184,7 @@ namespace TestNamespace var args1_filter = global::HotChocolate.Data.Filters.FilterContextResolverContextExtensions.GetFilterContext(context); var args1_sorting = global::HotChocolate.Data.Sorting.SortingContextResolverContextExtensions.GetSortingContext(context); var args1 = new global::GreenDonut.Data.QueryContext( - global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args1_selection), + global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args1_selection, context.IncludeFlags), args1_filter?.AsPredicate(), args1_sorting?.AsSortDefinition()); var args2 = _binding_GetProductsAsync_productService.Execute(context); diff --git a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextProjectionAnalyzerTests.QueryContext_WithoutUseProjection_NoError.md b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextProjectionAnalyzerTests.QueryContext_WithoutUseProjection_NoError.md index ae328281a47..68a4f7ca826 100644 --- a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextProjectionAnalyzerTests.QueryContext_WithoutUseProjection_NoError.md +++ b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/QueryContextProjectionAnalyzerTests.QueryContext_WithoutUseProjection_NoError.md @@ -184,7 +184,7 @@ namespace TestNamespace var args1_filter = global::HotChocolate.Data.Filters.FilterContextResolverContextExtensions.GetFilterContext(context); var args1_sorting = global::HotChocolate.Data.Sorting.SortingContextResolverContextExtensions.GetSortingContext(context); var args1 = new global::GreenDonut.Data.QueryContext( - global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args1_selection), + global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args1_selection, context.IncludeFlags), args1_filter?.AsPredicate(), args1_sorting?.AsSortDefinition()); var args2 = _binding_GetProductsAsync_productService.Execute(context); diff --git a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/ResolverTests.Inject_QueryContext.md b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/ResolverTests.Inject_QueryContext.md index b299aa9e43a..566ee5ebcf0 100644 --- a/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/ResolverTests.Inject_QueryContext.md +++ b/src/HotChocolate/Core/test/Types.Analyzers.Tests/__snapshots__/ResolverTests.Inject_QueryContext.md @@ -98,7 +98,7 @@ namespace TestNamespace var args0_filter = global::HotChocolate.Data.Filters.FilterContextResolverContextExtensions.GetFilterContext(context); var args0_sorting = global::HotChocolate.Data.Sorting.SortingContextResolverContextExtensions.GetSortingContext(context); var args0 = new global::GreenDonut.Data.QueryContext( - global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args0_selection), + global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector(args0_selection, context.IncludeFlags), args0_filter?.AsPredicate(), args0_sorting?.AsSortDefinition()); var result = global::TestNamespace.TestType.GetTest(args0); diff --git a/src/HotChocolate/Data/src/Data/QueryContextParameterExpressionBuilder.cs b/src/HotChocolate/Data/src/Data/QueryContextParameterExpressionBuilder.cs index 1a0959f1335..afb818a5ff6 100644 --- a/src/HotChocolate/Data/src/Data/QueryContextParameterExpressionBuilder.cs +++ b/src/HotChocolate/Data/src/Data/QueryContextParameterExpressionBuilder.cs @@ -84,7 +84,7 @@ private static QueryContext CreateQueryContext(IResolverContext context) var sortContext = context.GetSortingContext(); return new QueryContext( - selection.AsSelector(), + selection.AsSelector(context.IncludeFlags), filterContext?.AsPredicate(), sortContext?.AsSortDefinition()); } diff --git a/src/HotChocolate/Data/test/Data.Tests/IntegrationTests.cs b/src/HotChocolate/Data/test/Data.Tests/IntegrationTests.cs index 90fd097c207..64cb788fa7c 100644 --- a/src/HotChocolate/Data/test/Data.Tests/IntegrationTests.cs +++ b/src/HotChocolate/Data/test/Data.Tests/IntegrationTests.cs @@ -960,6 +960,113 @@ public async Task AsSortDefinition_Descending_QueryContext_2() result.MatchSnapshot(); } + [Fact] + public async Task QueryContext_Selector_Respects_Include_Directive() + { + // arrange + var executor = await new ServiceCollection() + .AddGraphQL() + .AddFiltering() + .AddSorting() + .AddProjections() + .AddQueryType() + .BuildRequestExecutorAsync(); + + // act + var result = await executor.ExecuteAsync( + """ + { + conditionalAuthors { + id + name @include(if: false) + } + } + """); + + // assert + result.MatchSnapshot(); + } + + [Fact] + public async Task QueryContext_Selector_Respects_Skip_Directive() + { + // arrange + var executor = await new ServiceCollection() + .AddGraphQL() + .AddFiltering() + .AddSorting() + .AddProjections() + .AddQueryType() + .BuildRequestExecutorAsync(); + + // act + var result = await executor.ExecuteAsync( + """ + { + conditionalAuthors { + id + name @skip(if: true) + } + } + """); + + // assert + result.MatchSnapshot(); + } + + [Fact] + public async Task QueryContext_Selector_Respects_Variable_Include_Directive_Across_Requests() + { + // arrange + var executor = await new ServiceCollection() + .AddGraphQL() + .AddFiltering() + .AddSorting() + .AddProjections() + .AddQueryType() + .BuildRequestExecutorAsync(); + + const string query = + """ + query Test($withName: Boolean!, $empty: Boolean!) { + conditionalAuthors(empty: $empty) { + id + name @include(if: $withName) + } + } + """; + + // act + var warmupResult = await executor.ExecuteAsync( + OperationRequestBuilder.New() + .SetDocument(query) + .SetVariableValues( + new Dictionary + { + ["withName"] = true, + ["empty"] = true + }) + .Build()); + + var result = await executor.ExecuteAsync( + OperationRequestBuilder.New() + .SetDocument(query) + .SetVariableValues( + new Dictionary + { + ["withName"] = false, + ["empty"] = false + }) + .Build()); + + // assert + Snapshot + .Create() + .Add(warmupResult, "Warmup") + .Add(result, "Result") + .Match(); + } + [QueryType] public static class StaticQuery { @@ -1210,8 +1317,41 @@ public IQueryable GetAuthorsData2(QueryContext context) Id = 5, Name = "Author2", Books = [] - } - }.AsQueryable() + } + }.AsQueryable() .With(context, t => t with { Operations = t.Operations.Add(SortBy.Ascending(t => t.Id)) }); + + [UseSorting] + public IQueryable GetConditionalAuthors( + QueryContext context, + bool empty = false) + => (empty + ? Array.Empty() + : [ + new ConditionalAuthor + { + Id = 1, + ThrowOnNameRead = true + } + ]) + .AsQueryable() + .With(context); + } + + public sealed class ConditionalAuthor + { + private string _name = "author"; + + public int Id { get; set; } + + public bool ThrowOnNameRead { get; set; } + + public string Name + { + get => ThrowOnNameRead + ? throw new InvalidOperationException("Name should not be accessed for skipped selections.") + : _name; + set => _name = value; + } } } diff --git a/src/HotChocolate/Data/test/Data.Tests/__snapshots__/IntegrationTests.QueryContext_Selector_Respects_Include_Directive.snap b/src/HotChocolate/Data/test/Data.Tests/__snapshots__/IntegrationTests.QueryContext_Selector_Respects_Include_Directive.snap new file mode 100644 index 00000000000..d640cef27af --- /dev/null +++ b/src/HotChocolate/Data/test/Data.Tests/__snapshots__/IntegrationTests.QueryContext_Selector_Respects_Include_Directive.snap @@ -0,0 +1,9 @@ +{ + "data": { + "conditionalAuthors": [ + { + "id": 1 + } + ] + } +} diff --git a/src/HotChocolate/Data/test/Data.Tests/__snapshots__/IntegrationTests.QueryContext_Selector_Respects_Skip_Directive.snap b/src/HotChocolate/Data/test/Data.Tests/__snapshots__/IntegrationTests.QueryContext_Selector_Respects_Skip_Directive.snap new file mode 100644 index 00000000000..d640cef27af --- /dev/null +++ b/src/HotChocolate/Data/test/Data.Tests/__snapshots__/IntegrationTests.QueryContext_Selector_Respects_Skip_Directive.snap @@ -0,0 +1,9 @@ +{ + "data": { + "conditionalAuthors": [ + { + "id": 1 + } + ] + } +} diff --git a/src/HotChocolate/Data/test/Data.Tests/__snapshots__/IntegrationTests.QueryContext_Selector_Respects_Variable_Include_Directive_Across_Requests.snap b/src/HotChocolate/Data/test/Data.Tests/__snapshots__/IntegrationTests.QueryContext_Selector_Respects_Variable_Include_Directive_Across_Requests.snap new file mode 100644 index 00000000000..6b80b4a5586 --- /dev/null +++ b/src/HotChocolate/Data/test/Data.Tests/__snapshots__/IntegrationTests.QueryContext_Selector_Respects_Variable_Include_Directive_Across_Requests.snap @@ -0,0 +1,21 @@ +Warmup +--------------- +{ + "data": { + "conditionalAuthors": [] + } +} +--------------- + +Result +--------------- +{ + "data": { + "conditionalAuthors": [ + { + "id": 1 + } + ] + } +} +---------------