An open API service indexing awesome lists of open source software.

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.

Awesome Lists containing this project

README

          

# GraphQL.Relay

![License](https://img.shields.io/github/license/graphql-dotnet/relay)

[![CodeQL analysis](https://github.com/graphql-dotnet/relay/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/graphql-dotnet/relay/actions/workflows/codeql-analysis.yml)

[![codecov](https://codecov.io/gh/graphql-dotnet/relay/branch/master/graph/badge.svg?token=wTEXq34OBT)](https://codecov.io/gh/graphql-dotnet/relay)

![Activity](https://img.shields.io/github/commit-activity/w/graphql-dotnet/relay)
![Activity](https://img.shields.io/github/commit-activity/m/graphql-dotnet/relay)
![Activity](https://img.shields.io/github/commit-activity/y/graphql-dotnet/relay)

![Size](https://img.shields.io/github/repo-size/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 | [![Nuget](https://img.shields.io/nuget/dt/GraphQL.Relay)](https://www.nuget.org/packages/GraphQL.Relay) | [![Nuget](https://img.shields.io/nuget/v/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).