-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add subscription support to source generator (#1729)
- Loading branch information
Showing
36 changed files
with
1,389 additions
and
158 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
## Subscriptions | ||
|
||
Code generator will generate object definition and extensions methods for adding subscription | ||
types to the schema. Generator will generate a subscriber for each `IAsyncEnumerable<T>` method | ||
of a class with `[ObjectType]` attribute. You can use provided extension method to add the | ||
subscription type, subscribers and resolver to the schema. | ||
|
||
|
||
### Tanka.GraphQL.Samples.SG.Subscription | ||
|
||
```csharp | ||
#include::xref://samples:GraphQL.Samples.SG.Subscription/Program.cs | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
- [Installation & basics](xref://01-samples-sg-basic.md) | ||
- [Arguments](xref://02-samples-sg-arguments.md) | ||
- [Namespace](xref://03-samples-sg-namespace.md) | ||
- [Dependency injection](xref://04-samples-sg-services.md) | ||
- [Dependency injection](xref://04-samples-sg-services.md) | ||
- [Subscriptions](xref://05-samples-sg-subscriptions.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,3 @@ | ||
using System.Collections.Concurrent; | ||
using Microsoft.AspNetCore.Mvc; | ||
|
||
using Tanka.GraphQL; | ||
|
19 changes: 19 additions & 0 deletions
19
samples/GraphQL.Samples.SG.Subscription/GraphQL.Samples.SG.Subscription.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
<Project Sdk="Microsoft.NET.Sdk.Web"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net8.0</TargetFramework> | ||
<Nullable>enable</Nullable> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\..\src\GraphQL.Language\GraphQL.Language.csproj" /> | ||
<ProjectReference Include="..\..\src\GraphQL.Server\GraphQL.Server.csproj" /> | ||
<ProjectReference Include="..\..\src\GraphQL\GraphQL.csproj" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\..\src\GraphQL.Server.SourceGenerators\GraphQL.Server.SourceGenerators.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" /> | ||
</ItemGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
using System.Runtime.CompilerServices; | ||
|
||
using Tanka.GraphQL.Server; | ||
|
||
WebApplicationBuilder builder = WebApplication.CreateBuilder(args); | ||
|
||
builder.AddTankaGraphQL() | ||
.AddHttp() | ||
.AddWebSockets() | ||
.AddSchemaOptions("Default", options => | ||
{ | ||
// This extension point is used by the generator to add | ||
// type controllers | ||
options.AddGeneratedTypes(types => | ||
{ | ||
// Add generated controllers | ||
types | ||
.AddQueryController() | ||
.AddSubscriptionController(); | ||
}); | ||
}); | ||
|
||
WebApplication app = builder.Build(); | ||
app.UseWebSockets(); | ||
|
||
app.MapTankaGraphQL("/graphql", "Default"); | ||
app.MapGraphiQL("/graphql/ui"); | ||
app.Run(); | ||
|
||
[ObjectType] | ||
public static class Subscription | ||
{ | ||
/// <summary> | ||
/// This is subscription field producing random integers of count between from and to | ||
/// </summary> | ||
/// <returns></returns> | ||
public static async IAsyncEnumerable<int> Random(int from, int to, int count, [EnumeratorCancellation] CancellationToken cancellationToken) | ||
{ | ||
var r = new Random(); | ||
|
||
for (var i = 0; i < count; i++) | ||
{ | ||
cancellationToken.ThrowIfCancellationRequested(); | ||
yield return r.Next(from, to); | ||
await Task.Delay(500, cancellationToken); | ||
} | ||
} | ||
} | ||
|
||
[ObjectType] | ||
public static class Query | ||
{ | ||
// this is required as the graphiql will error without a query field | ||
public static string Hello() => "Hello World!"; | ||
} |
14 changes: 14 additions & 0 deletions
14
samples/GraphQL.Samples.SG.Subscription/Properties/launchSettings.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
{ | ||
"profiles": { | ||
"GraphQL.Samples.SG.Subscription": { | ||
"commandName": "Project", | ||
"launchBrowser": true, | ||
"launchUrl": "https://localhost:7239/graphql/ui", | ||
"environmentVariables": { | ||
"ASPNETCORE_ENVIRONMENT": "Development" | ||
}, | ||
"applicationUrl": "https://localhost:7239", | ||
"dotnetRunMessages": true | ||
} | ||
} | ||
} |
8 changes: 8 additions & 0 deletions
8
samples/GraphQL.Samples.SG.Subscription/appsettings.Development.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"Logging": { | ||
"LogLevel": { | ||
"Default": "Information", | ||
"Microsoft.AspNetCore": "Warning" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
"Logging": { | ||
"LogLevel": { | ||
"Default": "Information", | ||
"Microsoft.AspNetCore": "Warning" | ||
} | ||
}, | ||
"AllowedHosts": "*" | ||
} |
115 changes: 115 additions & 0 deletions
115
src/GraphQL.Server.SourceGenerators/Internal/EquatableArray.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
using System; | ||
using System.Collections; | ||
using System.Collections.Generic; | ||
using System.Collections.Immutable; | ||
using System.Linq; | ||
|
||
namespace Tanka.GraphQL.Server.SourceGenerators.Internal; | ||
|
||
public static class EquatableArrayExtensions | ||
{ | ||
public static EquatableArray<T> ToEquatableArray<T>(this IEnumerable<T> array) | ||
where T : IEquatable<T> | ||
{ | ||
return new(array.ToArray()); | ||
|
||
} | ||
} | ||
|
||
/// <summary> | ||
/// Origin https://github.com/andrewlock/NetEscapades.EnumGenerators | ||
/// An immutable, equatable array. This is equivalent to <see cref="Array"/> but with value equality support. | ||
/// </summary> | ||
/// <typeparam name="T">The type of values in the array.</typeparam> | ||
public readonly struct EquatableArray<T> : IEquatable<EquatableArray<T>>, IEnumerable<T> | ||
where T : IEquatable<T> | ||
{ | ||
/// <summary> | ||
/// The underlying <typeparamref name="T"/> array. | ||
/// </summary> | ||
private readonly T[]? _array; | ||
|
||
/// <summary> | ||
/// Creates a new <see cref="EquatableArray{T}"/> instance. | ||
/// </summary> | ||
/// <param name="array">The input <see cref="ImmutableArray{T}"/> to wrap.</param> | ||
public EquatableArray(T[] array) | ||
{ | ||
_array = array; | ||
} | ||
|
||
/// <sinheritdoc/> | ||
public bool Equals(EquatableArray<T> array) | ||
{ | ||
return AsSpan().SequenceEqual(array.AsSpan()); | ||
} | ||
|
||
/// <sinheritdoc/> | ||
public override bool Equals(object? obj) | ||
{ | ||
return obj is EquatableArray<T> array && Equals(this, array); | ||
} | ||
|
||
/// <sinheritdoc/> | ||
public override int GetHashCode() | ||
{ | ||
if (_array is not T[] array) | ||
{ | ||
return 0; | ||
} | ||
|
||
HashCode hashCode = default; | ||
|
||
foreach (T item in array) | ||
{ | ||
hashCode.Add(item); | ||
} | ||
|
||
return hashCode.ToHashCode(); | ||
} | ||
|
||
/// <summary> | ||
/// Returns a <see cref="ReadOnlySpan{T}"/> wrapping the current items. | ||
/// </summary> | ||
/// <returns>A <see cref="ReadOnlySpan{T}"/> wrapping the current items.</returns> | ||
public ReadOnlySpan<T> AsSpan() | ||
{ | ||
return _array.AsSpan(); | ||
} | ||
|
||
/// <sinheritdoc/> | ||
IEnumerator<T> IEnumerable<T>.GetEnumerator() | ||
{ | ||
return ((IEnumerable<T>)(_array ?? Array.Empty<T>())).GetEnumerator(); | ||
} | ||
|
||
/// <sinheritdoc/> | ||
IEnumerator IEnumerable.GetEnumerator() | ||
{ | ||
return ((IEnumerable<T>)(_array ?? Array.Empty<T>())).GetEnumerator(); | ||
} | ||
|
||
public int Count => _array?.Length ?? 0; | ||
|
||
/// <summary> | ||
/// Checks whether two <see cref="EquatableArray{T}"/> values are the same. | ||
/// </summary> | ||
/// <param name="left">The first <see cref="EquatableArray{T}"/> value.</param> | ||
/// <param name="right">The second <see cref="EquatableArray{T}"/> value.</param> | ||
/// <returns>Whether <paramref name="left"/> and <paramref name="right"/> are equal.</returns> | ||
public static bool operator ==(EquatableArray<T> left, EquatableArray<T> right) | ||
{ | ||
return left.Equals(right); | ||
} | ||
|
||
/// <summary> | ||
/// Checks whether two <see cref="EquatableArray{T}"/> values are not the same. | ||
/// </summary> | ||
/// <param name="left">The first <see cref="EquatableArray{T}"/> value.</param> | ||
/// <param name="right">The second <see cref="EquatableArray{T}"/> value.</param> | ||
/// <returns>Whether <paramref name="left"/> and <paramref name="right"/> are not equal.</returns> | ||
public static bool operator !=(EquatableArray<T> left, EquatableArray<T> right) | ||
{ | ||
return !left.Equals(right); | ||
} | ||
} |
Oops, something went wrong.