Apollo Federation

"Implement a single data graph across multiple services"

Specification

Scope

Tanka GraphQL implements the service section of the Apollo Federation specification allowing GraphQL service implemented using it to be joined into graph managed by Gateway.

Installation

Support is provided as an NuGet package.

dotnet add package Tanka.GraphQL.Extensions.ApolloFederation

Usage

Creating a service requires two steps:

  1. Define entities in service schema
  2. Create federation service from schema

First step is achived by extending the schema with federation directives which allow you to define your entities. Extending is done by first adding the directives to schema using AddFederationDirectives SchemaBuilder extension method. Use @key directive to mark object or interface as an entity and specify key fields.

Second step is after you have your basic schema with entities specified and it will add the required extension points to schema, mainly additional fields to query root type.

Example

    public static async Task<ISchema> Create()
    {
        var typeDefs = @"
type Review @key(fields: ""id"") {
    id: ID!
    body: String
    author: User @provides(fields: ""username"")
    product: Product
}

type User @key(fields: ""id"") @extends {
    id: ID! @external
    username: String @external
    reviews: [Review]
}

type Product @key(fields: ""upc"") @extends {
    upc: String! @external
    reviews: [Review]
}

type Query {
}
";

        var builder = new ExecutableSchemaBuilder();
        builder.Add(typeDefs);
        builder.AddSubgraph(new(new DictionaryReferenceResolversMap
        {
            ["User"] = UserReference,
            ["Product"] = ProductReference
        }));
        builder.Add(new ResolversMap
        {
            ["User"] = new()
            {
                { "id", ctx => ctx.ResolveAsPropertyOf<User>(u => u.ID) },
                { "username", UserUsername },
                { "reviews", UserReviews }
            },
            ["Review"] = new()
            {
                { "id", ctx => ctx.ResolveAsPropertyOf<Review>(r => r.ID) },
                { "body", ctx => ctx.ResolveAsPropertyOf<Review>(r => r.Body) },
                { "author", ReviewAuthor },
                { "product", ctx => ctx.ResolveAsPropertyOf<Review>(r => r.Product) }
            },
            ["Product"] = new()
            {
                { "upc", ctx => ctx.ResolveAsPropertyOf<Product>(p => p.Upc) },
                { "reviews", ProductReviews }
            }
        });

        var schema = await builder.Build();

        return schema;
    }

Demo

Demo is provided as an fork of the federation demo. It's modified to use Tanka.GraphQL.Dev.Reviews project as an replacement for reviews service.

git clone https://github.com/pekkah/tanka-graphql.git

cd tanka-graphql/dev/GraphQL.Dev.Reviews
dotnet run
git clone https://github.com/pekkah/federation-demo.git
cd federation-demo
git switch tanka-graphql-reviews-service
npm run start-services

# in a yet another prompt
npm run start-gateway

# open http://localhost:4000 in your browser to test the service