https://github.com/graphql-dotnet/relay
A toolset for creating Relay.js compatible GraphQL servers in dotnet.
https://github.com/graphql-dotnet/relay
Last synced: 7 months ago
JSON representation
A toolset for creating Relay.js compatible GraphQL servers in dotnet.
- Host: GitHub
- URL: https://github.com/graphql-dotnet/relay
- Owner: graphql-dotnet
- License: mit
- Created: 2016-11-22T18:27:06.000Z (about 9 years ago)
- Default Branch: master
- Last Pushed: 2023-11-20T10:43:19.000Z (about 2 years ago)
- Last Synced: 2025-05-08T00:41:45.735Z (7 months ago)
- Language: C#
- Homepage:
- Size: 542 KB
- Stars: 75
- Watchers: 14
- Forks: 28
- Open Issues: 39
-
Metadata Files:
- Readme: README.md
- License: LICENSE.md
Awesome Lists containing this project
README
# GraphQL.Relay

[](https://github.com/graphql-dotnet/relay/actions/workflows/codeql-analysis.yml)
[](https://codecov.io/gh/graphql-dotnet/relay)




A collection of classes, tools, and utilities for creating Relay.js compatible GraphQL servers in dotnet.
Provides the following packages:
| Package | Downloads | NuGet Latest |
|---------------|---------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------|
| GraphQL.Relay | [](https://www.nuget.org/packages/GraphQL.Relay) | [](https://www.nuget.org/packages/GraphQL.Relay) |
## Usage
### Setup
Add the Nuget package:
```bash
$> dotnet add package GraphQL.Relay
```
Ensure your resolver for GraphQL can resolve:
* `ConnectionType<>`
* `EdgeType<>`
* `NodeInterface`
* `PageInfoType`
If you're using the resolver from MVC (`IServiceProvider`), that might look like this:
```csharp
services.AddTransient(typeof(ConnectionType<>));
services.AddTransient(typeof(EdgeType<>));
services.AddTransient();
services.AddTransient();
```
### GraphTypes
Included are a few GraphQL types and helpers for creating Connections, Mutations, and Nodes
#### `QueryGraphType`
A top level Schema query type, which defines the required `node` root query;
```csharp
public class StarWarsQuery : QueryGraphType
{
public StarWarsQuery() {
Field(
"hero",
resolve: context => new Droid { DroidId = "1", Name = "R2-D2" }
);
}
}
public class StarWarsSchema : Schema
{
public StarWarsSchema() {
Query = new StarWarsQuery();
}
}
```
#### `NodeGraphType`, `NodeGraphType`, `NodeGraphType`
NodeTypes, are `ObjectGraphType`s that implement the [`NodeInterface`](https://facebook.github.io/relay/docs/graphql-object-identification.html#content)
and provide a `GetById` method, which allows Relay (via the `node()` Query) to refetch nodes when it needs to.
Nodes, also provide a convenient `Id()` method for defining global `id` fields, derived from the type `Name` and `Id`.
If your underlying type has a name conflict on the field `id`, the "local" Id will be prefixed with the type name,
e.g. `Droid.Id -> droidId`
```csharp
public class Droid
{
public string DroidId { get; set; }
public string Name { get; set; }
}
public class DroidType : NodeGraphType
{
public DroidType()
{
Name = "Droid";
Id(d => d.DroidId); // adds an id Field as well as the `Droid` id field
Field("name", "The name of the droid.");
}
public override Droid GetById(string droidId) {
return StarWarsData.GetDroidByIdAsync(droidId);
}
}
```
#### Mutations
Relay mutations specify a few constraints on top of the general GraphQL mutations. To accommodate this, there are
mutation specific GraphTypes provided.
#### `MutationGraphType`
The top level mutation type attached to the GraphQL Schema
```csharp
public class StarWarsMutation : MutationGraphType
{
public StarWarsMutation() {
Mutation("createDroid");
Mutation("deleteDroid");
}
}
public class StarWarsSchema : Schema
{
public StarWarsSchema() {
Query = new StarWarsQuery();
Mutation = new StarWarsMutation();
}
}
```
#### `MutationInputGraphType`
An simple base class that defines a `clientMutationId` field. functionally identical to `InputObjectGraphType` otherwise
#### `MutationPayloadGraphType`, `MutationPayloadGraphType`, `MutationPayloadGraphType`
The output ObjectGraphType containing the mutation payload, functionally similar to an `ObjectGraphType` with the
addition of requiring a `MutateAndGetPayload()` method used to resolve the payload from the inputs.
```csharp
public class CreateDroidPayload : MutationPayloadGraphType>
{
public CreateDroidPayload()
{
Name = "CreateDroidPayload";
Field(
name: "droid",
type: typeof(Droid));
}
public override async Task MutateAndGetPayload(MutationInputs inputs)
{
string name = inputs.Get("name");
Droid newDroid = await StarWarsData.CreateDroidAsync(name)
return new DroidPayload {
Droid = newDroid
};
}
}
```
### Connections
Luckily `GraphQL-dotnet` already provides helpful utilities for creating connection fields, on GraphTypes. In addition
included here are a few more helpful methods for creating relay compatible Connections from IEnumerables.
#### `Connection.ToConnection(IEnumerable items, ResolveConnectionContext context)`
Creates a connection from an existing list of objects.
```csharp
public class Droid
{
public string DroidId { get; set; }
public string Name { get; set; }
public IEnumerable Friends { get; set; }
}
public class DroidType : ObjectGraphType
{
public DroidType()
{
Name = "Droid";
Field("name", "The name of the droid.");
Connection()
.Name("friends")
.Resolve(context =>
ConnectionUtils.ToConnection(c.Source.Friends, context));
}
}
```
#### `ConnectionUtils.ToConnection(IEnumerable items, ResolveConnectionContext context, int sliceStartIndex, int totalCount)`
Similar to the above, but creates a connection with the correct cursors, when you only have a slice of the entire set
of items. Windowing the items based on the arguments.
#### `ConnectionUtils.CursorToOffset(string cursor)`
Convert a connection item cursor to the `int` index of the item in the set.
#### `ConnectionUtils.OffsetToCursor(int offset)`
Convert an index offset to a connection cursor.
#### `ResolveConnectionContextExtensions.ToConnection(this IResolveConnectionContext context, IQueryable items)`
Creates a connection from an IQueryable.
```csharp
public class Droid
{
public string DroidId { get; set; }
public string Name { get; set; }
public IQueryable Friends { get; set; }
}
public class DroidType : ObjectGraphType
{
public DroidType()
{
Name = "Droid";
Field("name", "The name of the droid.");
Connection()
.Name("friends")
.Resolve(context => context
.ToConnection(c.Source.Friends));
}
}
```
## Contributors
This project exists thanks to all the people who contribute.

PRs are welcome! Looking for something to work on? The list of [open issues](https://github.com/graphql-dotnet/relay/issues)
is a great place to start. You can help the project by simply responding to some of the [asked questions](https://github.com/graphql-dotnet/relay/issues?q=is%3Aissue+is%3Aopen+label%3Aquestion).