Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added new node id serializer. #7026

Merged
merged 16 commits into from
Apr 4, 2024
10 changes: 10 additions & 0 deletions src/HotChocolate/Core/src/Abstractions/WellKnownContextData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,11 @@ public static class WellKnownContextData
/// </summary>
public const string GlobalIdSupportEnabled = "HotChocolate.Relay.GlobalId";

/// <summary>
/// The key to get the serializer types.
/// </summary>
public const string SerializerTypes = "HotChocolate.Relay.SerializerTypes";

/// <summary>
/// The key to get the node id from the context data.
/// </summary>
Expand Down Expand Up @@ -299,4 +304,9 @@ public static class WellKnownContextData
/// Type key to access the object type configuration hooks in the schema builder context data.
/// </summary>
public const string ObjectTypeConfigurations = "HotChocolate.Types.ObjectTypeConfigurations";

/// <summary>
/// Type key to access the node id result formatter on the descriptor context.
/// </summary>
public const string NodeIdResultFormatter = "HotChocolate.Relay.NodeIdResultFormatter";
}
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ internal static IServiceCollection TryAddDeferredWorkStatePool(

return services;
}

internal static IServiceCollection TryAddTypeConverter(
this IServiceCollection services)
{
Expand Down Expand Up @@ -183,13 +183,6 @@ internal static IServiceCollection TryAddDefaultDataLoaderRegistry(
return services;
}

internal static IServiceCollection TryAddIdSerializer(
this IServiceCollection services)
{
services.TryAddSingleton<IIdSerializer, IdSerializer>();
return services;
}

internal static IServiceCollection TryAddDataLoaderParameterExpressionBuilder(
this IServiceCollection services)
=> services.TryAddParameterExpressionBuilder<DataLoaderParameterExpressionBuilder>();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using HotChocolate;
using HotChocolate.Execution.Configuration;
using HotChocolate.Types.Relay;
using Microsoft.Extensions.DependencyInjection.Extensions;
Expand All @@ -8,94 +11,89 @@

public static partial class RequestExecutorBuilderExtensions
{
public static IServiceCollection AddIdSerializer(
this IServiceCollection services,
bool includeSchemaName = false)
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
}

services.RemoveAll<IIdSerializer>();
services.AddSingleton<IIdSerializer>(new IdSerializer(includeSchemaName));
return services;
}

public static IServiceCollection AddIdSerializer<T>(
this IServiceCollection services)
where T : class, IIdSerializer
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
}

services.RemoveAll<IIdSerializer>();
services.AddSingleton<IIdSerializer, T>();
return services;
}

public static IServiceCollection AddIdSerializer(
this IServiceCollection services,
Func<IServiceProvider, IIdSerializer> factory)
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
}

if (factory == null)
{
throw new ArgumentNullException(nameof(factory));
}

services.RemoveAll<IIdSerializer>();
services.AddSingleton(factory);
return services;
}

public static IRequestExecutorBuilder AddIdSerializer(
/// <summary>
/// Adds a default node id serializer to the schema.
/// </summary>
/// <param name="builder">

Check warning on line 17 in src/HotChocolate/Core/src/Execution/DependencyInjection/RequestExecutorBuilderExtensions.IdSerializer.cs

View check run for this annotation

Codecov / codecov/patch

src/HotChocolate/Core/src/Execution/DependencyInjection/RequestExecutorBuilderExtensions.IdSerializer.cs#L14-L17

Added lines #L14 - L17 were not covered by tests
/// The request executor builder.
/// </param>
/// <param name="maxIdLength">
/// The maximum allowed length of a node id.
/// </param>
/// <returns>

Check warning on line 23 in src/HotChocolate/Core/src/Execution/DependencyInjection/RequestExecutorBuilderExtensions.IdSerializer.cs

View check run for this annotation

Codecov / codecov/patch

src/HotChocolate/Core/src/Execution/DependencyInjection/RequestExecutorBuilderExtensions.IdSerializer.cs#L20-L23

Added lines #L20 - L23 were not covered by tests
/// Returns the request executor builder.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="builder"/> is <see langword="null"/>.
/// </exception>
public static IRequestExecutorBuilder AddDefaultNodeIdSerializer(

Check warning on line 29 in src/HotChocolate/Core/src/Execution/DependencyInjection/RequestExecutorBuilderExtensions.IdSerializer.cs

View check run for this annotation

Codecov / codecov/patch

src/HotChocolate/Core/src/Execution/DependencyInjection/RequestExecutorBuilderExtensions.IdSerializer.cs#L28-L29

Added lines #L28 - L29 were not covered by tests
this IRequestExecutorBuilder builder,
bool includeSchemaName = false)
int maxIdLength = 1024)

Check warning on line 31 in src/HotChocolate/Core/src/Execution/DependencyInjection/RequestExecutorBuilderExtensions.IdSerializer.cs

View check run for this annotation

Codecov / codecov/patch

src/HotChocolate/Core/src/Execution/DependencyInjection/RequestExecutorBuilderExtensions.IdSerializer.cs#L31

Added line #L31 was not covered by tests
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}

builder.Services.AddIdSerializer(includeSchemaName);
return builder;
}
builder.ConfigureSchemaServices(
services =>
{
services.TryAddSingleton<INodeIdSerializer>(sp =>
{
var schema = sp.GetRequiredService<ISchema>();
var boundSerializers = new List<BoundNodeIdValueSerializer>();
var allSerializers = sp.GetServices<INodeIdValueSerializer>().ToArray();

Check warning on line 45 in src/HotChocolate/Core/src/Execution/DependencyInjection/RequestExecutorBuilderExtensions.IdSerializer.cs

View check run for this annotation

Codecov / codecov/patch

src/HotChocolate/Core/src/Execution/DependencyInjection/RequestExecutorBuilderExtensions.IdSerializer.cs#L42-L45

Added lines #L42 - L45 were not covered by tests

public static IRequestExecutorBuilder AddIdSerializer<T>(
this IRequestExecutorBuilder builder)
where T : class, IIdSerializer
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
if (schema.ContextData.TryGetValue(WellKnownContextData.SerializerTypes, out var value))
{
var serializerTypes = (Dictionary<string, Type>)value!;

Check warning on line 49 in src/HotChocolate/Core/src/Execution/DependencyInjection/RequestExecutorBuilderExtensions.IdSerializer.cs

View check run for this annotation

Codecov / codecov/patch

src/HotChocolate/Core/src/Execution/DependencyInjection/RequestExecutorBuilderExtensions.IdSerializer.cs#L48-L49

Added lines #L48 - L49 were not covered by tests

builder.Services.AddIdSerializer<T>();
foreach (var item in serializerTypes)
{
foreach (var serializer in allSerializers)
{
if (serializer.IsSupported(item.Value))
{

Check warning on line 56 in src/HotChocolate/Core/src/Execution/DependencyInjection/RequestExecutorBuilderExtensions.IdSerializer.cs

View check run for this annotation

Codecov / codecov/patch

src/HotChocolate/Core/src/Execution/DependencyInjection/RequestExecutorBuilderExtensions.IdSerializer.cs#L53-L56

Added lines #L53 - L56 were not covered by tests
boundSerializers.Add(new BoundNodeIdValueSerializer(item.Key, serializer));
break;
}
}
}
}

return new DefaultNodeIdSerializer(boundSerializers, allSerializers, maxIdLength);

Check warning on line 64 in src/HotChocolate/Core/src/Execution/DependencyInjection/RequestExecutorBuilderExtensions.IdSerializer.cs

View check run for this annotation

Codecov / codecov/patch

src/HotChocolate/Core/src/Execution/DependencyInjection/RequestExecutorBuilderExtensions.IdSerializer.cs#L61-L64

Added lines #L61 - L64 were not covered by tests
});
});
return builder;
}

public static IRequestExecutorBuilder AddIdSerializer(
this IRequestExecutorBuilder builder,
Func<IServiceProvider, IIdSerializer> factory)
/// <summary>
/// Adds a custom node id value serializer to the schema.
/// A value serializer is used to format a runtime value into a node id.
/// </summary>
/// <param name="builder">
/// The request executor builder.
/// </param>
/// <typeparam name="T">

Check warning on line 77 in src/HotChocolate/Core/src/Execution/DependencyInjection/RequestExecutorBuilderExtensions.IdSerializer.cs

View check run for this annotation

Codecov / codecov/patch

src/HotChocolate/Core/src/Execution/DependencyInjection/RequestExecutorBuilderExtensions.IdSerializer.cs#L74-L77

Added lines #L74 - L77 were not covered by tests
/// The type of the node id value serializer.
/// </typeparam>
/// <returns>
/// Returns the request executor builder.
/// </returns>

Check warning on line 82 in src/HotChocolate/Core/src/Execution/DependencyInjection/RequestExecutorBuilderExtensions.IdSerializer.cs

View check run for this annotation

Codecov / codecov/patch

src/HotChocolate/Core/src/Execution/DependencyInjection/RequestExecutorBuilderExtensions.IdSerializer.cs#L80-L82

Added lines #L80 - L82 were not covered by tests
/// <exception cref="ArgumentNullException">
/// <paramref name="builder"/> is <see langword="null"/>.
/// </exception>
public static IRequestExecutorBuilder AddNodeIdValueSerializer<T>(
this IRequestExecutorBuilder builder)
where T : class, INodeIdValueSerializer

Check warning on line 88 in src/HotChocolate/Core/src/Execution/DependencyInjection/RequestExecutorBuilderExtensions.IdSerializer.cs

View check run for this annotation

Codecov / codecov/patch

src/HotChocolate/Core/src/Execution/DependencyInjection/RequestExecutorBuilderExtensions.IdSerializer.cs#L87-L88

Added lines #L87 - L88 were not covered by tests
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}

if (factory == null)
{
throw new ArgumentNullException(nameof(factory));
}

builder.Services.AddIdSerializer(factory);
builder.ConfigureSchemaServices(

Check warning on line 95 in src/HotChocolate/Core/src/Execution/DependencyInjection/RequestExecutorBuilderExtensions.IdSerializer.cs

View check run for this annotation

Codecov / codecov/patch

src/HotChocolate/Core/src/Execution/DependencyInjection/RequestExecutorBuilderExtensions.IdSerializer.cs#L95

Added line #L95 was not covered by tests
services => services.AddSingleton<INodeIdValueSerializer, T>());
return builder;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ public static IServiceCollection AddGraphQLCore(this IServiceCollection services
.TryAddDefaultDocumentHashProvider()
.TryAddDefaultBatchDispatcher()
.TryAddDefaultDataLoaderRegistry()
.TryAddIdSerializer()
.TryAddDataLoaderParameterExpressionBuilder()
.AddSingleton<ResolverProvider>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Threading.Tasks;
using HotChocolate.Execution.Properties;
using HotChocolate.Execution.Serialization;
using HotChocolate.Language;
using HotChocolate.Resolvers;
using HotChocolate.Types;
using Microsoft.Extensions.DependencyInjection;
Expand Down Expand Up @@ -44,7 +45,7 @@
public CancellationToken RequestAborted { get; private set; }

public bool HasCleanupTasks => _cleanupTasks.Count > 0;

public void ReportError(string errorMessage)
{
if (string.IsNullOrEmpty(errorMessage))
Expand Down Expand Up @@ -115,6 +116,8 @@
ReportSingle(error);
}

return;

void ReportSingle(IError singleError)
{
var handled = _operationContext.ErrorHandler.Handle(singleError);
Expand All @@ -123,18 +126,35 @@
{
foreach (var ie in ar.Errors)
{
_operationContext.Result.AddError(ie, _selection);
_operationContext.DiagnosticEvents.ResolverError(this, ie);
var errorWithPath = EnsurePathAndLocation(ie, _selection.SyntaxNode, Path);

Check warning on line 129 in src/HotChocolate/Core/src/Execution/Processing/MiddlewareContext.Global.cs

View check run for this annotation

Codecov / codecov/patch

src/HotChocolate/Core/src/Execution/Processing/MiddlewareContext.Global.cs#L129

Added line #L129 was not covered by tests
_operationContext.Result.AddError(errorWithPath, _selection);
_operationContext.DiagnosticEvents.ResolverError(this, errorWithPath);
}
}
else
{
_operationContext.Result.AddError(handled, _selection);
_operationContext.DiagnosticEvents.ResolverError(this, handled);
var errorWithPath = EnsurePathAndLocation(handled, _selection.SyntaxNode, Path);
_operationContext.Result.AddError(errorWithPath, _selection);
_operationContext.DiagnosticEvents.ResolverError(this, errorWithPath);
}

HasErrors = true;
}

static IError EnsurePathAndLocation(IError error, ISyntaxNode node, Path path)
{
if (error.Path is null)
{
error = error.WithPath(path);

Check warning on line 148 in src/HotChocolate/Core/src/Execution/Processing/MiddlewareContext.Global.cs

View check run for this annotation

Codecov / codecov/patch

src/HotChocolate/Core/src/Execution/Processing/MiddlewareContext.Global.cs#L143-L148

Added lines #L143 - L148 were not covered by tests
}

if (error.Locations is not { Count: > 0 } && node.Location is not null)
{
error = error.WithLocations([new Location(node.Location.Line, node.Location.Column)]);

Check warning on line 153 in src/HotChocolate/Core/src/Execution/Processing/MiddlewareContext.Global.cs

View check run for this annotation

Codecov / codecov/patch

src/HotChocolate/Core/src/Execution/Processing/MiddlewareContext.Global.cs#L150-L153

Added lines #L150 - L153 were not covered by tests
}

return error;
}
}

public async ValueTask<T> ResolveAsync<T>()
Expand All @@ -152,7 +172,7 @@
: (T)_resolverResult;
}

public T Resolver<T>()
public T Resolver<T>()
=> _operationContext.Resolvers.GetResolver<T>(_operationContext.Services);

public T Service<T>() where T : notnull => Services.GetRequiredService<T>();
Expand Down
Loading
Loading