Skip to content

Commit

Permalink
Add IFieldMetadataWriter (#3959)
Browse files Browse the repository at this point in the history
  • Loading branch information
Shane32 committed Jun 7, 2024
1 parent 387cfe3 commit 3f3ec65
Show file tree
Hide file tree
Showing 10 changed files with 43 additions and 21 deletions.
12 changes: 11 additions & 1 deletion docs2/site/docs/migrations/migration8.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ See [issues](https://github.com/graphql-dotnet/graphql-dotnet/issues?q=milestone

## New Features

### 1. `IMetadataReader` and `IMetadataWriter` interfaces added
### 1. `IMetadataReader`, `IMetadataWriter` and `IFieldMetadataWriter` interfaces added

This makes it convenient to add extension methods to graph types or fields that can be used to read or write metadata
such as authentication information. Methods for `IMetadataWriter` types will appear on both field builders and graph/field
Expand All @@ -26,6 +26,16 @@ Both interfaces extend `IProvideMetadata` with read/write access to the metadata
Be sure not to write metadata during the execution of a query, as the same graph/field type instance may be used for
multiple queries and you would run into concurrency issues.

In addition, the `IFieldMetadataWriter` interface has been added to allow scoping extension methods to fields only.
For example:

```csharp
// adds the GraphQL Federation '@requires' directive to the field
public static TMetadataWriter Requires<TMetadataWriter>(this TMetadataWriter fieldType, string fields)
where TMetadataWriter : IFieldMetadataWriter
=> fieldType.ApplyDirective(PROVIDES_DIRECTIVE, d => d.AddArgument(new(FIELDS_ARGUMENT) { Value = fields }));
```

### 2. Built-in scalars may be overridden via DI registrations

For GraphQL.NET built-in scalars (such as `IntGraphType` or `GuidGraphType`), a dervied class may be registered
Expand Down
11 changes: 6 additions & 5 deletions src/GraphQL.ApiTests/net50/GraphQL.approved.txt
Original file line number Diff line number Diff line change
Expand Up @@ -866,7 +866,7 @@ namespace GraphQL.Builders
where TEdgeType : GraphQL.Types.Relay.EdgeType<TNodeType>
where TConnectionType : GraphQL.Types.Relay.ConnectionType<TNodeType, TEdgeType> { }
}
public class ConnectionBuilder<TSourceType> : GraphQL.Types.IMetadataWriter, GraphQL.Types.IProvideMetadata
public class ConnectionBuilder<TSourceType> : GraphQL.Types.IFieldMetadataWriter, GraphQL.Types.IMetadataWriter, GraphQL.Types.IProvideMetadata
{
protected ConnectionBuilder(GraphQL.Types.FieldType fieldType) { }
public GraphQL.Types.FieldType FieldType { get; set; }
Expand Down Expand Up @@ -917,7 +917,7 @@ namespace GraphQL.Builders
where TEdgeType : GraphQL.Types.Relay.EdgeType<TNodeType>
where TConnectionType : GraphQL.Types.Relay.ConnectionType<TNodeType, TEdgeType> { }
}
public class ConnectionBuilder<TSourceType, TReturnType> : GraphQL.Types.IMetadataWriter, GraphQL.Types.IProvideMetadata
public class ConnectionBuilder<TSourceType, TReturnType> : GraphQL.Types.IFieldMetadataWriter, GraphQL.Types.IMetadataWriter, GraphQL.Types.IProvideMetadata
{
protected ConnectionBuilder(GraphQL.Types.FieldType fieldType) { }
public GraphQL.Types.FieldType FieldType { get; set; }
Expand Down Expand Up @@ -951,7 +951,7 @@ namespace GraphQL.Builders
where TEdgeType : GraphQL.Types.Relay.EdgeType<TNodeType>
where TConnectionType : GraphQL.Types.Relay.ConnectionType<TNodeType, TEdgeType> { }
}
public class FieldBuilder<TSourceType, TReturnType> : GraphQL.Types.IMetadataWriter, GraphQL.Types.IProvideMetadata
public class FieldBuilder<TSourceType, TReturnType> : GraphQL.Types.IFieldMetadataWriter, GraphQL.Types.IMetadataWriter, GraphQL.Types.IProvideMetadata
{
protected FieldBuilder(GraphQL.Types.FieldType fieldType) { }
public GraphQL.Types.FieldType FieldType { get; }
Expand Down Expand Up @@ -2211,7 +2211,7 @@ namespace GraphQL.Types
protected override GraphQL.Types.EnumValuesBase CreateValues() { }
public override object? ParseValue(object? value) { }
}
public class FieldType : GraphQL.Utilities.MetadataProvider, GraphQL.Types.IFieldType, GraphQL.Types.IHaveDefaultValue, GraphQL.Types.IMetadataReader, GraphQL.Types.IMetadataWriter, GraphQL.Types.IProvideDeprecationReason, GraphQL.Types.IProvideDescription, GraphQL.Types.IProvideMetadata, GraphQL.Types.IProvideResolvedType
public class FieldType : GraphQL.Utilities.MetadataProvider, GraphQL.Types.IFieldMetadataWriter, GraphQL.Types.IFieldType, GraphQL.Types.IHaveDefaultValue, GraphQL.Types.IMetadataReader, GraphQL.Types.IMetadataWriter, GraphQL.Types.IProvideDeprecationReason, GraphQL.Types.IProvideDescription, GraphQL.Types.IProvideMetadata, GraphQL.Types.IProvideResolvedType
{
public FieldType() { }
public GraphQL.Types.QueryArguments? Arguments { get; set; }
Expand Down Expand Up @@ -2290,7 +2290,8 @@ namespace GraphQL.Types
GraphQL.Types.FieldType? GetField(GraphQLParser.ROM name);
bool HasField(string name);
}
public interface IFieldType : GraphQL.Types.IHaveDefaultValue, GraphQL.Types.IMetadataReader, GraphQL.Types.IMetadataWriter, GraphQL.Types.IProvideDeprecationReason, GraphQL.Types.IProvideDescription, GraphQL.Types.IProvideMetadata, GraphQL.Types.IProvideResolvedType
public interface IFieldMetadataWriter : GraphQL.Types.IMetadataWriter, GraphQL.Types.IProvideMetadata { }
public interface IFieldType : GraphQL.Types.IFieldMetadataWriter, GraphQL.Types.IHaveDefaultValue, GraphQL.Types.IMetadataReader, GraphQL.Types.IMetadataWriter, GraphQL.Types.IProvideDeprecationReason, GraphQL.Types.IProvideDescription, GraphQL.Types.IProvideMetadata, GraphQL.Types.IProvideResolvedType
{
GraphQL.Types.QueryArguments? Arguments { get; set; }
bool IsPrivate { get; set; }
Expand Down
11 changes: 6 additions & 5 deletions src/GraphQL.ApiTests/net60/GraphQL.approved.txt
Original file line number Diff line number Diff line change
Expand Up @@ -866,7 +866,7 @@ namespace GraphQL.Builders
where TEdgeType : GraphQL.Types.Relay.EdgeType<TNodeType>
where TConnectionType : GraphQL.Types.Relay.ConnectionType<TNodeType, TEdgeType> { }
}
public class ConnectionBuilder<TSourceType> : GraphQL.Types.IMetadataWriter, GraphQL.Types.IProvideMetadata
public class ConnectionBuilder<TSourceType> : GraphQL.Types.IFieldMetadataWriter, GraphQL.Types.IMetadataWriter, GraphQL.Types.IProvideMetadata
{
protected ConnectionBuilder(GraphQL.Types.FieldType fieldType) { }
public GraphQL.Types.FieldType FieldType { get; set; }
Expand Down Expand Up @@ -917,7 +917,7 @@ namespace GraphQL.Builders
where TEdgeType : GraphQL.Types.Relay.EdgeType<TNodeType>
where TConnectionType : GraphQL.Types.Relay.ConnectionType<TNodeType, TEdgeType> { }
}
public class ConnectionBuilder<TSourceType, TReturnType> : GraphQL.Types.IMetadataWriter, GraphQL.Types.IProvideMetadata
public class ConnectionBuilder<TSourceType, TReturnType> : GraphQL.Types.IFieldMetadataWriter, GraphQL.Types.IMetadataWriter, GraphQL.Types.IProvideMetadata
{
protected ConnectionBuilder(GraphQL.Types.FieldType fieldType) { }
public GraphQL.Types.FieldType FieldType { get; set; }
Expand Down Expand Up @@ -951,7 +951,7 @@ namespace GraphQL.Builders
where TEdgeType : GraphQL.Types.Relay.EdgeType<TNodeType>
where TConnectionType : GraphQL.Types.Relay.ConnectionType<TNodeType, TEdgeType> { }
}
public class FieldBuilder<TSourceType, TReturnType> : GraphQL.Types.IMetadataWriter, GraphQL.Types.IProvideMetadata
public class FieldBuilder<TSourceType, TReturnType> : GraphQL.Types.IFieldMetadataWriter, GraphQL.Types.IMetadataWriter, GraphQL.Types.IProvideMetadata
{
protected FieldBuilder(GraphQL.Types.FieldType fieldType) { }
public GraphQL.Types.FieldType FieldType { get; }
Expand Down Expand Up @@ -2218,7 +2218,7 @@ namespace GraphQL.Types
protected override GraphQL.Types.EnumValuesBase CreateValues() { }
public override object? ParseValue(object? value) { }
}
public class FieldType : GraphQL.Utilities.MetadataProvider, GraphQL.Types.IFieldType, GraphQL.Types.IHaveDefaultValue, GraphQL.Types.IMetadataReader, GraphQL.Types.IMetadataWriter, GraphQL.Types.IProvideDeprecationReason, GraphQL.Types.IProvideDescription, GraphQL.Types.IProvideMetadata, GraphQL.Types.IProvideResolvedType
public class FieldType : GraphQL.Utilities.MetadataProvider, GraphQL.Types.IFieldMetadataWriter, GraphQL.Types.IFieldType, GraphQL.Types.IHaveDefaultValue, GraphQL.Types.IMetadataReader, GraphQL.Types.IMetadataWriter, GraphQL.Types.IProvideDeprecationReason, GraphQL.Types.IProvideDescription, GraphQL.Types.IProvideMetadata, GraphQL.Types.IProvideResolvedType
{
public FieldType() { }
public GraphQL.Types.QueryArguments? Arguments { get; set; }
Expand Down Expand Up @@ -2297,7 +2297,8 @@ namespace GraphQL.Types
GraphQL.Types.FieldType? GetField(GraphQLParser.ROM name);
bool HasField(string name);
}
public interface IFieldType : GraphQL.Types.IHaveDefaultValue, GraphQL.Types.IMetadataReader, GraphQL.Types.IMetadataWriter, GraphQL.Types.IProvideDeprecationReason, GraphQL.Types.IProvideDescription, GraphQL.Types.IProvideMetadata, GraphQL.Types.IProvideResolvedType
public interface IFieldMetadataWriter : GraphQL.Types.IMetadataWriter, GraphQL.Types.IProvideMetadata { }
public interface IFieldType : GraphQL.Types.IFieldMetadataWriter, GraphQL.Types.IHaveDefaultValue, GraphQL.Types.IMetadataReader, GraphQL.Types.IMetadataWriter, GraphQL.Types.IProvideDeprecationReason, GraphQL.Types.IProvideDescription, GraphQL.Types.IProvideMetadata, GraphQL.Types.IProvideResolvedType
{
GraphQL.Types.QueryArguments? Arguments { get; set; }
bool IsPrivate { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -833,7 +833,7 @@ namespace GraphQL.Builders
where TEdgeType : GraphQL.Types.Relay.EdgeType<TNodeType>
where TConnectionType : GraphQL.Types.Relay.ConnectionType<TNodeType, TEdgeType> { }
}
public class ConnectionBuilder<TSourceType> : GraphQL.Types.IMetadataWriter, GraphQL.Types.IProvideMetadata
public class ConnectionBuilder<TSourceType> : GraphQL.Types.IFieldMetadataWriter, GraphQL.Types.IMetadataWriter, GraphQL.Types.IProvideMetadata
{
protected ConnectionBuilder(GraphQL.Types.FieldType fieldType) { }
public GraphQL.Types.FieldType FieldType { get; set; }
Expand Down Expand Up @@ -884,7 +884,7 @@ namespace GraphQL.Builders
where TEdgeType : GraphQL.Types.Relay.EdgeType<TNodeType>
where TConnectionType : GraphQL.Types.Relay.ConnectionType<TNodeType, TEdgeType> { }
}
public class ConnectionBuilder<TSourceType, TReturnType> : GraphQL.Types.IMetadataWriter, GraphQL.Types.IProvideMetadata
public class ConnectionBuilder<TSourceType, TReturnType> : GraphQL.Types.IFieldMetadataWriter, GraphQL.Types.IMetadataWriter, GraphQL.Types.IProvideMetadata
{
protected ConnectionBuilder(GraphQL.Types.FieldType fieldType) { }
public GraphQL.Types.FieldType FieldType { get; set; }
Expand Down Expand Up @@ -918,7 +918,7 @@ namespace GraphQL.Builders
where TEdgeType : GraphQL.Types.Relay.EdgeType<TNodeType>
where TConnectionType : GraphQL.Types.Relay.ConnectionType<TNodeType, TEdgeType> { }
}
public class FieldBuilder<TSourceType, TReturnType> : GraphQL.Types.IMetadataWriter, GraphQL.Types.IProvideMetadata
public class FieldBuilder<TSourceType, TReturnType> : GraphQL.Types.IFieldMetadataWriter, GraphQL.Types.IMetadataWriter, GraphQL.Types.IProvideMetadata
{
protected FieldBuilder(GraphQL.Types.FieldType fieldType) { }
public GraphQL.Types.FieldType FieldType { get; }
Expand Down Expand Up @@ -2146,7 +2146,7 @@ namespace GraphQL.Types
protected override GraphQL.Types.EnumValuesBase CreateValues() { }
public override object? ParseValue(object? value) { }
}
public class FieldType : GraphQL.Utilities.MetadataProvider, GraphQL.Types.IFieldType, GraphQL.Types.IHaveDefaultValue, GraphQL.Types.IMetadataReader, GraphQL.Types.IMetadataWriter, GraphQL.Types.IProvideDeprecationReason, GraphQL.Types.IProvideDescription, GraphQL.Types.IProvideMetadata, GraphQL.Types.IProvideResolvedType
public class FieldType : GraphQL.Utilities.MetadataProvider, GraphQL.Types.IFieldMetadataWriter, GraphQL.Types.IFieldType, GraphQL.Types.IHaveDefaultValue, GraphQL.Types.IMetadataReader, GraphQL.Types.IMetadataWriter, GraphQL.Types.IProvideDeprecationReason, GraphQL.Types.IProvideDescription, GraphQL.Types.IProvideMetadata, GraphQL.Types.IProvideResolvedType
{
public FieldType() { }
public GraphQL.Types.QueryArguments? Arguments { get; set; }
Expand Down Expand Up @@ -2218,7 +2218,8 @@ namespace GraphQL.Types
GraphQL.Types.FieldType? GetField(GraphQLParser.ROM name);
bool HasField(string name);
}
public interface IFieldType : GraphQL.Types.IHaveDefaultValue, GraphQL.Types.IMetadataReader, GraphQL.Types.IMetadataWriter, GraphQL.Types.IProvideDeprecationReason, GraphQL.Types.IProvideDescription, GraphQL.Types.IProvideMetadata, GraphQL.Types.IProvideResolvedType
public interface IFieldMetadataWriter : GraphQL.Types.IMetadataWriter, GraphQL.Types.IProvideMetadata { }
public interface IFieldType : GraphQL.Types.IFieldMetadataWriter, GraphQL.Types.IHaveDefaultValue, GraphQL.Types.IMetadataReader, GraphQL.Types.IMetadataWriter, GraphQL.Types.IProvideDeprecationReason, GraphQL.Types.IProvideDescription, GraphQL.Types.IProvideMetadata, GraphQL.Types.IProvideResolvedType
{
GraphQL.Types.QueryArguments? Arguments { get; set; }
bool IsPrivate { get; set; }
Expand Down
2 changes: 1 addition & 1 deletion src/GraphQL/Builders/ConnectionBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ public static class ConnectionBuilder
/// Builds a connection field for graphs that have the specified source type.
/// </summary>
// TODO: Remove in v5
public class ConnectionBuilder<[NotAGraphType] TSourceType> : IMetadataWriter
public class ConnectionBuilder<[NotAGraphType] TSourceType> : IFieldMetadataWriter
{
internal const string PAGE_SIZE_METADATA_KEY = "__ConnectionBuilder_PageSize";

Expand Down
2 changes: 1 addition & 1 deletion src/GraphQL/Builders/ConnectionBuilder_Typed.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace GraphQL.Builders;
/// <summary>
/// Builds a connection field for graphs that have the specified source and return type.
/// </summary>
public class ConnectionBuilder<[NotAGraphType] TSourceType, [NotAGraphType] TReturnType> : IMetadataWriter
public class ConnectionBuilder<[NotAGraphType] TSourceType, [NotAGraphType] TReturnType> : IFieldMetadataWriter
{
private bool IsBidirectional => FieldType.Arguments?.Find("before")?.Type == typeof(StringGraphType) && FieldType.Arguments.Find("last")?.Type == typeof(IntGraphType);

Expand Down
2 changes: 1 addition & 1 deletion src/GraphQL/Builders/FieldBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace GraphQL.Builders;
/// </summary>
/// <typeparam name="TSourceType">The type of <see cref="IResolveFieldContext.Source"/>.</typeparam>
/// <typeparam name="TReturnType">The type of the return value of the resolver.</typeparam>
public class FieldBuilder<[NotAGraphType] TSourceType, [NotAGraphType] TReturnType> : IMetadataWriter
public class FieldBuilder<[NotAGraphType] TSourceType, [NotAGraphType] TReturnType> : IFieldMetadataWriter
{
/// <summary>
/// Returns the generated field.
Expand Down
9 changes: 9 additions & 0 deletions src/GraphQL/Types/Fields/IFieldMetadataWriter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace GraphQL.Types;

/// <summary>
/// Provides basic capabilities for getting and setting arbitrary meta information on fields.
/// This interface is implemented by field builders and field types for configuring metadata.
/// </summary>
public interface IFieldMetadataWriter : IMetadataWriter
{
}
2 changes: 1 addition & 1 deletion src/GraphQL/Types/Fields/IFieldType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ namespace GraphQL.Types;
/// <summary>
/// Represents a field of a graph type.
/// </summary>
public interface IFieldType : IHaveDefaultValue, IMetadataReader, IMetadataWriter, IProvideDescription, IProvideDeprecationReason
public interface IFieldType : IHaveDefaultValue, IMetadataReader, IFieldMetadataWriter, IProvideDescription, IProvideDeprecationReason
{
/// <summary>
/// Gets or sets the name of the field.
Expand Down
2 changes: 1 addition & 1 deletion src/GraphQL/Types/IMetadataWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ namespace GraphQL.Types;

/// <summary>
/// Provides basic capabilities for getting and setting arbitrary meta information.
/// This interface is implemented by field builders and field types for configuring metadata.
/// This interface is implemented by field builders, field types, graph types and schemas for configuring metadata.
/// </summary>
public interface IMetadataWriter : IProvideMetadata
{
Expand Down

0 comments on commit 3f3ec65

Please sign in to comment.