Skip to content

Commit

Permalink
@semanticNonNull support (#7681)
Browse files Browse the repository at this point in the history
  • Loading branch information
tobias-tengler committed Nov 28, 2024
1 parent 0049944 commit 901267a
Show file tree
Hide file tree
Showing 60 changed files with 2,921 additions and 128 deletions.
1 change: 1 addition & 0 deletions src/HotChocolate/Core/src/Abstractions/ErrorCodes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public static class Execution
public const string OneSlicingArgumentRequired = "HC0082";

public const string NonNullViolation = "HC0018";
public const string SemanticNonNullViolation = "HC0088";
public const string MustBeInputType = "HC0017";
public const string InvalidType = "HC0016";
public const string QueryNotFound = "HC0015";
Expand Down
10 changes: 10 additions & 0 deletions src/HotChocolate/Core/src/Abstractions/WellKnownDirectives.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,14 @@ public static class WellKnownDirectives
/// The name of the @tag argument name.
/// </summary>
public const string Name = "name";

/// <summary>
/// The name of the @semanticNonNull directive.
/// </summary>
public const string SemanticNonNull = "semanticNonNull";

/// <summary>
/// The name of the @semanticNonNull argument levels.
/// </summary>
public const string Levels = "levels";
}
5 changes: 5 additions & 0 deletions src/HotChocolate/Core/src/Abstractions/WellKnownMiddleware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,9 @@ public static class WellKnownMiddleware
/// The key identifies the authorization middleware.
/// </summary>
public const string Authorization = "HotChocolate.Authorization";

/// <summary>
/// This key identifies the semantic-non-null middleware.
/// </summary>
public const string SemanticNonNull = "HotChocolate.Types.SemanticNonNull";
}
7 changes: 7 additions & 0 deletions src/HotChocolate/Core/src/Types/IReadOnlySchemaOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,13 @@ public interface IReadOnlySchemaOptions
/// </summary>
bool EnableStream { get; }

/// <summary>
/// Enables the @semanticNonNull directive and rewrites Non-Null types to nullable types
/// with this directive attached to indicate semantic non-nullability.
/// This feature is experimental and might be changed or removed in the future.
/// </summary>
bool EnableSemanticNonNull { get; }

/// <summary>
/// Specifies the maximum allowed nodes that can be fetched at once through the nodes field.
/// </summary>
Expand Down
1 change: 1 addition & 0 deletions src/HotChocolate/Core/src/Types/SchemaBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public partial class SchemaBuilder : ISchemaBuilder
typeof(InterfaceCompletionTypeInterceptor),
typeof(MiddlewareValidationTypeInterceptor),
typeof(EnableTrueNullabilityTypeInterceptor),
typeof(SemanticNonNullTypeInterceptor),
];

private SchemaOptions _options = new();
Expand Down
162 changes: 34 additions & 128 deletions src/HotChocolate/Core/src/Types/SchemaOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,58 +15,34 @@ public class SchemaOptions : IReadOnlySchemaOptions
private BindingBehavior _defaultBindingBehavior = BindingBehavior.Implicit;
private FieldBindingFlags _defaultFieldBindingFlags = FieldBindingFlags.Instance;

/// <summary>
/// Gets or sets the name of the query type.
/// </summary>
/// <inheritdoc cref="IReadOnlySchemaOptions.QueryTypeName"/>
public string? QueryTypeName { get; set; }

/// <summary>
/// Gets or sets the name of the mutation type.
/// </summary>
/// <inheritdoc cref="IReadOnlySchemaOptions.MutationTypeName"/>
public string? MutationTypeName { get; set; }

/// <summary>
/// Gets or sets the name of the subscription type.
/// </summary>
/// <inheritdoc cref="IReadOnlySchemaOptions.SubscriptionTypeName"/>
public string? SubscriptionTypeName { get; set; }

/// <summary>
/// Defines if the schema allows the query type to be omitted.
/// </summary>
/// <inheritdoc cref="IReadOnlySchemaOptions.StrictValidation"/>
public bool StrictValidation { get; set; } = true;

/// <summary>
/// Defines if the CSharp XML documentation shall be integrated.
/// </summary>
/// <inheritdoc cref="IReadOnlySchemaOptions.UseXmlDocumentation"/>
public bool UseXmlDocumentation { get; set; } = true;

/// <summary>
/// A delegate which defines the name of the XML documentation file to be read.
/// Only used if <seealso cref="UseXmlDocumentation"/> is true.
/// </summary>
/// <inheritdoc cref="IReadOnlySchemaOptions.ResolveXmlDocumentationFileName"/>
public Func<Assembly, string>? ResolveXmlDocumentationFileName { get; set; }

/// <summary>
/// Defines if fields shall be sorted by name.
/// Default: <c>false</c>
/// </summary>
/// <inheritdoc cref="IReadOnlySchemaOptions.SortFieldsByName"/>
public bool SortFieldsByName { get; set; }

/// <summary>
/// Defines if types shall be removed from the schema that are
/// unreachable from the root types.
/// </summary>
/// <inheritdoc cref="IReadOnlySchemaOptions.RemoveUnreachableTypes"/>
public bool RemoveUnreachableTypes { get; set; }

/// <summary>
/// Defines if unused type system directives shall
/// be removed from the schema.
/// </summary>
/// <inheritdoc cref="IReadOnlySchemaOptions.RemoveUnusedTypeSystemDirectives"/>
public bool RemoveUnusedTypeSystemDirectives { get; set; } = true;

/// <summary>
/// Defines the default binding behavior.
/// </summary>
/// <inheritdoc cref="IReadOnlySchemaOptions.DefaultBindingBehavior"/>
public BindingBehavior DefaultBindingBehavior
{
get => _defaultBindingBehavior;
Expand All @@ -81,10 +57,7 @@ public BindingBehavior DefaultBindingBehavior
}
}

/// <summary>
/// Defines which members shall be by default inferred as GraphQL fields.
/// This default applies to <see cref="ObjectType"/> and <see cref="ObjectTypeExtension"/>.
/// </summary>
/// <inheritdoc cref="IReadOnlySchemaOptions.DefaultFieldBindingFlags"/>
public FieldBindingFlags DefaultFieldBindingFlags
{
get => _defaultFieldBindingFlags;
Expand All @@ -99,137 +72,69 @@ public FieldBindingFlags DefaultFieldBindingFlags
}
}

/// <summary>
/// Defines on which fields a middleware pipeline can be applied on.
/// </summary>
/// <inheritdoc cref="IReadOnlySchemaOptions.FieldMiddleware"/>
public FieldMiddlewareApplication FieldMiddleware { get; set; } =
FieldMiddlewareApplication.UserDefinedFields;

/// <summary>
/// Defines if the experimental directive introspection feature shall be enabled.
/// </summary>
/// <inheritdoc cref="IReadOnlySchemaOptions.EnableDirectiveIntrospection"/>
public bool EnableDirectiveIntrospection { get; set; }

/// <summary>
/// The default directive visibility when directive introspection is enabled.
/// </summary>
/// <inheritdoc cref="IReadOnlySchemaOptions.DefaultDirectiveVisibility"/>
public DirectiveVisibility DefaultDirectiveVisibility { get; set; } =
DirectiveVisibility.Public;

/// <summary>
/// Defines that the default resolver execution strategy.
/// </summary>
/// <inheritdoc cref="IReadOnlySchemaOptions.DefaultResolverStrategy"/>
public ExecutionStrategy DefaultResolverStrategy { get; set; } =
ExecutionStrategy.Parallel;

/// <summary>
/// Defines if the order of important middleware components shall be validated.
/// </summary>
/// <inheritdoc cref="IReadOnlySchemaOptions.ValidatePipelineOrder"/>
public bool ValidatePipelineOrder { get; set; } = true;

/// <summary>
/// Defines if the runtime types of types shall be validated.
/// </summary>
/// <inheritdoc cref="IReadOnlySchemaOptions.StrictRuntimeTypeValidation"/>
public bool StrictRuntimeTypeValidation { get; set; }

/// <summary>
/// Defines a delegate that determines if a runtime
/// is an instance of an <see cref="ObjectType{T}"/>.
/// </summary>
/// <inheritdoc cref="IReadOnlySchemaOptions.DefaultIsOfTypeCheck"/>
public IsOfTypeFallback? DefaultIsOfTypeCheck { get; set; }

/// <summary>
/// Defines if the OneOf spec RFC is enabled. This feature is experimental.
/// </summary>
/// <inheritdoc cref="IReadOnlySchemaOptions.EnableOneOf"/>
public bool EnableOneOf { get; set; }

/// <summary>
/// Defines if the schema building process shall validate that all nodes are resolvable through `node`.
/// </summary>
/// <inheritdoc cref="IReadOnlySchemaOptions.EnsureAllNodesCanBeResolved"/>
public bool EnsureAllNodesCanBeResolved { get; set; } = true;

/// <summary>
/// Defines if flag enums should be inferred as object value nodes
/// </summary>
/// <example>
/// Given the following enum
/// <br/>
/// <code>
/// [Flags]
/// public enum Example { First, Second, Third }
///
/// public class Query { public Example Loopback(Example input) => input;
/// </code>
/// <br/>
/// The following schema is produced
/// <br/>
/// <code>
/// type Query {
/// loopback(input: ExampleFlagsInput!): ExampleFlags
/// }
///
/// type ExampleFlags {
/// isFirst: Boolean!
/// isSecond: Boolean!
/// isThird: Boolean!
/// }
///
/// input ExampleFlagsInput {
/// isFirst: Boolean
/// isSecond: Boolean
/// isThird: Boolean
/// }
/// </code>
/// </example>
/// <inheritdoc cref="IReadOnlySchemaOptions.EnableFlagEnums"/>
public bool EnableFlagEnums { get; set; }

/// <summary>
/// Enables the @defer directive.
/// Defer and stream both are at the moment preview features.
/// </summary>
/// <inheritdoc cref="IReadOnlySchemaOptions.EnableDefer"/>
public bool EnableDefer { get; set; }

/// <summary>
/// Enables the @stream directive.
/// Defer and stream both are at the moment preview features.
/// </summary>
/// <inheritdoc cref="IReadOnlySchemaOptions.EnableStream"/>
public bool EnableStream { get; set; }

/// <summary>
/// Specifies the maximum allowed nodes that can be fetched at once through the nodes field.
/// </summary>
/// <inheritdoc cref="IReadOnlySchemaOptions.EnableSemanticNonNull"/>
public bool EnableSemanticNonNull { get; set; }

/// <inheritdoc cref="IReadOnlySchemaOptions.MaxAllowedNodeBatchSize"/>
public int MaxAllowedNodeBatchSize { get; set; } = 50;

/// <summary>
/// Specified if the leading I shall be stripped from the interface name.
/// </summary>
/// <inheritdoc cref="IReadOnlySchemaOptions.StripLeadingIFromInterface"/>
public bool StripLeadingIFromInterface { get; set; }

/// <summary>
/// Specifies that the true nullability proto type shall be enabled.
/// </summary>
/// <inheritdoc cref="IReadOnlySchemaOptions.EnableTrueNullability"/>
public bool EnableTrueNullability { get; set; }

/// <summary>
/// Specifies that the @tag directive shall be registered with the type system.
/// </summary>
/// <inheritdoc cref="IReadOnlySchemaOptions.EnableTag"/>
public bool EnableTag { get; set; } = true;

/// <summary>
/// Defines the default dependency injection scope for query fields.
/// </summary>
/// <inheritdoc cref="IReadOnlySchemaOptions.DefaultQueryDependencyInjectionScope"/>
public DependencyInjectionScope DefaultQueryDependencyInjectionScope { get; set; } =
DependencyInjectionScope.Resolver;

/// <summary>
/// Defines the default dependency injection scope for mutation fields.
/// </summary>
/// <inheritdoc cref="IReadOnlySchemaOptions.DefaultMutationDependencyInjectionScope"/>
public DependencyInjectionScope DefaultMutationDependencyInjectionScope { get; set; } =
DependencyInjectionScope.Request;

/// <summary>
/// Defines if the root field pages shall be published to the promise cache.
/// </summary>
/// <inheritdoc cref="IReadOnlySchemaOptions.PublishRootFieldPagesToPromiseCache"/>
public bool PublishRootFieldPagesToPromiseCache { get; set; } = true;

/// <summary>
Expand Down Expand Up @@ -263,6 +168,7 @@ public static SchemaOptions FromOptions(IReadOnlySchemaOptions options)
EnableFlagEnums = options.EnableFlagEnums,
EnableDefer = options.EnableDefer,
EnableStream = options.EnableStream,
EnableSemanticNonNull = options.EnableSemanticNonNull,
DefaultFieldBindingFlags = options.DefaultFieldBindingFlags,
MaxAllowedNodeBatchSize = options.MaxAllowedNodeBatchSize,
StripLeadingIFromInterface = options.StripLeadingIFromInterface,
Expand Down
Loading

0 comments on commit 901267a

Please sign in to comment.