Skip to content

Commit

Permalink
Merge branch 'main' into TylerSiegrist/Strawberry-Shake-NET-9-Tools
Browse files Browse the repository at this point in the history
  • Loading branch information
glen-84 authored Nov 20, 2024
2 parents b46de93 + b521e35 commit 83c15da
Show file tree
Hide file tree
Showing 299 changed files with 27,735 additions and 716 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"
}
}
6 changes: 6 additions & 0 deletions src/CookieCrumble/src/CookieCrumble/Snapshot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,12 @@ private static bool MatchSnapshot(
bool inline,
[NotNullWhen(false)] out string? snapshotDiff)
{
if (OperatingSystem.IsWindows())
{
// Normalize escaped line endings
after = after.Replace("\\r\\n", "\\n");
}

var diff = InlineDiffBuilder.Diff(before, after);

if (diff.HasDifferences)
Expand Down
1 change: 1 addition & 0 deletions src/Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
<PackageVersion Include="System.Reactive" Version="6.0.0" />
<PackageVersion Include="Xunit" Version="2.9.0" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.8.2" />
<PackageVersion Include="TUnit" Version="0.3.34" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'net9.0'">
Expand Down
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
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ directive @cost("The `weight` argument defines what value to add to the overall
"The `@defer` directive may be provided for fragment spreads and inline fragments to inform the executor to delay the execution of the current fragment to indicate deprioritization of the current fragment. A query with `@defer` directive will cause the request to potentially return multiple responses, where non-deferred data is delivered in the initial response and data deferred is delivered in a subsequent response. `@include` and `@skip` take precedence over `@defer`."
directive @defer("If this argument label has a value other than null, it will be passed on to the result of this defer directive. This label is intended to give client applications a way to identify to which fragment a deferred result belongs to." label: String "Deferred when true." if: Boolean) on FRAGMENT_SPREAD | INLINE_FRAGMENT

directive @foo(bar: Int!) on SUBSCRIPTION

"The purpose of the `@listSize` directive is to either inform the static analysis about the size of returned lists (if that information is statically available), or to point the analysis to where to find that information."
directive @listSize("The `assumedSize` argument can be used to statically define the maximum length of a list returned by a field." assumedSize: Int "The `slicingArguments` argument can be used to define which of the field's arguments with numeric type are slicing arguments, so that their value determines the size of the list returned by that field. It may specify a list of multiple slicing arguments." slicingArguments: [String!] "The `sizedFields` argument can be used to define that the value of the `assumedSize` argument or of a slicing argument does not affect the size of a list returned by a field itself, but that of a list returned by one of its sub-fields." sizedFields: [String!] "The `requireOneSlicingArgument` argument can be used to inform the static analysis that it should expect that exactly one of the defined slicing arguments is present in a query. If that is not the case (i.e., if none or multiple slicing arguments are present), the static analysis may throw an error." requireOneSlicingArgument: Boolean! = true) on FIELD_DEFINITION

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

```text
Headers:
ETag: "1-LzuFZZrknIre5etJZHfNRC1e/vj+qW9tAf9pYpS8bQM="
ETag: "1-LXklYHgmBtUalJ0Ugb0vQzLmP6FuyFt1keIXDn4SE/Y="
Cache-Control: public, must-revalidate, max-age=3600
Content-Type: application/graphql; charset=utf-8
Content-Disposition: attachment; filename="schema.graphql"
Last-Modified: Fri, 01 Jan 2021 00:00:00 GMT
Content-Length: 7261
Content-Length: 7304
-------------------------->
Status Code: OK
-------------------------->
Expand Down Expand Up @@ -138,6 +138,8 @@ directive @cost("The `weight` argument defines what value to add to the overall
"The `@defer` directive may be provided for fragment spreads and inline fragments to inform the executor to delay the execution of the current fragment to indicate deprioritization of the current fragment. A query with `@defer` directive will cause the request to potentially return multiple responses, where non-deferred data is delivered in the initial response and data deferred is delivered in a subsequent response. `@include` and `@skip` take precedence over `@defer`."
directive @defer("If this argument label has a value other than null, it will be passed on to the result of this defer directive. This label is intended to give client applications a way to identify to which fragment a deferred result belongs to." label: String "Deferred when true." if: Boolean) on FRAGMENT_SPREAD | INLINE_FRAGMENT
directive @foo(bar: Int!) on SUBSCRIPTION
"The purpose of the `@listSize` directive is to either inform the static analysis about the size of returned lists (if that information is statically available), or to point the analysis to where to find that information."
directive @listSize("The `assumedSize` argument can be used to statically define the maximum length of a list returned by a field." assumedSize: Int "The `slicingArguments` argument can be used to define which of the field's arguments with numeric type are slicing arguments, so that their value determines the size of the list returned by that field. It may specify a list of multiple slicing arguments." slicingArguments: [String!] "The `sizedFields` argument can be used to define that the value of the `assumedSize` argument or of a slicing argument does not affect the size of a list returned by a field itself, but that of a list returned by one of its sub-fields." sizedFields: [String!] "The `requireOneSlicingArgument` argument can be used to inform the static analysis that it should expect that exactly one of the defined slicing arguments is present in a query. If that is not the case (i.e., if none or multiple slicing arguments are present), the static analysis may throw an error." requireOneSlicingArgument: Boolean! = true) on FIELD_DEFINITION
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

```text
Headers:
ETag: "1-B2t9cwf/BRF8NYIpFDtJE4DLg8FfD5d5HdAF9KObaUc="
ETag: "1-SGSC/P4ipajfTuy/tz1WcPpecD5c1THPYtIkhxzZoQE="
Cache-Control: public, must-revalidate, max-age=3600
Content-Type: application/graphql; charset=utf-8
Content-Disposition: attachment; filename="schema.graphql"
Last-Modified: Fri, 01 Jan 2021 00:00:00 GMT
Content-Length: 7193
Content-Length: 7236
-------------------------->
Status Code: OK
-------------------------->
Expand Down Expand Up @@ -138,6 +138,8 @@ directive @cost("The `weight` argument defines what value to add to the overall
"The `@defer` directive may be provided for fragment spreads and inline fragments to inform the executor to delay the execution of the current fragment to indicate deprioritization of the current fragment. A query with `@defer` directive will cause the request to potentially return multiple responses, where non-deferred data is delivered in the initial response and data deferred is delivered in a subsequent response. `@include` and `@skip` take precedence over `@defer`."
directive @defer("If this argument label has a value other than null, it will be passed on to the result of this defer directive. This label is intended to give client applications a way to identify to which fragment a deferred result belongs to." label: String "Deferred when true." if: Boolean) on FRAGMENT_SPREAD | INLINE_FRAGMENT
directive @foo(bar: Int!) on SUBSCRIPTION
"The purpose of the `@listSize` directive is to either inform the static analysis about the size of returned lists (if that information is statically available), or to point the analysis to where to find that information."
directive @listSize("The `assumedSize` argument can be used to statically define the maximum length of a list returned by a field." assumedSize: Int "The `slicingArguments` argument can be used to define which of the field's arguments with numeric type are slicing arguments, so that their value determines the size of the list returned by that field. It may specify a list of multiple slicing arguments." slicingArguments: [String!] "The `sizedFields` argument can be used to define that the value of the `assumedSize` argument or of a slicing argument does not affect the size of a list returned by a field itself, but that of a list returned by one of its sub-fields." sizedFields: [String!] "The `requireOneSlicingArgument` argument can be used to inform the static analysis that it should expect that exactly one of the defined slicing arguments is present in a query. If that is not the case (i.e., if none or multiple slicing arguments are present), the static analysis may throw an error." requireOneSlicingArgument: Boolean! = true) on FIELD_DEFINITION
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
40 changes: 23 additions & 17 deletions src/HotChocolate/Core/src/Types.Scalars/LocalDateType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace HotChocolate.Types;
/// character sequences YYYY-MM-DD. The scalar follows the specification defined in
/// <a href="https://tools.ietf.org/html/rfc3339">RFC3339</a>
/// </summary>
public class LocalDateType : ScalarType<DateTime, StringValueNode>
public class LocalDateType : ScalarType<DateOnly, StringValueNode>
{
private const string _localFormat = "yyyy-MM-dd";

Expand Down Expand Up @@ -42,13 +42,14 @@ public override IValueNode ParseResult(object? resultValue)
{
null => NullValueNode.Default,
string s => new StringValueNode(s),
DateTimeOffset o => ParseValue(o.DateTime),
DateTime dt => ParseValue(dt),
DateOnly d => ParseValue(d),
DateTimeOffset o => ParseValue(DateOnly.FromDateTime(o.DateTime)),
DateTime dt => ParseValue(DateOnly.FromDateTime(dt)),
_ => throw ThrowHelper.LocalDateType_ParseValue_IsInvalid(this),
};
}

protected override DateTime ParseLiteral(StringValueNode valueSyntax)
protected override DateOnly ParseLiteral(StringValueNode valueSyntax)
{
if (TryDeserializeFromString(valueSyntax.Value, out var value))
{
Expand All @@ -58,7 +59,7 @@ protected override DateTime ParseLiteral(StringValueNode valueSyntax)
throw ThrowHelper.LocalDateType_ParseLiteral_IsInvalid(this);
}

protected override StringValueNode ParseValue(DateTime runtimeValue)
protected override StringValueNode ParseValue(DateOnly runtimeValue)
{
return new(Serialize(runtimeValue));
}
Expand All @@ -70,10 +71,13 @@ public override bool TrySerialize(object? runtimeValue, out object? resultValue)
case null:
resultValue = null;
return true;
case DateTime dt:
resultValue = Serialize(dt);
case DateOnly d:
resultValue = Serialize(d);
return true;
case DateTimeOffset o:
resultValue = Serialize(o);
return true;
case DateTimeOffset dt:
case DateTime dt:
resultValue = Serialize(dt);
return true;
default:
Expand All @@ -92,11 +96,14 @@ public override bool TryDeserialize(object? resultValue, out object? runtimeValu
case string s when TryDeserializeFromString(s, out var d):
runtimeValue = d;
return true;
case DateTimeOffset d:
runtimeValue = d.DateTime;
case DateOnly d:
runtimeValue = d;
return true;
case DateTimeOffset o:
runtimeValue = DateOnly.FromDateTime(o.DateTime);
return true;
case DateTime dt:
runtimeValue = dt;
runtimeValue = DateOnly.FromDateTime(dt);
return true;
default:
runtimeValue = null;
Expand All @@ -111,16 +118,15 @@ private static string Serialize(IFormattable value)

private static bool TryDeserializeFromString(
string? serialized,
[NotNullWhen(true)] out DateTime? value)
[NotNullWhen(true)] out DateOnly? value)
{
if (serialized is not null
&& DateTime.TryParse(
&& DateOnly.TryParseExact(
serialized,
CultureInfo.InvariantCulture,
DateTimeStyles.AssumeLocal,
out var dt))
_localFormat,
out var date))
{
value = dt;
value = date;
return true;
}

Expand Down
Loading

0 comments on commit 83c15da

Please sign in to comment.