Skip to content

Commit

Permalink
Merge branch 'main' into gai/date-time-runtime-type
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelstaib authored Nov 17, 2024
2 parents 4d5af6a + 9ba5997 commit 7ce284b
Show file tree
Hide file tree
Showing 190 changed files with 26,288 additions and 208 deletions.
2 changes: 1 addition & 1 deletion global.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"sdk": {
"version": "9.0.100-rc.2.24474.11",
"version": "9.0.100",
"rollForward": "latestMinor"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -551,7 +551,7 @@ protected virtual void OnWriteResponseHeaders(
return _multiPartFormat;
}

if (mediaType.Kind is EventStream)
if (mediaType.Kind is EventStream or All)
{
return _eventStreamFormat;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ protected virtual TestServer CreateStarWarsServer(
.AddStarWarsTypes()
.AddTypeExtension<QueryExtension>()
.AddTypeExtension<SubscriptionsExtensions>()
.AddType<Foo>()
.AddStarWarsRepositories()
.AddInMemorySubscriptions()
.UseInstrumentation()
Expand Down Expand Up @@ -165,4 +166,10 @@ protected virtual TestServer CreateServer(
.UseRouting()
.UseEndpoints(endpoints => configureConventions?.Invoke(endpoints)));
}

[DirectiveType(DirectiveLocation.Subscription)]
public class Foo
{
public required int Bar { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -457,7 +457,102 @@ public async Task EventStream_Sends_KeepAlive()
Snapshot
.Create()
.Add(response)
.MatchInline("""
.MatchInline(
"""
Headers:
Cache-Control: no-cache
Content-Type: text/event-stream; charset=utf-8
-------------------------->
Status Code: OK
-------------------------->
event: next
data: {"data":{"delay":"next"}}
:
event: next
data: {"data":{"delay":"next"}}
:
event: complete
""");
}

[Fact]
public async Task EventStream_When_Accept_Is_All()
{
// arrange
var server = CreateStarWarsServer();
var client = server.CreateClient();
client.Timeout = TimeSpan.FromSeconds(30);

// act
using var request = new HttpRequestMessage(HttpMethod.Post, _url);
request.Content = JsonContent.Create(
new ClientQueryRequest
{
Query = "subscription {delay(count: 2, delay:15000)}",
});
request.Headers.Add("Accept", "*/*");

using var response = await client.SendAsync(request, ResponseHeadersRead);

// assert
Snapshot
.Create()
.Add(response)
.MatchInline(
"""
Headers:
Cache-Control: no-cache
Content-Type: text/event-stream; charset=utf-8
-------------------------->
Status Code: OK
-------------------------->
event: next
data: {"data":{"delay":"next"}}
:
event: next
data: {"data":{"delay":"next"}}
:
event: complete
""");
}

[Fact]
public async Task EventStream_When_Accept_Is_All_And_Subscription_Directive()
{
// arrange
var server = CreateStarWarsServer();
var client = server.CreateClient();
client.Timeout = TimeSpan.FromSeconds(30);

// act
using var request = new HttpRequestMessage(HttpMethod.Post, _url);
request.Content = JsonContent.Create(
new ClientQueryRequest
{
Query = "subscription foo @foo(bar: 1) {delay(count: 2, delay:15000)}",
});
request.Headers.Add("Accept", "*/*");

using var response = await client.SendAsync(request, ResponseHeadersRead);

// assert
Snapshot
.Create()
.Add(response)
.MatchInline(
"""
Headers:
Cache-Control: no-cache
Content-Type: text/event-stream; charset=utf-8
Expand Down
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";
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ protected override ValueTask<Connection> SliceAsync(
=> source switch
{
IQueryable<TEntity> q => SliceAsyncInternal(context, Executable.From(q), arguments),
IEnumerable<TEntity> e => SliceAsyncInternal(context, Executable.From(e.AsQueryable()), arguments),
IEnumerable<TEntity> e => e.GetType().IsValueType
? throw new GraphQLException("Cannot handle the specified data source.")
: SliceAsyncInternal(context, Executable.From(e.AsQueryable()), arguments),
IQueryableExecutable<TEntity> ex => SliceAsyncInternal(context, ex, arguments),
_ => throw new GraphQLException("Cannot handle the specified data source."),
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ protected override ValueTask<CollectionSegment> SliceAsync(
return source switch
{
IQueryable<TEntity> q => ResolveAsync(context, q, arguments, ct),
IEnumerable<TEntity> e => ResolveAsync(context, e.AsQueryable(), arguments, ct),
IEnumerable<TEntity> e => e.GetType().IsValueType
? throw new GraphQLException("Cannot handle the specified data source.")
: ResolveAsync(context, e.AsQueryable(), arguments, ct),
IExecutable<TEntity> ex => SliceAsync(context, ex.Source, arguments),
_ => throw new GraphQLException("Cannot handle the specified data source."),
};
Expand Down
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
3 changes: 2 additions & 1 deletion src/HotChocolate/Core/src/Types/SchemaBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ public partial class SchemaBuilder : ISchemaBuilder
[
typeof(IntrospectionTypeInterceptor),
typeof(InterfaceCompletionTypeInterceptor),
typeof(MiddlewareValidationTypeInterceptor)
typeof(MiddlewareValidationTypeInterceptor),
typeof(SemanticNonNullTypeInterceptor),
];

private SchemaOptions _options = new();
Expand Down
Loading

0 comments on commit 7ce284b

Please sign in to comment.